mirror of
https://github.com/calesthio/OpenMontage.git
synced 2026-09-12 06:23:56 +08:00
45f45855da
_extract_video_frames built `-vf thumbnail=N -frames:v N` when no explicit
frame_indices were given. That reads as even sampling and is not: thumbnail=N
selects the most representative frame out of each consecutive N-frame BATCH, so
paired with -frames:v N it stops once N frames have been emitted and never
looks at the rest of the video.
Reproduced against a four-second fixture, solid red for 2s then solid blue
for 2s:
ffmpeg -i clip.mp4 -frames:v 4 -vf "thumbnail=4" out_%04d.png
-> frame_0001 (254,0,0) frame_0002 (254,0,0)
frame_0003 (254,0,0) frame_0004 (254,0,0)
Every sample lands in the first half. The blue half of the clip is invisible,
and because the failure produces four perfectly valid frames the caption pass
has no way to know: it described the clip as one in which nothing changes.
Sampling is now timestamp-driven. Duration comes from ffprobe and one frame is
taken at duration*(i+0.5)/n — inside each slice rather than on its edge, so a
cut landing exactly on a boundary does not sample the frame before or after it
depending on rounding. -ss goes ahead of -i to seek by keyframe, which is fast
and accurate enough for sampling that was never frame-exact.
Same fixture, after:
frame 0 (254,0,0) frame 1 (254,0,0) frame 2 (0,0,255) frame 3 (0,0,255)
Three behaviours preserved deliberately:
* The explicit frame_indices branch is untouched. It was already correct.
* No duration — a stream, or no ffprobe on PATH — falls back to an even pass
over the file rather than returning an empty list.
* A zero or negative duration is treated as unknown, since it would otherwise
divide the sampler by zero.
Also drops probe_cmd, which was assigned and never used.
tests/tools/test_video_understand_sampling.py adds 9 cases with subprocess.run
faked, so they assert the commands built rather than one ffmpeg build's output,
and fail if `thumbnail=` returns. tests/tools/ is 490 passed, 1 skipped.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>