121

In my .mp4 file the audio delay is -3840 ms. I synced it in KMplayer, and I don't want to use MKVGUI to make a .mkv file. I just need to delay the audio by 3840 ms, everything else should be left intact.
What would be the right command to accomplish this using ffmpeg?
I would appreciate your help.

3
  • 1
    How did you find the audio delay?
    – Zimba
    Feb 13, 2020 at 16:19
  • 1
    In my .mp4 file the audio delay is -3840 ms. ... I just need to delay the audio by -3840 ms, it's a bit contradictory: between the number of the present delay and the number of the needed delay, one and only one of them has to be negative.
    – cipricus
    Mar 21, 2020 at 11:35
  • 1
    You are right @cipricus, I removed the minus sign in front of the second delay amount.
    – Weaver
    Mar 22, 2020 at 16:19

7 Answers 7

190

If you need to delay video by 3.84 seconds, use a command like this:

ffmpeg -i "movie.mp4" -itsoffset 3.84 -i "movie.mp4" -map 1:v -map 0:a -c copy "movie-video-delayed.mp4"

If you need to delay audio by 3.84 seconds, use a command like this:

ffmpeg -i "movie.mp4" -itsoffset 3.84 -i "movie.mp4" -map 0:v -map 1:a -c copy "movie-audio-delayed.mp4"

Make sure, that your ffmpeg build is not too old, newer than 2012 will suffice.


Explanation

-itsoffset 3.84 -i "movie.mp4"

Offsets timestamps of all streams by 3.84 seconds in the input file that follows the option (movie.mp4). itsoffset is documented in the Main options section

-map 1:v -map 0:a

Takes video stream from the second (delayed) input and audio stream from the first input - both inputs may of course be the same file. map is documented in the Advanced options section

A more verbose explanation can be found here:
http://alien.slackbook.org/blog/fixing-audio-sync-with-ffmpeg/

26
  • 3
    How do you choose one specific audio track instead of delaying all audio tracks?
    – Freedo
    Oct 20, 2017 at 6:41
  • 1
    Using the capabilities of map option. You first need to find the index of the desired audio stream in the input file using any of these commands: ffprobe.exe "input_file.mp4" or ffmpeg.exe -i "input_file.mp4" Let's suppose that the index of the audio stream to be delayed is 2 (i.e. the third stream) and that the delayed input is the second one (as in my example). To delay only the third stream, take all other streams from the first input and only the one audio stream from the second (delayed) input: -map 0:0 -map 0:1 -map 1:2
    – Weaver
    Oct 22, 2017 at 15:03
  • 2
    AFAIK -c copy can be used instead of -vcodec copy -acodec copy, and itsoffset only affects video, so maybe this would work the same?: ffmpeg -i "movie.mp4" -itsoffset 3.84 -c copy "movie-video-delayed.mp4" and to delay the audio instead simply add a negative sign to the duration: -3.84.
    – miyalys
    Mar 16, 2018 at 14:35
  • 1
    @miyalys, you are right, I have shortened the codec options in the answer. However I am not sure whether the -itsoffset option affecting only video is a bug or a feature. If it is a bug, it might get fixed in a future version.
    – Weaver
    Mar 18, 2018 at 13:33
  • 2
    @miyalys Doing that doesn't work for me: "Option itsoffset (set the input ts offset) cannot be applied to output url delayed.mp4 -- you are trying to apply an input option to an output file or vice versa. Move this option before the file it belongs to. Error parsing options for output file delayed.mp4. Error opening output files: Invalid argument"
    – Geremia
    Dec 1, 2020 at 22:52
4

As stated in the currently top voted answer, you can use ffmpeg's -itsoffset. According to the ffmpeg wiki, if you do not want to offset all streams, all you have to do is to specify the input file twice. Once for the streams you want to keep as they are and once again for the streams you want to offset. Then you simply map the streams you want to the final output file. This way, there is no need to extract streams and then remux them together later.

For instance (copied from the wiki), if you want all audio streams to be offset by 5 seconds:

ffmpeg -i video.mp4 -itsoffset 5 -i video.mp4 -map 0:v -map 1:a out.mp4
  • -map 0:v will copy the video from the first input file (video.mp4)
  • -map 1:a will copy the audio from the second input file. Which happens to be video.mp4 too, but delayed 5 seconds by the use of -itsoffset right before the corresponding -i option.
2
  • 1
    I think the second bullet should say "-map 1:a will copy the audio ..." but I'm not confident enough of that to make the edit.
    – Amanda
    Mar 20, 2023 at 1:04
  • @Amanda : You're right; I edited the answer.
    – edison23
    Apr 4 at 17:35
3

Make first silence audio:

ffmpeg -f lavfi -i anullsrc=channel_layout=5.1:sample_rate=48000 -t 3 silence_3_sec.mp3

Then concat files:

ffmpeg -i "concat:silence_3_sec.mp3|input.mp3" -acodec copy out.mp3
1

Newer versions of ffmpeg require the -map options to be located just before the output options. For example:

ffmpeg.exe %InputOpts% -i %1 -itsoffset 1.00 -i %1  %CodecsOpts% %MapOpts% %OutputOpts%
1

I extracted audio with Audacity, then cut some silence (equal to delay) from end of video, and added to beginning of audio.

After doing any other adjustments to audio eg. normalization, I exported audio, and replaced audio in original via ffmpeg:

ffmpeg-i "in.mp4" -i "synced.m4a" -vcodec copy -acodec copy -map 0:0 -map 1:0 out.mp4
1
  • 1
    For future reference, Audacity has a Generate > Silence menu item that will allow you to insert silence at the cursor down to the millisecond.
    – Eric
    Apr 16, 2021 at 20:51
1

A method that works without ffmpeg having to read and process the file twice is to use a so-called complex filter that manipulates the presentation timestamps of either the video or audio tracks.

The benefit of this method is that it works for streams (which can be read from only once), and not just for files.

For example -filter_complex "asetpts=PTS-0.3/TB" subtracts 300ms from the presentation time stamps of audio packets.

1
  • Welcome to SuperUser, and thanks for your contribution. It looks technically simpler, more versatile and is something not previously proposed, so very good addition :-) What'd make it better is firstly putting in the entire ffmpeg command as you'd recommend, and maybe a link to ffmpeg documentation that explains the option. Mar 1, 2023 at 20:13
0

Having had no luck with the earlier suggestions, I finally got it to work. My input was mp4 made of mpeg-4 avc with mp3 audio. The critical information points that were missing for me, is that -itsoffset with codec copy doesn't update the streams. It only applies timestamp offset information to the output stream. And this: "For MP4s, ffmpeg's muxer writes an edit list for delaying a stream. Players which honor it, will play as expected e.g. Potplayer does, WMP does not.". That came from https://trac.ffmpeg.org/ticket/1349

So I output to mkv instead.

I'd seen comments that -itsofset works only on video not audio, and that it doesn't work on avi, but also saw both those positions contradicted. YMMV.

To simplify I split the input into separate video and audio files to avoid the -map complexity. I expect this method will also work with map. My audio was late and needed to be brought forward.

ffmpeg -itsoffset 0.4 -i inputVid.mp4 -itsoffset 0 -i inputAudio.mp3 -vcodec copy -acodec copy fixed.mkv

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .