Extract Audio from a Video File
This operation is possible in a number of different ways and choosing the correct one depends on you, the aim and the format of the audio stream in the file
Lossy... or is it? (dump then code)
First dump the audio from the file using a standard mplayer command:
mplayer videofile.avi -ao pcm:waveheader:file=output.wav
Or with mpv
mpv --no-video --speed=0.75 --ao=pcm --ao-pcm-waveheader=yes \ --ao-pcm-file=audiodump.wav inputfilename.mp4
Then encode it with lame, faac (or flac for lossless but a big file!)
# lame lame -abr -b 128 -q 9 output.wav # faac faac -w output.wav # flac flac output.wav
All these commands will produce a file with the same name but a
different extension, .mp3
, .m4a
or
.flac
respectively.
For Gentoo users, the above commands reside in the following packages... though I am sure you could have easily worked it out!
media-libs/lame media-libs/flac media-libs/faac
Lossless when Container Required (no encoding)
Simple when you use FFMPEG, this will work to just dump the audio into a container. If the audio track is AAC thie file needs a container or mplayer will not be able to play it.
ffmpeg -i videoplayback -acodec copy -vn audiofile.mp4
Just dump from the stream
If the audio is already in a recognisable format... i.e. a media player can detect what it is and play it without the need for a container (mp3 is one) then you can ask MPlayer to dump the raw stream for you.
mplayer -dumpaudio -dumpfile rawstream.mp3 myvideofile.avi
It is likely that the file will be useless if it is not MP3... even RAW PCM won't work unless you provide additional command line parameters.
Get m4a out of mp4 file
ffmpeg -i input.mp4 -vn -c:a copy output.m4a
Or if you want to encode the audio, for example if the audio is in Opus format and your phone cannot play Opus (my Blackberry can't).
ffmpeg -i input.mp4 -c:a libfdk_aac -b:a 128k output.m4a
The -vn
switch in the first example is something to do
with not copying the video. The man page says: "Disable Video
Recording".
Write Plain 16bit WAV from Video Section
ffmpeg -i MyVideo.mp4 -ss 1:19:10 -t 5:0.0 -f wav -acodec pcm_s16le Audio.wav
Encoding m4a from a wav file (with libavcodec)
Encode a wav file using libavcodec aac (rather than libfdk_aac)
$ ffmpeg -i input.wav -c:a aac -b:a 128k output.m4a
mplayer play section of file
Play a section of a file with MPlayer. Below will play 3.5 seconds at 19 minutes 19 seconds into the file... this may not be quite what you get because of keyframes etc so you may have to dump to a raw format first.
$ mplayer -ss 0:19:19 -endpos 3.5 <filename>
And maybe save the sound to a file...
$ mplayer -ss 0:19:19 -endpos 3.5 -ao \ pcm:waveheader:file=<filename> <filename>
You may also do something similar with ffmpeg, if you want to save just a bit of a movie or TV programme... like the starting theme for Eiken Club.
$ ffmpeg -ss 00:02:56 -i \[V-A\]_Eiken_-_01_\[D0246097\]_\[x264\].mkv \ -t 00:01:32 -vn -c:a libfdk_aac -b:a 128k ~/eiken_start.m4a
Normalisation
Sometimes the volume on the encoded audio file is not loud enough,
this is quite common and to fix it you need to "normalise" the sound.
This is quite easy but is a two step process, first add the filter
argument for audio to the command line using the volumedetect
filter:
$ ffmpeg -ss 00:02:55 -i \[V-A\]_Eiken_-_01_\[D0246097\]_\[x264\].mkv -t \ 00:01:32 -filter:a "volumedetect" -vn -c:a libfdk_aac -b:a 128k \ ~/eiken_start.m4a $ ffmpeg -i Eiken-01_x264.mkv -ss 00:02:55 -t 00:01:32 \ -filter:a "volumedetect" -vn -c:a pcm_s16le eiken_start.wav
Then look for the line that tells you the max_volume
,
it should look a little like this:
[Parsed_volumedetect_0 @ 0x2874410] max_volume: -6.2 dB
Invert the number (remove the -) and use that value in the encoding line like so:
$ ffmpeg -ss 00:02:56 -i \[V-A\]_Eiken_-_01_\[D0246097\]_\[x264\].mkv \ -t 00:01:32 -filter:a "volume=6.4dB" -vn -c:a libfdk_aac -b:a 128k \ ~/eiken_start.m4a
Removing the mov_text
stream
Some output files may contain a mov_text
stream even after you
spend some time playing with -map 0:1
etc. I found that to
remove this stream on my Eiken encodes all I needed to do was add an odd
switch to the command line -map_chapters -1
. This works
well in my situation and I found it in a comment on StackOverflow (see
references if you are interested). The final command looks like this:
$ ffmpeg -ss 00:27:07 -i \[V-A\]_Eiken_-_01_\[D0246097\]_\[x264\].mkv \ -map_chapters -1 -t 00:01:35 -filter:a "volume=6.4dB" -vn -sn \ -c:a libfdk_aac -b:a 128k ~/eiken_end.m4a
Naturally there is no need to include this command for the first pass
as you are only detecting the range of the audio amplitude.
You may find the -map
switch useful also, there is a
nice description on the FFMPEG trac website... in references below also.
Merging Audio with a Video File
ffmpeg -i InputFileV.mp4 -i InputFileA.m4a \ -c:v copy -c:a copy \ -map 0:v:0 -map 1:a:0 OutputFile.mp4
Here we take the input files InputFileV.mp4
and
InputFileA.m4a
in the -map
arguments refer to the
file number, (0
= InputFileV.mp4
) then the type of stream
(v
= Video) and finally stream number
(0
= First stream of specified type, video, in file).
Mapping is fairly involved, please see more detail in the references.
References
- superuser.com extract aac from mp4
- https://trac.ffmpeg.org/wiki/Encode/AAC
- https://pypi.python.org/pypi/ffmpeg-normalize
- superuser.com ffmpeg normalize
- stackoverflow.com mov_text fix
- superuser.com How to Merge Audio and Video file in FFmpeg
- stackoverflow.com Merge mp4 files and audio file (complex filter)
- the
-map
switch - https://github.com/mpv-player/mpv/blob/master/DOCS/man/ao.rst