Efficently join audio tracks from avi to mp4

1

I have around 100 videos (episodes of a series) twice.

  1. [avi] 720p video resolution with my preferred audio tracks
  2. [mp4] 1080p but the wrong language

Obviously, I would like to have good video with my preferred language. But if its possible I would like to maintain both audio options.

I tried manually joining them with an mp4 joiner (GUI for mp4box) but that takes ages. I would love to see some suggestions to automate and optimize that process.

Proxycon

Posted 2018-08-21T16:24:05.927

Reputation: 13

Possible duplicate of How to replace an audio stream in a video file with multiple audio streams?

– Vlastimil Ovčáčík – 2018-08-22T14:32:58.490

Answers

1

You can do this very easily with ffmpeg (download a static build) like so:

ffmpeg -i input.mp4 -i input.avi -c copy -map 0:v:0 -map 1:a output.mp4

This will map the following streams to the output file:

  • the first video channel of the first input (0:v:0)
  • the audio channels of the second input (1:a) – if you only want the first one, use 1:a:0, etc.

The video and audio streams are copied, so this process is fast.

Incompatible audio

In case that the AVI file uses MP3 for audio streams, they cannot be mapped to an MP4 file. In this case, use:

ffmpeg -i input.mp4 -i input.avi -c:v copy -c:a aac -b:a 192k -map 0:v:0 -map 1:a output.mp4

This would re-encode the audio streams using AAC at 192 kBit/s, which should be high enough quality for you not to notice any artifacts from re-encoding.

Or, you can use MKV as an output container, which supports virtually any codec:

ffmpeg -i input.mp4 -i input.avi -c copy -map 0:v:0 -map 1:a output.mkv

How to run in batch

You can use this command in a loop, obvisouly, to run it on all files, e.g. under Linux with Bash, assuming that the MP4 and AVI files have the same base name, and that you only run it once (otherwise it'll try to convert its output files as well):

for f in *.mp4; do
    aviFile="${f%%.mp4}.avi" # replace the extension
    outputFile="${f%%.mp4}-output.mp4" # create output filename
    ffmpeg -i "$f" -i "$aviFile" -c copy -map 0:v:0 -map 1:a "$outputFile"
done

You will find a lot of examples online on how to run a command in a Windows Batch file loop.

slhck

Posted 2018-08-21T16:24:05.927

Reputation: 182 472

Instead of reencoding the audio track, I would try Matroska (MKV) as the container... – user1686 – 2018-08-21T21:13:54.227

And if you will need to sync the audio and video you can use delay filter. Here's example for stereo audio delayed by 10 seconds: -filter:a:0 "adelay=10000^|10000". (^ is escape character for Windows command line) – Vlastimil Ovčáčík – 2018-08-22T14:31:09.360

@VlastimilOvčáčík Yes, however, if you use this filter, you need to re-encode; you cannot copy the stream in that case. The -itsoffset parameter can also be used to shift input signals without requiring a filter. – slhck – 2018-08-22T19:19:04.177

I might be wrong, but -itsoffset is not adding silence to the gap it creates, while adelay will. My MPC-HC player was confused about it and with added silence there was no problem. – Vlastimil Ovčáčík – 2018-08-22T20:16:51.443