fix: Wails file drop, duplicate listeners, trim drag, crop stage, preview cache/pixfmt, NSIS temp quoting
Build Windows Installer / build (push) Successful in 8m46s

This commit is contained in:
m4xx1m committed 2026-11-12 18:04:53 +03:00
1 parent 65387c5dcd
commit 478dbff654
12 files changed
+563 -226

No files matched your search

+18 -5
View File
@@ -22,6 +22,8 @@ import (
type Server struct {
addr string
httpSrv *http.Server
ctx context.Context
cancel context.CancelFunc
ffmpegBin string
mu sync.RWMutex
files map[string]registeredFile
@@ -41,8 +43,11 @@ func Start(ffmpegBin string) (*Server, error) {
return nil, err
}
ctx, cancel := context.WithCancel(context.Background())
s := &Server{
addr: ln.Addr().String(),
ctx: ctx,
cancel: cancel,
ffmpegBin: ffmpegBin,
files: make(map[string]registeredFile),
proxyLocks: make(map[string]*sync.Mutex),
@@ -78,7 +83,12 @@ func (s *Server) BaseURL() string {
}
func (s *Server) Register(info *media.VideoInfo) string {
sum := sha1.Sum([]byte(info.Path))
var modUnix int64
if st, err := os.Stat(info.Path); err == nil {
modUnix = st.ModTime().UnixNano()
}
key := fmt.Sprintf("%s|%d|%d", info.Path, info.SizeBytes, modUnix)
sum := sha1.Sum([]byte(key))
id := hex.EncodeToString(sum[:8])
s.mu.Lock()
@@ -88,6 +98,9 @@ func (s *Server) Register(info *media.VideoInfo) string {
}
func (s *Server) Close() {
if s.cancel != nil {
s.cancel()
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
if s.httpSrv != nil {
@@ -166,7 +179,7 @@ func (s *Server) handleProxy(w http.ResponseWriter, r *http.Request) {
if proxyPath == "" {
proxyPath = filepath.Join(os.TempDir(), fmt.Sprintf("convert_preview_%s.mp4", cacheKey))
if err := s.buildProxy(r.Context(), ffmpegBin, rf.info, merge, proxyPath); err != nil {
if err := s.buildProxy(s.ctx, ffmpegBin, rf.info, merge, proxyPath); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
@@ -211,8 +224,8 @@ func (s *Server) buildProxy(ctx context.Context, ffmpegBin string, info *media.V
args = append(args, "-map", "0:v:0", "-map", "0:a:0", "-c:a", "aac", "-b:a", "128k")
}
if info.VideoCodec == "h264" {
// Remux video stream instantaneously when codec is already H.264
if info.VideoCodec == "h264" && media.IsH264BrowserNativePixFmt(info.PixFmt) {
// Remux video stream instantaneously when codec is already browser-native 8-bit H.264
args = append(args, "-c:v", "copy")
} else {
args = append(args,
@@ -220,7 +233,7 @@ func (s *Server) buildProxy(ctx context.Context, ffmpegBin string, info *media.V
"-preset", "ultrafast",
"-crf", "26",
"-pix_fmt", "yuv420p",
"-vf", "scale='min(1280,iw)':-2",
"-vf", "scale='min(1280,trunc(iw/2)*2)':-2",
)
}
args = append(args, "-movflags", "+faststart", outPath)
+55
View File
@@ -3,6 +3,7 @@ package preview
import (
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"testing"
@@ -85,3 +86,57 @@ func TestPreviewServer_RangeThumbAndProxy(t *testing.T) {
t.Fatalf("expected 404, got %d", nfResp.StatusCode)
}
}
func TestPreviewServer_CacheInvalidationAndOddWidthProxy(t *testing.T) {
bins := media.FindBinaries("", "")
if bins.FFmpeg == "" || bins.FFprobe == "" {
t.Skip("ffmpeg/ffprobe not installed")
}
tmpDir := t.TempDir()
src := filepath.Join(tmpDir, "odd.mkv")
// Odd width (321x180) vp8 source forces libx264 transcode in /proxy
gen := exec.Command(bins.FFmpeg,
"-hide_banner", "-loglevel", "error",
"-f", "lavfi", "-i", "testsrc=duration=1:size=321x180:rate=30",
"-c:v", "libvpx", "-y", src,
)
if out, err := gen.CombinedOutput(); err != nil {
t.Fatalf("failed generating odd-width mkv: %v (%s)", err, string(out))
}
info, err := media.Probe(bins.FFprobe, src)
if err != nil {
t.Fatalf("probe failed: %v", err)
}
srv, err := Start(bins.FFmpeg)
if err != nil {
t.Fatalf("start failed: %v", err)
}
defer srv.Close()
id1 := srv.Register(info)
// /proxy must succeed even on odd width (321 -> 320)
pResp, err := http.Get(srv.BaseURL() + "/proxy?id=" + id1 + "&merge=0")
if err != nil {
t.Fatalf("GET /proxy failed: %v", err)
}
pBody, _ := io.ReadAll(pResp.Body)
pResp.Body.Close()
if pResp.StatusCode != http.StatusOK || len(pBody) < 500 {
t.Fatalf("expected valid MP4 proxy for odd-width source, status=%d len=%d", pResp.StatusCode, len(pBody))
}
// Overwrite same path with different size -> Register must yield a new ID
if err := os.WriteFile(src, []byte("different-content-size"), 0o644); err != nil {
t.Fatalf("overwrite failed: %v", err)
}
info2 := *info
info2.SizeBytes = 22
id2 := srv.Register(&info2)
if id1 == id2 {
t.Fatalf("expected different videoId after file modification at same path, both were %q", id1)
}
}