7

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:

  • Original video
    • Length of 1:00:00
    • Has a key frame every 10s
  • Desired cut:
    • From 0:01:35 through till the end
  • Attempt #1:
    • Using -ss 0:01:35 -i blah.mp4 -vcodec copy, what results is a file where:
    • audio starts at 0:01:30
    • video also starts at 0:01:30
    • this starts both the audio and the video too early
  • using -i blah.mp4 -ss 0:01:35 -vcodec copy, what results is a file where:
    • audio starts at 0:01:35,
    • but the video is blank/ black for the first 5 seconds,
      • until 0:01:40, when the video starts
    • this starts the audio on time, but the video starts too late

Rough idea

  • (1) cut 0:01:30 to 0:01:40
    • re-encode this to have new key frames, including one at the target time of 0:01:35
    • then cut this to get the 5 seconds from 0:01:35 through 0:01:40
  • (2) cut 0:01:40 through till the end
    • without re-encoding, using -vcodec copy
  • (3) ffmpeg concat the first short clip (the 5 second one) with the second long clip

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

stib
  • 2,729
  • 2
  • 23
  • 33
bguiz
  • 22,661
  • 40
  • 140
  • 226
  • Note that using edit lists with mp4 container is not an option in my case because of target video players, as well as subsequent steps that I have in post-processing this video – bguiz Aug 24 '20 at 02:03
  • This can help - https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg – Vijayendra Sep 01 '20 at 12:30
  • For specifying the keyframe interval (GOP size), use the `-g` flag. https://trac.ffmpeg.org/wiki/EncodingForStreamingSites – francis duvivier Sep 01 '20 at 15:04

2 Answers2

8

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
llogan
  • 87,794
  • 21
  • 166
  • 190
  • 1
    this looks like something that fits what I'm asking. I followed the link to matching the profile in your answer, but couldn't work out how to use that. what would your `ffmpeg` command that outputs the trimmed file be when doing that. something like `-v:profile copy` perhaps? – bguiz Aug 27 '20 at 06:19
  • 1
    @bguiz Look at input with ffmpeg and look for `Video: h264 (High)`. The `()` may contain Baseline or Main instead of High. If that's the case add `-profile:v main` or `-profile:v baseline`. You don't need to do anything extra if it is High. Or use ffprobe to find profile: `ffprobe -v error -select_streams v -show_entries stream=profile -of csv=p=0 input.mp4`. Not all formats have profiles. – llogan Aug 27 '20 at 16:50
2

try

ffmpeg -i src.mp4 -vcodec copy -reset_timestamps 1 -map 0 out.mp4

or

ffmpeg -i src.mp4 -vcodec copy -reset_timestamps 1 -map 0 src_.m3u8

which generates hls playlists

bguiz
  • 22,661
  • 40
  • 140
  • 226
krishna
  • 51
  • 7