0

I am trying to scale down a video (mp4 format) by using the following process :

  1. Segment the video
ffmpeg -v quiet -i <input-file> -map 0 -c copy -f segment -segment_time <segment_length> -reset_timestamps 1 -avoid_negative_ts make_non_negative output_%03d.mp4 
  1. Scale down each segment parallelly
ls output_*.mp4 |  parallel ffmpeg -v quiet -i {} -vf scale=-2:<output-resolution> temp_{#}.mp4
  1. Join segments to get back whole video
for i in temp_*.mp4; do echo file "$i"; done > concat.txt
ffmpeg -v quiet -f concat -i concat.txt -codec copy <output-file>

However, the final output contains small audio gaps. Consider segment length of 15s, then at roughly 15.28s there is a gap in the audio stream as shown in the waveform of audio below.

Audio waveform

The green part highlights the waveform of the audio generated by scaling down the video using this command :

ffmpeg -v quiet -i <input-file> -vf scale=-2:<output-resolution> <output-file>

The yellow part highlights the waveform of the audio scaled down using the segmenting process described earlier.

One approach I could think of is to work on the video stream only while segmenting and copy the audio stream from the input file directly to the output file. But again it might lead to audio sync issues. How do I solve this ?

I am using ffmpeg version git-2020-03-03-60b1f85 in Windows 10.

Please note that I don't want to re-encode the video because this will defeat the purpose of segmenting in the first place (in terms of time taken).

1

It is not the video scaling, that produces the gaps, but it is the process of splitting and joining while killing the timestamps.

This is quite a usual problem in the broadcast industry, and we typically solve it this way:

  • split audio and video, in the process using the hls segmenter with a segment list file
  • do parallel video processing of the segemnts without changes to the timestamps and audio processing i/a
  • rejoin audio and video by pointing ffmpeg to the segment list file, not a concat file

EXAMPLES

Split:

ffmpeg -y -i ... -dn -sn -an -c:v copy -bsf:v h264_mp4toannexb -copyts -start_at_zero -f segment -segment_list /path/to/output.m3u8 -segment_time 30 /path/to/folder/para%05d.ts -dn -sn -vn -c:a copy /path/to/audiofile

Rejoin:

ffmpeg -y -i /path/to/output.m3u8 -i /path/to/audiofile -map '0:v' -map '1:a' -c:a copy -c:v copy /path/to/output.mp4
  • Thank you for the answer, What is i/a in the second point? – Saurabh P Bhandari Mar 26 at 12:04
  • If possible please provide an example, it will be very helpful – Saurabh P Bhandari Mar 26 at 16:01
  • i/a is "if applicable" ... if you just copy the audio it is nothing, but if you need to e.g. recompress or normalize audio you can do it inparallel to the video processing. – Eugen Rieck Mar 27 at 8:45
  • The rejoin command gives an error : Invalid stream specifier: '0:v'. If I remove the map options, it executes but says Packet corrupt when reading each ts file – Saurabh P Bhandari 2 days ago
  • 1
    That seams to be a bug in your version of ffmpeg, I copy-pasted the line from our own reencode servers (and I would know immediately if they wouldn't work). Since only one of the streams contains a video stream and only one an audio stream, the -map parameters are not strictly necessary. – Eugen Rieck 2 days ago

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.