Split a video file into separate video and audio files using a single ffmpeg call? - audio

Background: I would like to use MLT melt to render a project, but I'd like that render to result with separate audio and video files. I'd intend to use melt's "consumer" avformat which uses ffmpeg's libraries, so I'm formulating this question as for ffmpeg.
According to Useful FFmpeg Commands For Converting Audio & Video Files (labnol.org), the following is possible:
ffmpeg -i video.mp4 -t 00:00:50 -c copy small-1.mp4 -ss 00:00:50 -codec copy small-2.mp4
... which slices the "merged" audio+video files into two separate "chunk" files, which are also audio+video files, in a single call; that's not what I need.
Then, ffmpeg Documentation (ffmpeg.org), mentions this:
ffmpeg -i INPUT -map_channel 0.0.0 OUTPUT_CH0 -map_channel 0.0.1 OUTPUT_CH1
... which splits the entire duration of the content of two channels of a stereo audio file, into two mono files; that's more like what I need, except I want to split an A+V file into a stereo audio file, and a video file.
So I tried this with elephantsdream_teaser.ogv:
ffmpeg -i /tmp/elephantsdream_teaser.ogv \
-map 0.0 -vcodec copy ele.ogv -map 0.1 -acodec copy ele.ogg
... but this fails with "Number of stream maps must match number of output streams" (even if zero-size ele.ogv and ele.ogg are created).
So my question is - is something like this possible with ffmpeg, and if it is, how can I do it?

