In ffmpeg, how to delay only the audio of a .mp4 video without converting the audio?

49

16

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 intact.
What would be the right command to accomplish this using ffmpeg?
I would appreciate your help.

Alireza

Posted 2015-10-05T09:32:33.730

Reputation: 491

How did you find the audio delay? – Zimba – 2020-02-13T16:19:56.377

Answers

77

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

ffmpeg.exe -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.exe -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).

-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.

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

Weaver

Posted 2015-10-05T09:32:33.730

Reputation: 963

2How do you choose one specific audio track instead of delaying all audio tracks? – Freedo – 2017-10-20T06:41:58.363

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 – 2017-10-22T15:03:49.013

that's kind not what I meant. In this case i still have to call ffmpeg and parse the results to do find the indexes. Is there a equivalent to say -map eng – Freedo – 2017-11-11T06:53:52.793

Well, @Freedo , as you have been already advised in https://superuser.com/questions/639402/convert-specific-video-and-audio-track-only-with-ffmpeg#comment1855076_639430 , what you suggest is in fact possible by specifying streams using metadata values, e.g.: -map 1:m:language:eng

However, bear in mind, that it will select all streams satisfying the criterium, possibly including multiple audio and/or subtitle streams. You can find more information in https://stackoverflow.com/questions/46769419/ffmpeg-choosing-audio-streams-by-language

– Weaver – 2017-11-11T14:42:49.423

1AFAIK -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 – 2018-03-16T14:35:31.690

@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 – 2018-03-18T13:33:35.173

Why does -i have to be specified two times, in the "delay audio" example? – shevy – 2018-03-29T10:32:58.353

Because we need a non-delayed input video stream and another delayed input audio stream, @shevy – Weaver – 2018-04-07T19:12:07.110

delay video command is not working.. delay audio command is working. – MathaN – 2019-03-05T12:55:29.007

2

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

Ivan Malyshev

Posted 2015-10-05T09:32:33.730

Reputation: 208

0

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

Zimba

Posted 2015-10-05T09:32:33.730

Reputation: 107