FFMPEG Recode all audio streams while keeping originals - ffmpeg

I am trying to add a additional set of audio tracks into some video files, as part of a automated process. I would like to keep all the original audio tracks and have a second re-coded copy.
What I have been using is:
ffmpeg -i file
-map 0:v -codec:v copy
-map 0:a -codec:a copy
-map 0:a:0 -codec:a:0 aac -strict experimental ...(Bitrate, filters etc all with :a:0)
-map 0:s -codec:s copy
output file
However I can't work out how to change this to handle input files that have multiple audio tracks as it will only convert the first.
If I change the :a:0 to :a on the codec line it produces the extra copy I need but overrides the copy codec for the original copy.
Any ideas anyone?

Two ways to do this.
First uses a single command but can get long. Idea is to conditionally map audio streams upto the maximum possible streams a file may have. Not elegant but will get the job done.
ffmpeg -i in.mp4
-c copy
-map 0:v
-map 0:a:0? -c:a:0 copy
-map 0:a:0? -c:a:1 aac
-map 0:a:1? -c:a:2 copy
-map 0:a:1? -c:a:3 aac
-map 0:a:2? -c:a:4 copy
-map 0:a:2? -c:a:5 aac
-map 0:a:3? -c:a:6 copy
-map 0:a:3? -c:a:7 aac
out.mp4
Second method transcodes all audio tracks and pipes it to another ffmpeg execution for copying. With this method, you have less flexibility with stream order in the final output.
ffmpeg -i in.mp4 -c:a aac -map 0:a -f nut - |
ffmpeg -i - -i in.mp4 -c copy -map 1 -map 0 out.mp4

Related

How to merge all audio tracks into one [duplicate]

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

adding background music to video using ffmpeg

I am trying to add bacground music to a video using ffmpeg and it is working fine but I want if length of video is more than the music file then music should start playing again till the video is over -
ffmpeg -i 1.mp4 -i 2.mp3 -map 0:v:0 -map 1:a:0 output.mp4
is there anyway to perform this action?
you can use the following example:
ffmpeg -i ./INPUUT_VIDEO.mp4 -filter_complex "amovie=./INPUT_MUSIC.M4A:loop=0,asetpts=N/SR/TB[aud];[0:a][aud]amix[a]" -map 0:v -map '[a]' -c:v copy -c:a aac -b:a 256k -shortest ./OUTPUT_VIDEO.mp4
you can set/change the audio bit rate by using -b:a flag, for more detail, take a look at this document.
EDIT:
for replacing new audio in the video (repeat it until the end of the video):
ffmpeg -i VIDEO.mp4 -stream_loop -1 -i MUSIC.mp3 -c copy -shortest -map 0:v:0 -map 1:a:0 OUTPUT.mp4
replacing new audio in the video (repeat video until the end of the audio):
ffmpeg -stream_loop -1 -i VIDEO.mp4 -i MUSIC.mp3 -c copy -shortest -map 0:v:0 -map 1:a:0 OUTPUT.mp4

ffmpeg - cannot find matching stream for unlabeled input pad 1 on filter Parsed_amix_0

I have an mp4 and I am trying to merge multiple audio files into it. The command is generated dynamically given the number of audio and their offset. Everything works when I have multiple audios to merge but doesn't when I have one audio file to merge.
Here is the command to merge single audio into the mp4
ffmpeg -y -i ./video.mp4 -itsoffset 00:00:1.753 -i ./audio0.mp3 -filter_complex amix -map 0:v -map 1:a -c:v copy -async 1 -c:a aac -strict experimental -t 10 ./finalVideo.mp4
Here is the command to merge multiple audio files which works
ffmpeg -y -i ./video.mp4 -itsoffset 00:00:1.753 -i ./audio0.mp3 -itsoffset 00:00:0.113 -i ./audio/audio1.mp3 -filter_complex amix -map 0:v -map 1:a -map 2:a -c:v copy -async 1 -c:a aac -strict experimental -t 10 ./finalVideo.mp4

ffmpeg: copy all audio streams and add two more

I want to copy all audio streams from the input to the output. Additionally, I want to downmix two of the audio streams to stereo and add them. The output will be identical to the input but with two additional stereo tracks.
This is what I'm trying:
ffmpeg -i INPUT
-map 0:0 -c:v copy /
-map 0:1 -map 0:18 -af aformat=channel_layouts=stereo /
-map 0:a -c:a copy
OUTPUT.mkv
This is the error message.
Filtergraph 'aformat=channel_layouts=stereo' was defined for audio output stream 0:1 but codec copy was selected.
Filtering and streamcopy cannot be used together
Any advice much appreciated.
Edit: the input streams aren't mono, so go with
ffmpeg -i INPUT
-map 0:0 -c:v copy
-map '[dm]' -map 0:a -c:a copy -c:a:0 aac
-filter_complex "[0:1]pan=stereo[1a];[0:18]pan=stereo[18a];[1a][18a]amerge,pan=stereo[dm]"
OUTPUT.mkv
If you're on Windows, use "[dm]" Make sure you're using the most latest git build, rather than a release. Older versions have a bug in pan when no channel mappings are supplied, like in this revised command.

ffmpeg output in Audacity

I wanted to split the audio track of a mp4 file each receiving different filter then merge to an output mp4 file. Please note I do not wanted series filter but rather parallel filter and then merge.
I came up with the following command.
ffmpeg -i input.mp4 -filter_complex "[0:a]asplit[audio1][audio2];[audio1]highpass=f=200:p=1:t=h:w=50;[audio2]lowpass=f=700:p=1:t=h:w=200;[audio1][audio2]amerge=inputs=2[out]" -map "[out]" -map 0:v -c:v copy -map 0:s? -c:s copy -ac 2 -y output.mp4
this output will play on Vlc and mpv. However, when I try to open it in Audacity, I get:
Why I do get this? I assume the index[05] is the correct audio output.
This raise the question, which audio track is playing when opened in Vlc? How can I create an output which has only one final audio track?
You shouldn't leave filter outputs unlabelled. They are treated as sinks if not consumed by any downstream filters and implicitly mapped for output.
Use
ffmpeg -i input.mp4 -filter_complex "[0:a]asplit[audio1][audio2];[audio1]highpass=f=200:p=1:t=h:w=50[audio1];[audio2]lowpass=f=700:p=1:t=h:w=200[audio2];[audio1][audio2]amerge=inputs=2[out]" -map "[out]" -map 0:v -c:v copy -map 0:s? -c:s copy -ac 2 -y output.mp4

Resources