ffmpeg concat discards audio stream - audio

What I want to achieve
I have two input videos which I do want to concatenate using ffmpeg.
Issue
The input videos contain two stereo audio channels:
after concatenation, the second audio stream is lost:
steps to reproduce
The Command I used is
ffmpeg -f concat -i list.txt -c:a copy -c:v copy demuxed.mp4
Additional Information
The Console Output shows the second audio stream in input properly:
The Output settings also show that there is only one audio output stream. But I want to have the exact same settings in to out, just concatenated:

Assuming that all input videos have matching audio streams, add mapping.
ffmpeg -f concat -i list.txt -map 0:v -map 0:a -c:a copy -c:v copy demuxed.mp4
See http://ffmpeg.org/ffmpeg.html#Stream-selection, especially the section on automatic stream selection for details on how ffmpeg selects streams.

Related

ffmpeg - add 3 audio streams to video

I have the following problem.
In the folder there is video.mp4 file (contain 1 audio stream). There are also 3 different files audio1.wav, audio2.wav, audio3.wav. These files I need to 'attach' as multi stream to the video file - so the user can choose the audio language in VLC player or similar. Result must be one audio at the time - no mixing it all together.
Now, I've done it via Premiere Pro with multitrack (quicktime export to mov), and then I run a script to change audio stream names to correspond with the audio language (iso 639-2 ) and output the mp4 file. All works well, but I wonder if there is simple way to do everything via ffmpeg ( .bat script ). I have a working script for replacing audio in the video, but I need to add few additional .wav to the video file as separate audio tracks.
Any help will be appreciated!
To add a new audio track into an existing video with audio, use
the -i parameter to specify all the input files (original video and additional audios)
the -map option to manually select the tracks of each input (https://trac.ffmpeg.org/wiki/Map)
in your case,
-map 0 to copy all streams from the input #0 (video)
-map 1:a to include all audio streams from input#1 file (audio1)
-map 2:a to include all audio streams from input#2 file (audio2)
and so on
and
-shortest to crop the output to the shortest input
and additionally you may want to use
-c:v copy to copy the video stream without reencoding.
so, try this (line split for readability)
ffmpeg -i video.mp4 -i input1.mp3 -i input2.mp3
-map 0 -map 1:a -map 2:a
-c:v copy -shortest
output.mp4
and (addording to your comment) adding metadata for the audio tracks
ffmpeg -i video.mp4 -i input1.mp3 -i input2.mp3
map 0 -map 1:a -map 2:a
-metadata:s:a:0 language=eng
-metadata:s:a:1 language=ger
-metadata:s:a:2 language=fra
-disposition:a:0 default
-c:v copy -shortest
output.mp4

How to make FFmpeg automatically inject mp3 audio tracks in the single cycled muted video?

everybody here! So basically this is what I want to achieve:
I have a muted video about 3 minutes long.
I have a list of audio tracks in mp3 format (40 songs in a folder with duration 2 to 6 mins each one)
I want this video to play cycled automatically taking songs from playlist and injecting them to the video one by one. Every time a song finishes the next one from the list should start playing at the moment. Video continues playing and doesn't care duration of tracks.
I consider it as the first step on the way to broadcast radio with a video background on youtube in 24/7 mode with ability to put additional tracks to playlist without need to stop translation.
My problem is that I'm new in FFmpeg and I would appreciate any suggestions regarding which FFMpeg topic to start investigate with in order to achieve my goal
Use the concat demuxer
You can do live updates to the playlist for the concat demuxer, but each audio file must have the same attributes, the same number of streams, and all be the same format.
Create input.txt containing:
ffconcat version 1.0
file 'audio1.mp3'
file 'audio2.mp3'
file 'audio3.mp3'
file 'audio40.mp3'
All file names must be "safe" or it will fail with Unsafe file name. Basically no special characters in file names and only use absolute paths. See concat demuxer for more info.
Run ffmpeg to stream to YouTube:
ffmpeg -re -framerate 10 -loop 1 -i image.jpg -re -f concat -i input.txt -map 0:v -map 1:a -c:v libx264 -tune stillimage -vf format=yuv420p -c:a aac -g 20 -b:v 2000k -maxrate 2000k -bufsize 8000k -f flv rtmp://youtube
When you are ready to add new songs make temp.txt containing:
ffconcat version 1.0
file 'audio41.mp3'
file 'audio42.mp3'
file 'audio43.mp3'
Replace input.txt atomically:
mv temp.txt input.txt
See FFmpeg Wiki: Concatenate for lots more info.
If your audio files are not the same
The files listed in input.txt must all have the same:
Format (AAC, MP3, etc, but not mixed)
Sample rate (48000, 44100, etc)
Number of channels (mono, stereo, etc).
If they vary then you will have to pre-process them before adding them to the playlist. Bash example conforming each audio to stereo (-ac 2) with 44100 sample rate (-ar 44100) and save as AAC format in M4A container:
mkdir conformed
for f in *.mp3; do ffmpeg -i "$f" -map 0:a -ac 2 -ar 44100 -c:a aac "conformed/${f%.*}.m4a"; done
Outputting to AAC is recommended for streaming to YouTube.
If you do this then you can avoid re-encoding the audio in the ffmpeg command to YouTube. Just change -c:a aac to -c:a copy in step #2: Run ffmpeg to stream to YouTube.

FFmpeg concat audio with video or gif looping

I'm looking for a solution in FFmpeg to merge audio (mp3) with a short video loop, or gif.
I've already been able to generate a video from an image by joining with audio, but the video stays static frame for the audio duration, the command to make this:
ffmpeg -loop 1 -i imagem.jpg -i audio.mp3 -vcodec h264 -tune stillimage -acodec aac -b:a 64k -pix_fmt yuv420p -shortest video.mp4
I need video that has the duration of the audio, but that uses a loop of another mp4 or a gif. To keep repeating for the duration of the audio.
To do this with a video (MP4 or other format) you should use the Concatenate demuxer.
First create a text file with a list of the paths of the videos you want to concatenate. In your case it will be a list of the same video file, like the following.
# mylist.txt
file /your/path/video.mp4
file /your/path/video.mp4
file /your/path/video.mp4
The paths can be absolute or relative.
Then you need to use the concat demuxer option.
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
This will generate an mp4 with your original video looping 3 times. If your original video is 4 seconds long, then the output will be 12 seconds long. I suggest that you create a video just a bit longer than your audio track and then use the -shortest option when creating your final video.
You can add the audio within this same command like you do in your post. So, all together will look like this:
ffmpeg -f concat -safe 0 -i mylist.txt -i audio.mp3 -c:v copy -c:a copy -shortest output.mp4
In my example I do a stream copy for my output (this will work just fine and will be very fast), but you can use the codecs you want for yours (like H264 and AAC like your post).
You can find more info in the concat demuxer documentation or better yet the concat wiki.
At the moment I don't know if there's a way to do this with a gif file.

Mapping streams by language in FFmpeg

I have lots of files with multiple audio and subtitle languages, however the track numbers aren't consistent (the English audio stream isn't always the first) so using a command such as:
ffmpeg -i "input.mkv" -map 0 -map -0:a:1 -c:v copy -c:a copy "output.mkv"
doesn't yield expected results. After searching around I discovered it was possible to map streams based on language with this command:
ffmpeg -i "input.mkv" -map 0 -map -0:m:language:eng -c:v copy -c:a copy "output.mkv"
However -map -0:m:language:eng will remove all tracks with the English language flag. To keep the subtitle tracks you can use -map 0:s this is a good solution however, I want to know if it's possible to only map audio streams based on language. I.e.,
I want to remove English audio while retaining all other streams without using stream IDs.
-0:m:language:eng will remove english audio tracks and keep all others.
to keep only english audio tracks and remove all others, remove the dash at the beginning: 0:m:language:eng
the dash at the beginning creates a negative mapping, which tells ffmpeg "remove this and only things that match this"
i know this is 8 months later, but i thought it would be helpful for those who end up here off of google searches like i did.
Edit: Ignore initial reply. Not possible at present. Use workaround on top.
ffmpeg -i "in.mkv" -map 0:a -map -0:m:language:eng -map 0:v -map 0:s -map 0:d? -map 0:t? -c copy "out.mkv"
This achieves the desired result because ffmpeg implements the map options in given order.
You need to suffix the metadata selectors to the stream type selector i.e.
ffmpeg.exe -i "%f" -map 0 -map -0:a:m:language:eng -c:v copy -c:a copy "../%f"
Updated As far as I can tell this is the best way to remove English audio while retaining all other streams without using stream IDs which I find to be more inconsistent then language flags. Generally people use correct language flags however audio languages are less likely to keep the same ID.
ffmpeg -i "in.mkv" -map a -map -m:language:eng -map v -map s -map d? -map t -c:v copy -c:a copy "out.mkv"
The command will map every audio stream then remove audio with the English language flag. It will then map all video, subtitle and attachment streams. You can add -disposition:a:0 default to give the first audio stream the [default] flag if needed. Note: Only use when you are removing audio that has the default flag already. Change -disposition:a:0 to -disposition:a:1 and so on if you want to set a different audio track to default.
The following will copy the video and English only audio stream.
ffmpeg -i "G:\VIDEO_TS\VTS_01_1.VOB" -map i:0x1e0 -map i:0x80 "THE STRANGERS 1.mp4"