Your command works, but you need to specify mapping with columns instead of dots as so:
ffmpeg -i /tmp/elephantsdream_teaser.ogv -map 0:0 -vcodec copy ele.ogv -map 0:1 -acodec copy ele.ogg
You might want to test with a more recent build of ffmpeg. Mine gave correct errors for your command:
[ogg # 00000000043f8480] Invalid stream specifier: .0.
Last message repeated 3 times
Stream map '0.0' matches no streams.

Related

FFmpeg: How to join multiple mono files into one multichannel file?

I have e.g. 3 mono wav files. I would like to join them in one wave file which has 3 channels (not 2.1). The duration o this wave should inherit from the longest duration of mono files. I tried many commands, but no one of them gave me the expected result. Could you help?
apad + join
One method is to use apad on the two shorter inputs and then mix them with the join filter:
ffmpeg -i front_left.wav -i front_right.wav -i front_center.wav -filter_complex "[0]apad[FL];[1]apad[FR];[FL][FR][2]join=inputs=3:channel_layout=3.0:map=0.0-FL|1.0-FR|2.0-FC" output.wav
apad + amerge + channelmap
Similar to above, but channelmap (or pan) has to be added because amerge has no mapping functionality and assumes 2.1 instead of 3.0:
ffmpeg -i front_left.wav -i front_right.wav -i front_center.wav -filter_complex "[0]apad[FL];[1]apad[FR];[FL][FR][2]amerge=inputs=3,channelmap=map=FL-FL|FR-FR|LFE-FC" output.wav
You can use ffprobe to get the file durations.
ffmpeg -layouts will provide a list of accepted channel names and layouts.

How do you replace audio at a given timestamp with ffmpeg?

I am trying to use the ffmpeg library to take two FLAC files and replace the audio in File A with the audio in File B at a given timestamp.
For example if File B was to be played at 00:02 and was a second long, playing the output it would be (00:00-0:01) File A Audio -> (00:02-0:03) File B Audio -> (00:04-...) File A Audio
To do this, I have tried the following
ffmpeg -y -i original.flac -i replacement.flac -acodec copy -ss 2 -to 3 -write_xing 0 result.flac
But this only produces the original audio between the specified timestamps.
Is there any way to achieve this within ffmpeg?
The typical method to do this would be the concat demuxer, but there are issues with FLAC extraction with duration header in the output, so you can use
ffmpeg -y -i original.flac -i replacement.flac \
-filter_complex "[0]atrim=0:2[Apre];[0]atrim=5,asetpts=PTS-STARTPTS[Apost];\
[Apre][1][Apost]concat=n=3:v=0:a=1" out.flac
Where 2 is the insertion point in seconds, and 5 is the insertion point + B's duration.

FFMPEG encode audio and forced subtitles at same time?

I'm using latest static build of ffmpeg windows.
My input file (.mkv) is:
[video] - 1080, V_MPEG4/ISO/AVC, 14.6 Mbps, ID#0
[audio] - DTS 5.1, 1510 Kbps, ID#1
[subtitles] - S_TEXT/ASS Lossless English, ID#14
My problem is this: I convert the audio, so that my target player, a XB1 console (media support faq), is able to play audio/video. However sometimes its rather difficult to hear or parts may be in foreign language, so I want to force the english subtitles into the mix at the same time I convert the audio.
Currently for the audio, I use the following command
ffmpeg -i input.mkv -codec copy -acodec ac3 output.mkv
Can I somehow tie in the forced subtitles (onto the video) in order to save an extra process of taking the output.mkv and trying to force subtitles on?
Edit: I've tried using the following command to extract subtitles to be able to edit them
ffmpeg -i Movie.mkv -map 0:s:14 subs.srt
However i get the error: Stream map '0:s:14' matches no streams
Edit2: attempted to extract subtitles and succeeded with
ffmpeg -i input.mkv -map 0:14 -c copy subtitles.ass
but still looking to force the subtitles, nonetheless!
Also - a little bonus to this question - can I somehow extract the .ass file and edit it to only produce subtitles for foreign parts - so english audio doesn't have subtitles during the movie but foreign audio does have subtitles?
Cheers
Edit3:
When I try to use both of the commands at once (my earlier mentioned audio converter & one from the ffmpeg wiki)
ffmpeg -i input.mkv -codec copy -acodec ac3 -vf "ass=subs.ass" output.mkv
I get the following error from ffmpeg,
Filtergraph 'ass=subs.ass' was defined for video output stream 0:0 but codec copy was selected.
Filtering and streamcopy cannot be used together.
Since your media player does not support subtitles, the text has to be burnt onto the video image. For that, use
ffmpeg -i input.mkv -vf "ass=subs.ass" -c:v libx264 -crf 20 -c:a ac3 output.mkv
This will re-encode the video, since text is being added. The CRF value controls the video quality. Lower values produce better quality but larger files. 18 to 28 is a decent range to try.

Re-encode video stream only with ffmpeg (and with all audio streams)

I'm looking for a way to re-encode the video stream of a movie only and keep all other streams as they are using ffmpeg or more specific streamio/streamio-ffmpeg (Github - StreamIO-FFMPEG).
I already tried various combinations of -map 0 or -map a:0 -map s:0, but in all combinations I tried, either nothing is encoded at all, or not all other streams are copied to the new file. In most cases there is only one audio stream after encoding, when there were two before, and sometimes the subtitle streams are lost, too. Also most times the info what language the streams are in gets lost.
So when I have a movie file (mkv) with the following streams:
0: video [H.264, 1080p]
1: audio [english, mp3]
2: audio [french, mp3]
3: subtitle [english (forced)]
4: subtitle [english]
What should the ffmpeg parameters be, if I want to encode the video file to H.265 and 720p and keep all other streams as they are?
What should the parameters be, if I additionally want to encode the audio streams as AAC?
Thanks in advance!
Use
ffmpeg -i in.mkv -vf scale=hd720 -map 0 -c copy -c:v libx265 out.mkv
To encode audio as well,
ffmpeg -i in.mkv -vf scale=hd720 -map 0 -c copy -c:v libx265 -c:a aac out.mkv
(The order of the arguments above matter)

Normalize audio in an avi file

I have an avi file that has different levels of audio. Is there a way to decrease and increase appropriately where needed the audio of my file using ffmpeg?
In ffmpeg you can use the volume filter to change the volume of a track. Make sure you download a recent version of the program.
Find out the gain to apply
First you need to analyze the audio stream for the maximum volume to see if normalizing would even pay off:
ffmpeg -i video.avi -af "volumedetect" -f null /dev/null
Replace /dev/null with NUL on Windows. This will output something like the following:
[Parsed_volumedetect_0 # 0x7f8ba1c121a0] mean_volume: -16.0 dB
[Parsed_volumedetect_0 # 0x7f8ba1c121a0] max_volume: -5.0 dB
[Parsed_volumedetect_0 # 0x7f8ba1c121a0] histogram_0db: 87861
As you can see, our maximum volume is -5.0 dB, so we can apply 5 dB gain. If you get a value of 0 dB, then you don't need to normalize the audio.
Apply the volume filter:
Now we apply the volume filter to an audio file. Note that applying the filter means we will have to re-encode the audio stream. What codec you want for audio depends on the original format, of course. Here are some examples:
Plain audio file: Just encode the file with whatever encoder you need:
ffmpeg -i input.wav -af "volume=5dB" output.mp3
Your options are very broad, of course.
AVI format: Usually there's MP3 audio with video that comes in an AVI container:
ffmpeg -i video.avi -af "volume=5dB" -c:v copy -c:a libmp3lame -q:a 2 output.avi
Here we chose quality level 2. Values range from 0–9 and lower means better. Check the MP3 VBR guide for more info on setting the quality. You can also set a fixed bitrate with -b:a 192k, for example.
MP4 format: With an MP4 container, you will typically find AAC audio. We can use ffmpeg's build-in AAC encoder.
ffmpeg -i video.mp4 -af "volume=5dB" -c:v copy -c:a aac -strict experimental -b:a 192k output.mp4
Here you can also use other AAC encoders. Some of them support VBR, too. See this answer and the AAC encoding guide for some tips.
In the above examples, the video stream will be copied over using -c:v copy. If there are subtitles in your input file, or multiple video streams, use the option -map 0 before the output filename.
The author's info is: Jon Skarpeteig in SuperUser
You can use my ffmpeg-normalize script for that.
First, install a recent version of ffmpeg. Then, install via pip install ffmpeg_normalize, then run it on an AVI file:
ffmpeg-normalize input.avi -o output.mkv -c:a aac -b:a 192k
Here, we're choosing to re-encode the audio with AAC at 192 kBit/s, and copy the video stream over to the output. This will perform EBU R128 normalization, but simple peak/RMS normalization is also possible.

Resources