audiovideoffmpeg

Cut a video in between key frames without re-encoding the full video using ffpmeg?


I would like to cut a video at the beginning at any particular timestamp, and it need to be precise, so the nearest key frame is not good enough.

Also, these videos are rather long - an hour or longer - so I would like to avoid re-encoding this altogether if possible, or otherwise only re-encode a minimal fraction of the total duration. Thus, would like to maximise the use of -vcodec copy.

How can I accomplish this using ffmpeg?

NOTE: See scenario, and my own rough idea for a possible solution below.


Scenario:


Rough idea

I know/ can work out the commands for (2) and (3), but am unsure about what commands are needed for (1).


Solution

  • List timestamps of key frames:

    ffprobe -v error -select_streams v:0 -skip_frame nokey -show_entries frame=pkt_pts_time -of csv=p=0 input.mp4
    

    It will output something like:

    0.000000
    2.502000
    3.795000
    6.131000
    10.344000
    12.554000
    16.266000
    ...
    

    Let's say you want to delete timestamps 0 to 5, and then stream copy the remainder. The closest following key frame is 6.131.

    Re-encode 5 to 6.131. Ensure the input and output match attributes and formats. For MP4 default settings should do most of the work, assuming H.264/AAC, but you may have to manually match the profile.

    ffmpeg -i input.mp4 -ss 5 -to 6.131 trimmed.mp4
    

    Make input.txt for the concat demuxer:

    file 'trimmed.mp4'
    file 'input.mp4'
    inpoint 6.131
    

    Concatenate:

    ffmpeg -f concat -i input.mp4 -c copy output.mp4