Stop ffprobe walking every frame in video stream probe

probe_video_stream_meta requested a bare `side_data_list` section in
-show_entries. On modern ffprobe that's the *frame* side-data section,
so ffprobe enumerated every frame to collect it — reading the entire
mdat. For non-faststart phone clips on the SMB mount this turned a
metadata probe into a full-file read: /video/generate took 10-32s per
open (0% CPU, time proportional to file size).

Switch to `stream_side_data_list`, which reads the Display Matrix
rotation from the stream header (moov) without touching frames. Codec,
frame rate, and rotation are unchanged; the existing rotation parser
already reads streams[0].side_data_list[].rotation. Fixes both the
open-path probe and the transcode actor's probe. Cold opens now return
near-instantly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cameron Cordes
2026-05-30 13:19:47 -04:00
parent 16ae82ba70
commit b9b6e51af1
+9 -1
View File
@@ -159,8 +159,16 @@ pub async fn probe_video_stream_meta(video_path: &str) -> VideoStreamMeta {
.arg("v:0")
.arg("-print_format")
.arg("json")
// NOTE: request `stream_side_data_list` (stream-level side data, read
// from the moov atom), NOT the bare `side_data_list` section. On modern
// ffprobe the latter is the *frame* side-data section, which forces
// ffprobe to enumerate every frame — reading the entire mdat over the
// network. For non-faststart phone clips on an SMB mount that turned a
// metadata probe into a full-file read (tens of seconds per open). The
// Display Matrix rotation we need is present at stream level, so this
// keeps codec/fps/rotation while reading only the header.
.arg("-show_entries")
.arg("stream=codec_name,r_frame_rate,avg_frame_rate:stream_tags=rotate:side_data_list")
.arg("stream=codec_name,r_frame_rate,avg_frame_rate:stream_tags=rotate:stream_side_data_list")
.arg(video_path)
.output()
.await;