faster way to downmix 5.1 videos to stereo? - audio

I have a hand full of movies that are all in 5.1 audio, i need there to be one audio track that is only in stereo. i have found a few suggestions as to how to do this but some dont work for me and others are way too slow.
the one i found that works the fastest is this:
ffmpeg -y -i "input" -map 0:v -c:v copy -map 0:a:0? -c:a:0 copy -map 0:a:0? -c:a:1 aac -ac 2 -metadata:s:a:1 title="Eng 2.0 Stereo" -map 0:a:1? -c:a:2 copy -map 0:a:2? -c:a:3 copy -map 0:a:3? -c:a:4 copy -map 0:a:4? -c:a:5 copy -map 0:a:5? -c:a:6 copy -map 0:a:6? -c:a:7 copy -map 0:s? -c:s copy "output"
sadly i do not remember where it came from.
the problem with this being that it creates a separate audio track, and for my purposes this does not work.
doing just the standard -ac 2 works but is way to slow, i estimated to take over 40 hours to go through all my movies.
edit:
a bit of extra information to throw in here
all the movies are mp4's
all except 2 movies are 5.1 audio (there is 1 7.1 and 1 mono. i dont really care about them tho)
the command i posted runs at about a 40x speed while just doing -ac 4 runs at 2x speed

Bottleneck is the audio encoding.
Command can just be:
ffmpeg -i input.mp4 -c:v copy -c:a aac -ac 2 output.mp4
Make sure your ffmpeg version 4.0 or newer or else encoding will be slower.
Using -c:a libfdk_aac -afterburner 0 may be 2x faster:
ffmpeg -i input.mp4 -c:v copy -c:a libfdk_aac -ac 2 output.mp4
Due to the license of libfdk_aac you need to compile ffmpeg to use this encoder.
Not much else you can do.

Related

Using FFMPEG to extract multichannel audio from Quicktime

So I have a quicktime file with proxy video content and 8 audio tracks. I need to extract the audio into a single multichannel wave file. I think this is probably pretty simple, but I can't find the solution.
What I have:
ffmpeg -i input.mov -c:a copy output.wav
This gives me just a single channel, so there must be some mapping issue going on.
Without -map, ffmpeg will pick one audio stream from among all inputs for output.
You need to specify multiple outputs and map one stream per output.
ffmpeg -i input.mov
-map 0:a:0 -c:a copy stream0.wav
-map 0:a:1 -c:a copy stream1.wav
-map 0:a:2 -c:a copy stream2.wav
-map 0:a:3 -c:a copy stream3.wav
-map 0:a:4 -c:a copy stream4.wav
-map 0:a:5 -c:a copy stream5.wav
-map 0:a:6 -c:a copy stream6.wav
-map 0:a:7 -c:a copy stream7.wav
Command shown on multiple lines for clarity.
For a single multichannel output, you have to first merge the streams.
ffmpeg -i input.mov -filter_complex "[0:a:0][0:a:1][0:a:2][0:a:3][0:a:4][0:a:5][0:a:6][0:a:7]amerge=8" multichannel.wav

FFMPEG amix filter causes main audio stream to cut out

