FFmpeg concat video and audio out of sync

前端 未结 5 1409
死守一世寂寞
死守一世寂寞 2020-12-13 14:37

Joining multiple files using ffmpeg concat seems to result in a mismatch of the timestamps or offsets for the audio. I\'ve tried with several videos and noticed the same pro

5条回答
  •  自闭症患者
    2020-12-13 15:01

    If the input videos have been encoded with the same settings, you may be able to use mkvmerge from mkvtoolnix instead:

    mkvmerge -o output.mkv file1.mkv + file2.mkv + file3.mkv
    

    I needed to concatenate videos from different sources that were encoded with different settings, so I used a command like this to resize and re-encode the input videos first:

    for f in *.mp4; do
      width=1280;
      height=720;
      ffmpeg -i $f \
        -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih),
                 pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:
                                    ($height-ih*min($width/iw\,$height/ih))/2" \
        -c:v libx264 -crf 22 -preset slow -pix_fmt yuv420p \
        -c:a libfdk_aac -vbr 3 -ac 2 -ar 44100 ${f%mp4}mkv;
    done
    

    Some of the videos did not have an audio channel, so I had to use a command like this to add a silent audio channel to them:

    for f in *.mkv; do
      ffprobe $f |& grep -q '1: Audio' || {
        ffmpeg -i $f -f lavfi -i anullsrc -c:a libfdk_aac -shortest -c:v copy tmp-$f;
        mv tmp-$f $f;
      };
    done
    

    I then concatenated the videos using a command like this:

    mkvmerge -o output.mkv $(printf %s\\n *.mkv|sed '1!s/^/+/')
    

    This section was added on 14 Jun 2020 for the error "Unknown encoder 'libfdk_aac'"

    libfdk_aac isnt compatible with the GPL, and therefore not often made available by distributors

    Encoder aac can be used instead of encoder libfdk_aac as in the code below

    for f in *.mp4; do
      width=1280;
      height=720;
      ffmpeg -i $f \
        -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih),
                   pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:
                                      ($height-ih*min($width/iw\,$height/ih))/2" \
        -c:v libx264 -crf 22 -preset slow -pix_fmt yuv420p \
        -c:a aac -vbr 3 -ac 2 -ar 44100 ${f%mp4}mkv;
    done
    
    for f in *.mkv; do
      ffprobe $f |& grep -q '1: Audio' || {
        ffmpeg -i $f -f lavfi -i anullsrc -c:a aac -shortest -c:v copy tmp-$f;
        mv tmp-$f $f;
      };
    done
    

提交回复
热议问题