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
I'm using the following command to combine two video files together, overlaying the second one at a certain point in the first file. The result is what I want except the audio from the overlayed file is missing.
ffmpeg.exe -y -hide_banner -ss 00:00:00.067 -i promo.mov -i tag.mov -filter_complex "[1:v]setpts=PTS+6.5/TB[a];[0:v][a]overlay=enable=gte(t\,6.5)[out]" -map [out] -map 0:a -map 1:a -c:v mpeg2video -c:a pcm_s16le -ar 48000 -af loudnorm=I=-20:print_format=summary -preset ultrafast -q:v 0 -t 10 complete.mxf
Without the -map 0:a I get no audio at all, but the second -map 1:a does not pass the audio from -i tag.mov
I have also tried amix but that combines audio from both clips starting at the beginning, and I want the audio from the second file to begin when that file starts overlaying.
It would also be helpful if I could make the audio from the first clip drop lower at the time of the overlay.
amix doesn't support introducing an input mid-way, so the workaround is to add leading silence. You can use the adelay filter to do this.
make the audio from the first clip drop lower at the time of the overlay
This is possible using a sidechaincompressor which takes two inputs and lowers the volume of the first input based on the volume of the second input.
So use,
ffmpeg.exe -y -hide_banner -ss 00:00:00.067 -i promo.mov -i tag.mov -filter_complex "[1:v]setpts=PTS+6.5/TB[1v];[0:v][1v]overlay=enable=gte(t\,6.5)[vout];[1:a]adelay=6.5s,apad,asplit=2[1amix][1aref];[0:a][1aref]sidechaincompress[0asc];[0asc][1amix]amix=inputs=2:duration=first[aout]" -map [vout] -map [aout] -c:v mpeg2video -c:a pcm_s16le -ar 48000 -af loudnorm=I=-20:print_format=summary -preset ultrafast -q:v 0 -t 10 complete.mxf
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.
I am attempting to use ffmpeg for a number of files.
The actual number of audio streams (there is usually one channel per stream) per file isn't known until I'm using ffmpeg.
The desired outcome is to somehow have ffmpeg get the count of audio channel, use the number in the command line to amerge those into one single audio channel.
The goal is to create a preview version of the original video file for use in a simple HTML5 page.
Is this possible in just one call to ffmpeg?
(Also, apologies as some parts of this problem I'm still learning about)
Edit:
Dumas stackoverflow asker here.
Yes, I've been trying multiple combinations of ffmpeg args.
To answer the other question, we have video files that have multiple streams, usually with single channels.
I'll post some cmdline examples shortly.
This cmdline example kind of does what I want; there are 8 streams, and I'm able to combine all audio into one. THe issue is having to know the number before running ffmpeg:
ffmpeg -i EXAMPLE.MOV -filter_complex "[0:v]scale=-2:720,format=yuv420p[v];[0:a]amerge=inputs=8[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a libmp3lame -ar 44100 -ac 2 OUTPUT.mov
You can use ffprobe to find the number of audio streams and use the output as a variable in your ffmpeg command. Bash example using wc to count the audio streams listed by ffprobe:
ffmpeg -i input.mov -filter_complex "[0:v]scale=-2:720,format=yuv420p[v];[0:a]amerge=inputs=$(ffprobe -loglevel error -select_streams a -show_entries stream=codec_type -of csv=p=0 input.mov | wc -l)[a]" -map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a libmp3lame -ar 44100 -ac 2 output.mov
The following command should do the same thing as llogan's answer but doesn't recompress the video track and requires you to identify how many audio tracks should be merged together.
If you want to know how many audio streams are present, try:
ffprobe originalfile.mov 2>&1 | grep 'Stream #'
Once you have identified how many audio streams should be merged, use that number in the amerge=inputs=2 parameter here. This command will merge the streams into one and recompress the audio using aac compression.
ffmpeg -i originalfile.mov -c:v copy -c:a aac -b:a 160k -ac 2 -filter_complex amerge=inputs=2 output.mp4
I used a command like:
ffmpeg -i video.avi -i audio.mp3 -vcodec codec -acodec codec output_video.avi -newaudio
in latest version for adding new audio track to video (not mix).
But I updated the ffmpeg to the newest version (ffmpeg version git-2012-06-16-809d71d) and now in this version the parameter -newaudio doesn't work.
Tell me please how I can add new audio to my video (not mix) using ffmpeg.
Replace audio
ffmpeg -i video.mp4 -i audio.wav -map 0:v -map 1:a -c:v copy -shortest output.mp4
The -map option allows you to manually select streams / tracks. See FFmpeg Wiki: Map for more info.
This example uses -c:v copy to stream copy (mux) the video. No re-encoding of the video occurs. Quality is preserved and the process is fast.
If your input audio format is compatible with the output format then change -c:v copy to -c copy to stream copy both the video and audio.
If you want to re-encode video and audio then remove -c:v copy / -c copy.
The -shortest option will make the output the same duration as the shortest input.
Add audio
ffmpeg -i video.mkv -i audio.mp3 -map 0 -map 1:a -c:v copy -shortest output.mkv
The -map option allows you to manually select streams / tracks. See FFmpeg Wiki: Map for more info.
This example uses -c:v copy to stream copy (mux) the video. No re-encoding of the video occurs. Quality is preserved and the process is fast.
If your input audio format is compatible with the output format then change -c:v copy to -c copy to stream copy both the video and audio.
If you want to re-encode video and audio then remove -c:v copy / -c copy.
The -shortest option will make the output the same duration as the shortest input.
Mixing/combining two audio inputs into one
Use video from video.mkv. Mix audio from video.mkv and audio.m4a using the amerge filter:
ffmpeg -i video.mkv -i audio.m4a -filter_complex "[0:a][1:a]amerge=inputs=2[a]" -map 0:v -map "[a]" -c:v copy -ac 2 -shortest output.mkv
See FFmpeg Wiki: Audio Channels for more info.
Generate silent audio
You can use the anullsrc filter to make a silent audio stream. The filter allows you to choose the desired channel layout (mono, stereo, 5.1, etc) and the sample rate.
ffmpeg -i video.mp4 -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 \
-c:v copy -shortest output.mp4
Also see
Combine two audio streams into one
FFmpeg Wiki: Audio Channel Manipulation
FFmpeg mux video and audio from another video
mp3 music to wav
ffmpeg -i music.mp3 music.wav
truncate to fit video
ffmpeg -i music.wav -ss 0 -t 37 musicshort.wav
mix music and video
ffmpeg -i musicshort.wav -i movie.avi final_video.avi
If the input video has multiple audio tracks and you need to add one more then use the following command:
ffmpeg -i input_video_with_audio.avi -i new_audio.ac3 -map 0 -map 1 -codec copy output_video.avi
-map 0 means to copy (include) all streams from the first input file (input_video_with_audio.avi) and -map 1 means to include all streams (in this case one) from the second input file (new_audio.ac3).
None of these solutions quite worked for me. My original audio was being overwritten, or I was getting an error like "failed to map memory" with the more complex 'amerge' example. It seems I needed -filter_complex amix.
ffmpeg -i videowithaudioyouwanttokeep.mp4 -i audiotooverlay.mp3 -vcodec copy -filter_complex amix -map 0:v -map 0:a -map 1:a -shortest -b:a 144k out.mkv
Nothing quite worked for me (I think it was because my input .mp4 video didn't had any audio) so I found this worked for me:
ffmpeg -i input_video.mp4 -i balipraiavid.wav -map 0:v:0 -map 1:a:0 output.mp4
This shows how to merge all audio tracks into one entire directory with ffmpeg:
ffmpeg -i video.mp4 -i audio.mp3 -map 0:v -map 1:a -c:v copy -shortest output.mp4
Here is how I did what the OP wanted.
My setup is I have two stream of media one video (with its own audio channel) & one audio. I am not converting from but I am restreaming live source by integrating it with an additional audio channel without replacing the old audio from the video stream.
Here is the code I used.
ffmpeg -i "Video stream with its own audio" -i "another audio stream" -map 0:v -map 0:a -map 1:a -shortest -f mpegts "multicast udp stream out put"
what the code does is, it maps each video and audio channels after it acquired the streams from the live source. -map 0:v is the video stream, -map 0:a is the audio that is coming from the video source (notice the 0s from the -map) and finally -map 1:a which is the audio stream from the second source.
then it just restreams it using mpegts through a multicast address. You can change this to a file, a unicast stream or any other supported output format.
Here is the code I am using.
ffmpeg -i "rtp://#231.0.0.208:1234" -i "rtp://#231.0.0.206:1234" -map 0:v -map 0:a -map 1:a -shortest -f mpegts "udp://#231.0.0.45:1234"
Hope this helps some one. Thanks!
If you are using an old version of FFMPEG and you cant upgrade you can do the following:
ffmpeg -i PATH/VIDEO_FILE_NAME.mp4 -i PATH/AUDIO_FILE_NAME.mp3 -vcodec copy -shortest DESTINATION_PATH/NEW_VIDEO_FILE_NAME.mp4
Notice that I used -vcodec
Code to add audio to video using ffmpeg.
If audio length is greater than video length it will cut the audio to video length.
If you want full audio in video remove -shortest from the cmd.
String[] cmd = new String[]{"-i", selectedVideoPath,"-i",audiopath,"-map","1:a","-map","0:v","-codec","copy", ,outputFile.getPath()};
private void execFFmpegBinaryShortest(final String[] command) {
final File outputFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/videoaudiomerger/"+"Vid"+"output"+i1+".mp4");
String[] cmd = new String[]{"-i", selectedVideoPath,"-i",audiopath,"-map","1:a","-map","0:v","-codec","copy","-shortest",outputFile.getPath()};
try {
ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
#Override
public void onFailure(String s) {
System.out.println("on failure----"+s);
}
#Override
public void onSuccess(String s) {
System.out.println("on success-----"+s);
}
#Override
public void onProgress(String s) {
//Log.d(TAG, "Started command : ffmpeg "+command);
System.out.println("Started---"+s);
}
#Override
public void onStart() {
//Log.d(TAG, "Started command : ffmpeg " + command);
System.out.println("Start----");
}
#Override
public void onFinish() {
System.out.println("Finish-----");
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// do nothing for now
System.out.println("exceptio :::"+e.getMessage());
}
}
The marked answer does not set the audio track's language.
The following is an example that specifies German for the default audio track (the video's only audio channel) and English for the audio track that is added anew:
ffmpeg -i "/dir/video.mkv" -i "/dir2/audio.ac3" -map 0 -map 1:a -c:v copy -shortest -metadata:s:a:0 language=ger -metadata:s:a:0 title="GER" -metadata:s:a:1 language=eng -metadata:s:a:1 title="ENG" "/dir/output.mkv"
(The s:a:0 starts counting from 0, adjust that number as needed. If the audio track language is already specified, you don't need to set it and would only need to set it for the audio track that you add.)