Add video as a media kind in photos: streaming upload with per-kind limits, ffprobe metadata, poster frame reusing the image variant pipeline, and a playback object (remux when web-compatible, else h264/yuv420p/aac transcode). Video jobs run on a separate pool with a long lease. Frontend gains a video viewer, grid badge/duration and video upload.
74 lines
1.8 KiB
Go
74 lines
1.8 KiB
Go
package video
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func argsContain(args []string, want ...string) bool {
|
|
for _, w := range want {
|
|
found := false
|
|
for _, a := range args {
|
|
if a == w {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func TestRemuxArgs(t *testing.T) {
|
|
args := RemuxArgs("in.mkv", "out.mp4")
|
|
if !argsContain(args, "-c", "copy", "-movflags", "+faststart", "-map", "0:a:0?") {
|
|
t.Fatalf("remux args = %v", args)
|
|
}
|
|
}
|
|
|
|
func TestTranscodeArgs(t *testing.T) {
|
|
args := TranscodeArgs("in.mov", "out.mp4", MaxLongSide)
|
|
if !argsContain(args, "libx264", "yuv420p", "aac", "-movflags", "+faststart") {
|
|
t.Fatalf("transcode args = %v", args)
|
|
}
|
|
var scale string
|
|
for i, a := range args {
|
|
if a == "-vf" && i+1 < len(args) {
|
|
scale = args[i+1]
|
|
}
|
|
}
|
|
if !strings.Contains(scale, "min(1920,iw)") || !strings.Contains(scale, "force_divisible_by=2") {
|
|
t.Fatalf("scale filter = %q", scale)
|
|
}
|
|
}
|
|
|
|
func TestPosterArgs(t *testing.T) {
|
|
args := PosterArgs("in.mp4", "poster.jpg", 1)
|
|
if !argsContain(args, "-ss", "1", "-frames:v", "1", "-f", "image2") {
|
|
t.Fatalf("poster args = %v", args)
|
|
}
|
|
}
|
|
|
|
func TestRun(t *testing.T) {
|
|
dir := t.TempDir()
|
|
ok := filepath.Join(dir, "ok")
|
|
if err := os.WriteFile(ok, []byte("#!/bin/sh\nexit 0\n"), 0o755); err != nil {
|
|
t.Fatalf("write ok: %v", err)
|
|
}
|
|
if err := Run(context.Background(), ok, "-i", "x"); err != nil {
|
|
t.Fatalf("run ok: %v", err)
|
|
}
|
|
bad := filepath.Join(dir, "bad")
|
|
if err := os.WriteFile(bad, []byte("#!/bin/sh\necho nope >&2\nexit 3\n"), 0o755); err != nil {
|
|
t.Fatalf("write bad: %v", err)
|
|
}
|
|
if err := Run(context.Background(), bad); err == nil || !strings.Contains(err.Error(), "nope") {
|
|
t.Fatalf("run bad err = %v, want stderr captured", err)
|
|
}
|
|
}
|