Fixing audio sync with FFMPEG


Yesterday a client asked me if there was anything I could do with a piece of video they had produced in which the audio was out sync with the video. Normally when I come across this kind of problem is you get the audio happen after seeing the images move. But this one was the other way around.

I’d usually solve the first problem with the -itsoffset option in ffmpeg but this proved to be more troublesome then usual as a negative value didn’t have any effect. To solve this I used the -ss option, this basically skips the next input file forward. By doing this I was able move the audio input forward by a few seconds and sync it with the video. The full command is below

ffmpeg 
 -ss 00:00:00 -i inputfile.avi
 -ss 00:00:02 -i inputfile.avi
 -map 0:0 -map 1:1
 -vcodec libx264
 -acodec libfaac -ac 6 -ab 384k -ar 48000
 outputfile.avi

In this i’m specifying the input file twice using the -i option. Before each one i’m putting the -ss option which offsets the following input. Now because ffmpeg has 2 inputs (using the same source) it doesn’t know which is the video and which is the audio. This is resolved using the -map x:x option which takes the input source number first (so 0 or 1 depending on the order the inputs are specified) and then second it takes the stream number from the file (usually 0 is video and 1 is audio)

This then creates the file cutting the first 2 seconds off the audio and putting everything nice and into sync.

I first tried this using -acodec and -vcodec both set to copy. This wouldn’t work and the audio was still out of sync. It appears that -ss only has an effect if you re-encode both streams.

, , ,

  1. #1 by David on August 17, 2013 - 3:54 pm

    Hi Andy, I am having trouble getting A/V sync on files i record on my site via webcam. I think the problem is with FFmpeg. The audio comes way after the video.

    Does your solution apply here?
    echo shell_exec(“/usr/local/bin/ffmpeg -i “.$video.” -r 1 -s 500×281 -f image2 “.$image); // creat poster image
    echo shell_exec(“/usr/local/bin/ffmpeg -i “.$video.” -strict -2 -c:v libx264 -crf 23 -c:a aac -b:a 64k “.$convert_video);//

(will not be published)