7

I am trying to create small clips from video file using ffmpeg3. The type of clip and video will be same i.e. mp4 to mp4 only. Below is command, which is being used for same.

ffmpeg -ss 00:07:00.000 -t 0:00:02.000 -i source.mp4 -codec copy -y output.mp4

The duration for clips generated is not same, they always have additional seconds with them i.e. 4,5 or 6 seconds. I have tried this on multiple videos and behavior is same.

Since, the output and input type is same. So I am not using any encoding or decoding, as it will be time consuming process.

Please share suggestions on same.

3
  • 4
    For videos with codecs that use temporal compression, it's not possible All frames that are required for decoding will be included in the output. So, if your inpoint isn't a keyframe, output duration will be longer. You need to re-encode to be assured of output duration.
    – Gyan
    Commented Feb 10, 2018 at 18:50
  • You are right, we need to re-encode Commented Feb 16, 2018 at 19:48
  • correct, I was using -c copy while creating a clip from MKV using ffmpeg. When clip duration is small like 2seconds or 10 seconds then it was not picking up video stream. When duration is bigger like 35econds or 1minute then it produces audio+video streams in output file. Now, I have removed -c copy so it re-encodes and even 1second. 2second clips are fine now. thanks bunch!
    – Pranav
    Commented Oct 5, 2019 at 16:13

2 Answers 2

5

The help for seeking using ffmpeg explains the problem.

Seeking while doing a codec copy

Using -ss as input option together with -c:v copy might not be accurate since ffmpeg is forced to only use/split on i-frames. Though it will—if possible—adjust the start time of the stream to a negative value to compensate for that. Basically, if you specify "second 157" and there is no key frame until second 159, it will include two seconds of audio (with no video) at the start, then will start from the first key frame. So be careful when splitting and doing codec copy.

If you transcode (not copy) then:

As of FFmpeg 2.1, when transcoding with ffmpeg (i.e. not just stream copying), -ss is now also "frame-accurate" even when used as an input option.

Your options are:

  • Accept splits on i-frames and work with the output as-is, based on the options used. This is what you have now.

  • Recompress:

    Fast Input Seeking: The -ss parameter needs to be specified somewhere before -i. The input will be parsed using keyframes, which is very fast.

    ffmpeg -ss 00:23:00 -i Mononoke.Hime.mkv -frames:v 30 out1.mkv

    Slow Output Seeking: The -ss parameter needs to be specified after -i. This will be done very slowly, frame by frame. As of FFmpeg 2.1, the main advantage is that when applying filters to the output stream, the timestamps aren't reset prior to filtering (i.e. when ​burning subtitles into a video, you don't need to modify the subtitle timestamps), but the drawback is that it will take a lot of time until it finally reaches that time point.

    ffmpeg -i Mononoke.Hime.mkv -ss 00:23:00 -frames:v 30 out2.mkv

  • Adjust the start time forward so that when it ends on an i-frame the total duration is close to the desired duration.

    Slow Combined Seeking: For this we specify the -ss parameter before and after -i. This approach uses keyframes to seek until 00:22:30, and then seeks frame-by-frame until it reaches 00:00:30 (00:22:30 + 00:00:01), continue increasing the second -ss option until the duration is short enough; unfortunately you'll lose an exact start and end time and the duration may only be approximately close to the desired amount.

    ffmpeg -ss 00:22:30 -i Mononoke.Hime.mkv -ss 00:00:01 -frames:v 30 out3.mkv

    Note: Cutting small sections

    To extract only a small segment in the middle of a movie, it can be used in combination with -t which specifies the duration, like -ss 60 -t 10 to capture from second 60 to 70. Or you can use the -to option to specify an out point, like -ss 60 -to 70 to capture from second 60 to 70. -t and -to are mutually exclusive. If you use both, -t will be used.

    If you specify -ss before -i only, the timestamps will be reset to zero, so -t and -to have not the same effect. If you want to keep the original timestamps, add the -copytsoption.

    Cut from 00:01:00 to 00:03:00 (in the original), using the faster seek:

      ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy cut.mp4
    

    Cut from 00:01:00 to 00:02:00, as intended, using the slower seek:

      ffmpeg -i video.mp4 -ss 00:01:00 -to 00:02:00 -c copy cut.mp4
    

    Cut from 00:01:00 to 00:02:00, as intended, using the faster seek:

      ffmpeg -ss 00:01:00 -i video.mp4 -to 00:02:00 -c copy -copyts cut.mp4
    

    If you cut with stream copy (-c copy) you need to use the -avoid_negative_ts 1 option if you want to use that segment with the ​concat demuxer. Example:

      ffmpeg -ss 00:03:00 -i video.mp4 -t 60 -c copy -avoid_negative_ts 1 cut.mp4
    

    Valid values for the avoid_negative_ts variable are:

    avoid_negative_ts integer (output)

    ‘make_non_negative’
    
    Shift timestamps to make them non-negative. Also note that this affects only 
    leading negative timestamps, and not non-monotonic negative timestamps. 
    
    ‘make_zero’
    
    Shift timestamps so that the first timestamp is 0. 
    
    ‘auto’ (default)
    
    Enables shifting when required by the target format. 
    
    ‘disabled’
    
    Disables shifting of timestamp. 
    
    When shifting is enabled, all output timestamps are shifted by the same 
    amount. Audio, video, and subtitles desynching and relative timestamp
    differences are preserved compared to how they would have been without 
    Shifting. 
    
0

So looked into ffmpeg documentation and found that by changing position of -ss decodes and then creates the clip, which is way more faster than command posted in question

ffmpeg -i source.mp4 -ss 0:14:42.000 -codec copy -t 0:00:02.000 -y output.mp4
3
  • 1
    Since you're copying, it doesn't matter, since there's no decoding but it's the other way around. ss before i is much faster,
    – Gyan
    Commented Feb 17, 2018 at 6:34
  • It does decoding, but it does not tries to re-encode. Please see documentation. Commented Feb 17, 2018 at 7:16
  • 1
    If frames were decoded, then they would be saved as raw uncompressed frames, if not re-encoded. That's not what happens with -codec copy.
    – Gyan
    Commented Feb 17, 2018 at 7:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.