So I have a video called 1.mkv and would like to mix in a variety of different audio clips at certain points. To do this I'm using the -filter_complex option. However, I'm running into some problems because when ffmpeg tries to mix in the first audio stream the audio works for a short while when the clip is playing and then all audio cuts out. I'm running ffmpeg version 2.8.15-0(which is up to date with my distro). Another "weird" thing about the video output is that in xplayer the video will freeze after the audio cuts out, and will work if you skip far enough ahead in the video(not sure if this is helpful but it might give some extra clues).
Full command:
ffmpeg -i "1.mkv" -i "5.wav" -i "2.wav" -i "3.wav" -i "6.wav" -i "7.wav" -i "4.wav" -i "9.wav" -i "8.wav" -i "10.wav" -filter_complex "[0:0]setdar=4/3[v0];
[2:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=20000|20000,volume=0.5[ad2];
[4:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=900000|900000,volume=0.5[ad4];
[3:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=300000|300000,volume=0.5[ad3];
[1:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=720000|720000,volume=0.5[ad1];
[7:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=1140000|1140000,volume=0.5[ad7];
[9:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=1260000|1260000,volume=0.5[ad9];
[8:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=1020000|1020000,volume=0.5[ad8];
[5:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=960000|960000,volume=0.5[ad5];
[6:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=480000|480000,volume=0.5[ad6];
[0:1]volume=1[ad0];
[ad0][ad2][ad4][ad3][ad1][ad7][ad9][ad8][ad5][ad6]amix=inputs=10:duration=first:dropout_transition=0,dynaudnorm[a0]" -map "[v0]" -map "[a0]" -c:v libx264 -ar 44100 -c:a libmp3lame -preset ultrafast -crf 17 -b:v 1M out2.flv
partial command
ffmpeg -i "1.mkv" -i "2.wav" -filter_complex "[0:0]setdar=4/3[v0];
[1:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=20000|20000,volume=0.5[ad2];
[0:1]volume=1[ad0];
[ad0][ad2]amix=inputs=2:duration=first:dropout_transition=0,dynaudnorm[a0]" -map "[v0]" -map "[a0]" -c:v libx264 -ar 44100 -c:a libmp3lame -preset ultrafast -crf 17 -b:v 1M out2.flv
So I managed to solve this by playing around with the audio filters. The fix was converting the mono stream into a stereo before applying the audio filters. I was considering deleting the question but I'll leave it up incase someone has the same problem in the future.
mono to stereo
[1][1]amerge=inputs=2[a1]

FFmpeg: How to merge all audio streams into stereo

I have 4 audio streams in my video file. They are from 4 microphones placed at 4 different people speaking. I want to transcode to a preview file that can be listened to on headphones where everybody's voice can be heard.
I have seen the -ac 2 option, but I can't tell if this will merge all the audio streams or just select the 1st two. I've also seen the amerge filter, but the docs say this will produce 4 audio channels in the output file. So I'm wondering how headphones will deal with the additional 2 channels
You have several options. This assumes each individual audio stream in in.mp4 is mono.
Mono
Using the amerge filter and -ac 1:
ffmpeg -i in.mp4 -filter_complex "[0:a]amerge=inputs=4[a]" -ac 1 -map 0:v -map "[a]" -c:v copy out.mp4
With amix:
ffmpeg -i in.mp4 -filter_complex "[0:a]amix=inputs=4[a]" -map 0:v -map "[a]" -c:v copy out.mp4
Stereo
With amerge and -ac 2:
ffmpeg -i in.mp4 -filter_complex "[0:a]amerge=inputs=4[a]" -ac 2 -map 0:v -map "[a]" -c:v copy out.mp4
Manually mixed stereo
Using amerge and pan with custom downmix:
Channel 0 will be 100% in FL
Channel 1 will be 75% in FL & 25% in FR
Channel 2 will be 25% in FL & 75% in FR
Channel 3 will be 100% in FR
ffmpeg -i in.mp4 -filter_complex "[0:a]amerge=inputs=4,pan=stereo|FL<c0+0.75*c1+0.25*c2|FR<0.25*c1+0.75*c2+c3[a]" -map 0:v -map "[a]" -c:v copy out.mp4
Try the amerge audio filter, used to solve this similar question: How do I use ffmpeg to merge all audio streams (in a video file) into one audio channel?
amix should even better should fit your purpose.

Ffmpeg to duplicate an audio stream and encode this new stream

I have some video files that I need to re-encode due to compatibility issues. They are currently mkv files with h.264 video and ac3-a52 audio. I want to keep the h.264 video, convert the container to m4v and create two audio tracks, one with the original ac3-a52 and one copied from that but in aac stereo.
I assume there has to be some sort of audio stream mapping command but I don't know how to map and re-encode at the same time. What command should I enter into ffmpeg to achieve this?
Also, what is the difference between ac3 and ac3-a52? Will an apple TV still be able to pass through ac3-a52 or does that have to be converted to ac3?
this works for me:
ffmpeg -y -i Source.mkv -map 0:v -c:v copy -map 0:a -c:a copy -map 0:a -strict -2 -c:a aac out.mkv
-y – A global option to overwrite the output file if it already exists.
-map 0:v – Designate the video stream(s) from the first input as a source for the output file.
-c:v copy – Stream copy the video. This just muxes the input to the output. No re-encoding occurs.
-map 0:a – Designate the audio stream(s) from the first input as a source for the output file.
-c:a copy – Stream copy the audio. This just muxes the input to the output. No re-encoding occurs.
-strict -2 -c:a aac – Use the native FFmpeg AAC audio encoder. -strict -2 is required as a way that you acknowledge that the encoder is designated as experimental. It is not a great encoder, but it is not too bad at higher bitrates.
According to wikipedia, there is no difference between AC3 and ATSC A/52: the 1st one is the name of the codec, the 2nd is the name of the standard specifying the AC3 codec. Maybe someone have more knowledge about it?
I'm doing the same as the OP, but with an m4v container. I'm using the MacPorts "nonfree" variant of ffmpeg so that I can use libfaac, which gives better audio quality than the built-in AAC encoder and also had the same issue as #dkam. The command line I ended using is like this:
ffmpeg -i input.m4v -map 0:v -c:v copy -map 0:a -c:a:0 copy -map 0:a -c:a:1 libfaac output.m4v
(The videos are for playback on an iPad, which doesn't seem to be able to handle ac3.)
This command will take a video with 1 audio stream, and downmix to stereo and convert the audio stream and add it as a 2nd audio stream. It will be in AAC 384k.
ffmpeg -i INPUT.mkv -strict -2 -map 0 -c copy -map 0:a:0 -c:a:1 aac -b:a 384k -ac 2 OUTPUT.mkv
Explanation of the command
ffmpeg -i INPUT.mkv The application and input file
-strict -2 Enable downmixing support
-map 0 Tell ffmpeg read all Video, Audio, and Subtitle streams for the following arguments
-c copy Copy everything
-map 0:a:0 Tell ffmpeg to read the first audio stream for the following arguments
-c:a:1 aac Output the audio to a 2nd audio channel (0 = first channel) in aac format. Important! You must change the output channel to a higher number if there are multiple audio streams to prevent overwriting them.
-b:a 384k 384k bitrate (I don't know what's good for aac stereo but this is really high since it's for 5.1 aac)
-ac 2 Downmix to stereo
OUTPUT.mkv Output file
More examples
A video with two audio streams. Creating a third audio stream by encoding the first.
ffmpeg -i INPUT.mkv -strict -2 -map 0 -c copy -map 0:a:0 -c:a:2 aac -b:a 384k -ac 2 OUTPUT.mkv
Again a video with two audio streams, but you want to encode the second one
ffmpeg -i INPUT.mkv -strict -2 -map 0 -c copy -map 0:a:1 -c:a:2 aac -b:a 384k -ac 2 OUTPUT.mkv

ffmpeg stream offset command (-itsoffset) not working

I would really appreciate if someone could give some pointers regarding the use of itsoffset with ffmpeg. I have read a number of posts on this subject, some of them explain very clearly how to re-synchronize audio and video with -itsoffset, but I haven't been able to make it work.
My avi file is encoded with ffmpeg, in two passes, using the following command for the second pass:
ffmpeg -i whole-vts_01.avs -pass 2 -y -vcodec libxvid -vtag XVID -b:v 1300K -g 240 -trellis 2 -mbd rd -flags +mv4+aic -acodec ac3 -ac 2 -ar 48000 -b:a 128k output.avi
For whatever reason, I end up with a 1 sec delay in the video (or the audio is 1 sec early). It doesn't happen too often but I see it from time to time.
Among other attempts, I have tried the following:
(1) ffmpeg -i output.avi -itsoffset 00:00:01.0 -i output.avi -vcodec copy -acodec copy -map 0:0 -map 1:1 output-resynched.avi
(2) ffmpeg -i output.avi -itsoffset 00:00:01.0 -i output.ac3 -vcodec copy -acodec copy -map 0:0 -map 1:0 output-resynched2.avi
(3) ffmpeg -itsoffset -00:00:01.00 -i output.avi output-resynched8.avi
(4) ffmpeg -i output.avi -itsoffset -1.0 -i output.avi -vcodec copy -acodec copy -map 0:1 -map 1:0 output-resynched13.avi
Here are the results:
Audio garbled and only 5m 35 s long vs. 1h 41m.
(Output.ac3 is audio component of output.avi) Video and audio
identical to original, offset didn't work
Audio did get shifted, but original encoding parameters replaced with default ones (as expected).
Audio garbled and only 9m 56s long vs. 1h 41m.
I see that many people explain, and apparently use the process described above, but it doesn't seem to be working for me. Am I missing something obvious? I would very much like to be able to use -itsoffset as it is cleaner than my workaround solution.
FWIW, here is a different, and longer way of obtaining the desired result:
First create a shifted video only file using -ss:
ffmpeg -i output.avi -ss 1.0 -vcodec copy -an oupput_videoshifted.avi
Then extract the audio:
ffmpeg -i output.avi -vn -acodec copy outputaudioonly.ac3
And finally remux both components:
ffmpeg -i output_videoshifted.avi -i output_audioonly.ac3 -vcodec copy -acodec copy -map 0:0 -map 1:0 output-resynched14.avi
The process works, is fast enough, but I would really prefer to use the one pass -itsoffset solution.
Here is what I did and it work for me
The first input setting -i and the second input is come from the same one video file.
Delay 1 second in first input video and the second input audio just make a copy
ffmpeg -y -itsoffset 00:00:01.000 -i "d:\Video1.mp4" -i "d:\Video1.mp4"
-map 0:v -map 1:a -vcodec copy -acodec copy
-f mp4 -threads 2 -v warning "Video2.mp4"
Delay 1 second in second input audio and the first input video just make a copy
ffmpeg -y -i "d:\Video1.mp4" -itsoffset 00:00:01.000 -i "d:\Video1.mp4"
-map 0:v -map 1:a -vcodec copy -acodec copy
-f mp4 -threads 2 -v warning "Video2.mp4"
The problem is located on -vcodec copy -acodec copy because the shifting will only work on keyframes. I have had the same problem.
Just don't copy (audio/)video, try the thing with -itsoffset, but use
-vcodec libxvid -vtag XVID -b:v 1300K -g 240 -trellis 2 -mbd rd -flags +mv4+aic -acodec ac3 -ac 2 -ar 48000 -b:a 128k
for re-encoding. It should work.

Resources