ffmpeg merge silent video with another video+audio

I want to create, in a single command, a video from 3 sources:
a silent background video;
a smaller video to be overlayed (same length of 1), KEEPING its AUDIO;
a PNG logo to be overlayed
I can create the video but cannot get the audio track. I don't understand if -vf is supposed to work in this case. This is what I've tried to do :
ffmpeg.exe -y -i MASTER_SILENT_VIDEO.mp4 -vf "movie=SMALLER_VIDEO_WITH_AUDIO.flv, scale=320:-1[inner];movie=MY_LOGO.png[inner2]; [in][inner] overlay=800:480,amerge [step1]; [step1][inner2] overlay=30:30 [out]" completed.mp4
The "amerge" filter should do the audio merging job, but of course it doesn't work. I've found similar questions involving -map or filtergraph but they refer to mixing a video source and an audio source; I tried several filtergraph examples without success. Any idea?
overlay one video over other using audio from one input
Use -filter_complex, eliminate the movie source filters, and explicitly define output streams with -map:
ffmpeg -y -i main.mp4 -i overlay_with_audio.flv -i logo.png -filter_complex
"[1:v]scale=320:-1[scaled];
[0:v][scaled]overlay=800:480[bg];
[bg][2:v]overlay=30:30,format=yuv420p[video]"
-map "[video]" -map 1:a -movflags +faststart
output.mp4
You may have to provide additional options to the overlay filters depending on the length of the inputs and how you want overlay to react, but because you did not provide the complete console output from your command I had to make a generic, less efficient, and possibly incorrect example.
overlay one video over other merging audio from both inputs
ffmpeg -y -i main.mp4 -i overlay_with_audio.flv -i logo.png -filter_complex
"[1:v]scale=320:-1[scaled];
[0:v][scaled]overlay=800:480[bg];
[bg][2:v]overlay=30:30,format=yuv420p[video];
[0:a][1:a]amerge=inputs=2[audio]"
-map "[video]" -map "[audio]" -ac 2 -movflags +faststart
output.mp4
I'm assuming both inputs are stereo and that you want a stereo output. Also see FFmpeg Wiki: Audio channel Manipulation - 2 × stereo → stereo.

Resources