files: seek anywhere in a re-encode; it restarts from there

A re-encode's playlist is now the whole film on a fixed 4 s grid. A segment
that isn't on disk and isn't coming soon moves the encode there; runs stop
short of segments already made, and gaps are filled after. Every run is cut
the same way (-ss, -output_ts_offset start+10, frag_discont), so segments
from different runs join. Repackaging keeps its growing playlist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-10-20 13:08:52 -07:00
co-authored by Claude Opus 5.5
parent ff1373e838
commit 450a9d3327
8 changed files with 660 additions and 45 deletions
+29
View File
@@ -110,6 +110,35 @@ func TestHLSArgs(t *testing.T) {
}
}
func TestSegArgs(t *testing.T) {
in := src("h264", 1920, 1080, 25)
r := recipes(gridCaps(), "h264", in, 1920, 1080, 10000)[0]
first := strings.Join(segArgs("/d", "/v.mkv", in, r, 0, 900, 900, "init.mp4"), " ")
for _, want := range []string{"-ss 0 -i /v.mkv", "-output_ts_offset 10", "-start_number 0", "movflags=+frag_discont", "-hls_fmp4_init_filename init.mp4", "-hls_segment_filename /d/seg%05d.m4s", "/d/run.m3u8", "-force_key_frames expr:gte(t,n_forced*4)"} {
if !strings.Contains(first, want) {
t.Errorf("first run: missing %q in\n%s", want, first)
}
}
if strings.Contains(first, " -t ") {
t.Error("a run to the end has no -t")
}
// a seek: segments 30..44, stopping half a frame short of 45, which is on disk
seek := strings.Join(segArgs("/d", "/v.mkv", in, r, 30, 45, 900, "init-run.mp4"), " ")
for _, want := range []string{"-ss 120 -i /v.mkv", "-t 59.980", "-output_ts_offset 130", "-start_number 30", "-hls_fmp4_init_filename init-run.mp4"} {
if !strings.Contains(seek, want) {
t.Errorf("seek run: missing %q in\n%s", want, seek)
}
}
if strings.Index(seek, "-ss 120") > strings.Index(seek, "-i /v.mkv") || strings.Index(seek, "-hwaccel") > strings.Index(seek, "-i /v.mkv") {
t.Error("-ss and the decoder's options go before -i")
}
for d, n := range map[float64]int{9: 3, 8.2: 2, 8.31: 3, 64: 16, 0.1: 1, 3600: 900} {
if got := segCount(d); got != n {
t.Errorf("segCount(%v) = %d, want %d", d, got, n)
}
}
}
func TestParseProgress(t *testing.T) {
b := []byte("frame=10\nout_time_us=1000000\nspeed=2.5x\nprogress=continue\nframe=20\nout_time_us=2500000\nspeed=3.1x\nprogress=continue\n")
s, sp := parseProgress(b)