I would like to take live-captured h.264 video as an input and trim it to start in a fade up from black and end with a fade to black with as little encoding as possible. These fade in/out points may fall between I frames. It is not possible to trim at non-I frames without re-encoding.

I made a diagram:

enter image description here

I would like to split the input file into three parts. Part A would start at the I-Frame before point 1 and end at point 1. Part C would start at the I-Frame at point 2 and end at the next I-Frame after the fade to black. They would be re-encoded into an all I-Frame format. These two segments would be relatively short 10-30 seconds. Part B (most of the video) could just be transcoded using codec:copy.

Parts A & C would be trimmed (either automatically using black detection or manually) and then the entire video would be concatenated using ffmpeg.

I would like to use ffmpeg because that is what I'm most familiar with and the rest of my workflow uses it exclusively. What command lines would achieve this?

For the curious, here is my working command line to capture live video into encoded segments. From this point it is easy to discard unnecessary video, and re-encode segments if needed for trimming. The final step is to concatenate the segments.

ffmpeg -f dshow -rtbufsize 702000k -video_size 1920x1080 -framerate 29.97 -pixel_format uyvy422 -i video="Decklink Video Capture":audio="Decklink Audio Capture" -threads 0 -c:v libx264 -s 1280x720 -crf 18 -profile:v main -level 3.1 -pix_fmt yuv420p -c:a libvo_aacenc -b:a 128k -ac 1 -f segment -segment_time 0.01 -reset_timestamps 1 seg%02d.mp4
  • You can replace 29.97 with the exact 30000/1001. – Gyan Feb 14 '16 at 14:30

This can be achieved using the segment muxer and concat demuxer.

Step 1 Segment the input

Suppose you wish to extract 00:50 to 02:20 from the captured source. Let's say the GOP size is 3 seconds. Since your in-point may be the last frame of a GOP, we need to start one GOP length earlier. So, trim start is 00:47 and extract duration is 01:33. So,

ffmpeg -ss 0:47 -t 01:33 -i input.mp4 -c copy -f segment -segment_time 0.01 -reset_timestamps 1 seg%02d.mp4

This will create segments, each one GOP long. So, don't use this for intra-coded streams :)

Step 2 Trim the head and tail segments

Delete any superfluous segments at the head and tail - possible if GOP length is small. Then trim the correct top and tail segments:

ffmpeg -ss 2 -i seg00.mp4 -crf 18 -map [v] -map [a] seg00a.mp4

ffmpeg -t 2 -i seg46.mp4  -crf 18 -map [v] -map [a] seg46a.mp4

Step 3 Concat

a) Prepare concat file segments.txt

file 's00a.mp4'
file 's01.mp4'
file 's02.mp4'
file 's44.mp4'
file 's45.mp4'
file 's46a.mp4'


ffmpeg -f concat -i segments.txt -c copy -fflags +genpts trimmed.mp4

Since you're working on a live capture, you can output to TS instead of MP4, except for the final output.

  • First off, thank you for the speedy response! Please correct me if I'm not understanding this, but I'm not sure this does what I am trying to do. I am not trying to apply fade-in and fade-outs I am trying to trim to pre-existing ones. The ins and outs in my source video can be very tight. Segmenting may still help me, and I'm reading up on it right now. Thanks! – HGBells Feb 12 '16 at 19:17
  • Then skip the fade filters in Step 2. See edited command. – Gyan Feb 12 '16 at 19:19
  • EDIT: Nevermind, I see. I think this will work! – HGBells Feb 12 '16 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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