FFmpeg can find the cuts in a video with the scdet filter, or with the scene value of the select filter.

Basic Command

ffmpeg -i input.mp4 \
  -vf "scdet=t=10,metadata=mode=print:key=lavfi.scd.score" \
  -f null /dev/null

-f null /dev/null means no output file is written. metadata=print prints the score of every frame to stderr. On each frame that scdet judges to be a cut, scdet also prints its own line with lavfi.scd.score and lavfi.scd.time.

Reading the Output

[Parsed_metadata_1 @ 0x...] frame:149  pts:76288   pts_time:4.966667
[Parsed_metadata_1 @ 0x...] lavfi.scd.score=0.131
[Parsed_scdet_0 @ 0x...] lavfi.scd.score: 25.146, lavfi.scd.time: 5
[Parsed_metadata_1 @ 0x...] frame:150  pts:76800   pts_time:5
[Parsed_metadata_1 @ 0x...] lavfi.scd.score=25.146
Field Description
lavfi.scd.score Scene-change score (higher = larger change)
lavfi.scd.time Timestamp of the detection (seconds)

Tuning threshold

Parameter Default Description
t / threshold 10 Scores at or above this value are reported as scene changes
ffmpeg -i input.mp4 -vf "scdet=t=20" -f null /dev/null
  • Low value (for example 5): small changes are detected too, so you get more false detections
  • High value (for example 40): only clear cuts are detected, so more cuts are missed
  • For documentaries and films, start with 8–14

Save a Frame at Every Scene Change

To save a still image at each cut, use the select filter:

ffmpeg -i input.mp4 -vf "select='gt(scene,0.35)'" -fps_mode vfr scene_%04d.png

Note: select computes its own scene value. It uses a different scale from scdet’s lavfi.scd.score, so tune the two thresholds separately.

ffmpeg -i input.mp4 -vf "scdet=t=10,metadata=print" -f null /dev/null

Threshold Suggestions by Content Type

The FFmpeg documentation suggests values between 8 and 14. Start with the default, 10. Raise it if busy footage gives false hits, and lower it if cuts are missed.

Caveats

Fades and Dissolves Are Hard to Detect

Hard cuts (instant changes) are detected reliably. Fades and dissolves (gradual changes) differ little from one frame to the next, so scdet often misses them.

Long Videos Take Time

Scene detection decodes every frame, so long videos take a while to analyze. To analyze only part of a video, limit it with -ss and -to.

Measured: time and size

The timing below is for this command:

ffmpeg -i input.mp4 -vf "scdet=t=12,metadata=mode=print:key=lavfi.scd.time" -f null -
Measured
Time 7.09 s (16.92x realtime)
Output file none — analysis only

Test setup: a 1920x1080, 30 fps, 120 s, 351.4 MB H.264 source (Big Buck Bunny, looped, CC BY 3.0), a Core i9-14900KF (32 threads) and FFmpeg 8.1 (gyan.dev build), measured on 2026-09-05. The raw numbers are in the dataset.

Why 7.09 seconds

No output file is created. -f null - decodes every frame, passes it through scdet, and then discards it without encoding or writing anything. For comparison, a plain H.264 re-encode of the same clip on the same machine, with no filter (-c:v libx264 -crf 23 -preset medium), took 27.97 s. The difference is the encoder, which does not run here.

Commands that never decode a video frame finish in about a second: stream mapping took 0.41 s, moving the moov atom 0.49 s, and an audio fade 1.03 s. They copy the video stream unchanged (the audio fade re-encodes only the audio). scdet sits in between: it decodes every frame but encodes nothing.

The speed of 16.92x realtime on 32 threads applies to 1080p 8-bit H.264 read from a local disk. 4K or 10-bit HEVC is much slower to decode. This run read the file at about 50 MB/s (351.4 MB in 7.09 s), so a network connection slower than that becomes the limit before the CPU does.

The 7.09 s run wrote no images. Saving each detected scene as a PNG adds image encoding and disk writes to that time. If you use the detected times as edit points, leave 0.2–0.5 seconds of padding. Scene detection only looks at the picture and knows nothing about the timing of the audio or subtitles.

Frequently Asked Questions

What threshold should I use for scene detection?

Start with select='gt(scene,0.35)' for clear cuts. Lower it to 0.25–0.3 for fast-cut content, or raise it to 0.45–0.5 to catch only hard cuts. This scale is different from scdet’s t value.

How do I export the timestamps to a file?

Run ffmpeg -i in.mp4 -filter:v "select='gt(scene,0.4)',showinfo" -f null - 2> scenes.log, then search the log for pts_time (for example with grep).

Why does scene detect miss obvious cuts?

Cross-fades and flash cuts can stay below the threshold. To catch fades to black that work as cuts, combine scene detection with blackdetect.

Can I split the video at every detected scene automatically?

Yes. Feed the timestamps to a script that runs ffmpeg -ss A -to B -i input.mp4 -c copy partN.mp4 for each detected range. Because -c copy does not re-encode, a part can start at the keyframe before A. For frame-accurate cuts, drop -c copy and re-encode.

Does scene detect work on animation?

Yes, but adjust the threshold. Animation has large areas of flat colour, so with select, lower the scene threshold to 0.25–0.3 to catch real cuts. scdet’s t uses a different scale; start from the default, 10, and adjust from there.