Extracting audio splits into two cases, and picking the right one saves both time and quality. If the audio inside the file is already the format you want, copy it out untouched, instant, and bit-for-bit identical. If you need a different format, re-encode, which costs time and some quality.
Find out which case you are in first:
ffprobe -hide_banner input.mp4
Look at the audio stream line. It names the codec: usually AAC in an MP4, often AC3 or DTS in an MKV, sometimes Opus in a WebM.
Copy without re-encoding
If the codec is already what you want, this extracts it with no loss:
ffmpeg -i input.mp4 -vn -acodec copy output.m4a
-vn means no video. -acodec copy takes the audio stream as it is.
The extension has to match the codec. AAC audio goes into .m4a or .aac; putting it in a .mp3 file produces a file that either fails to write or misleads every program that opens it.
This is the right choice whenever it applies. Re-encoding AAC to MP3 makes the file worse and larger, and people do it constantly out of habit.
Re-encoding when you need a specific format
To MP3, using quality-based encoding in place of a fixed bitrate:
ffmpeg -i input.mp4 -vn -c:a libmp3lame -q:a 2 output.mp3
-q:a runs from 0 (best) to 9 (worst). 2 is roughly 190kbps and transparent for most material; 4 is about 165kbps and fine for speech.
If you need a fixed bitrate instead:
ffmpeg -i input.mp4 -vn -c:a libmp3lame -b:a 192k output.mp3
To AAC, which is smaller than MP3 at the same quality and plays everywhere modern:
ffmpeg -i input.mp4 -vn -c:a aac -b:a 192k output.m4a
To WAV, uncompressed, for editing or further processing, not for distribution:
ffmpeg -i input.mp4 -vn -c:a pcm_s16le output.wav
WAV files are very large. An hour of stereo audio is roughly 600MB, which is fine as an intermediate and unreasonable as a download.
Choosing a bitrate honestly
The audio inside a video file has already been compressed once. Re-encoding it discards more detail on top of what was already discarded, and no bitrate recovers what is gone.
So a very high bitrate on extraction is wasted: encoding a 128kbps AAC track to a 320kbps MP3 produces a file two and a half times larger that sounds no better than the source. Match roughly what was there, or go slightly above.
For speech, 96 to 128kbps is plenty. For music, 192kbps in MP3 or 128kbps in AAC is transparent for nearly everyone.
Extracting part of the audio
Put -ss before -i so FFmpeg seeks rather than decoding everything up to that point:
ffmpeg -ss 00:01:30 -i input.mp4 -t 60 -vn -acodec copy clip.m4a
-t 60 takes sixty seconds from that point. To specify an end time instead, use -to:
ffmpeg -ss 00:01:30 -i input.mp4 -to 00:02:30 -vn -acodec copy clip.m4a
With -ss after -i, FFmpeg decodes the entire file up to the timestamp first, on a long file that is minutes instead of a moment.
Files with several audio tracks
Films frequently carry multiple languages or commentary tracks. List them first:
ffprobe -hide_banner input.mkv
Then select by index, counting audio streams from zero:
# Second audio track ffmpeg -i input.mkv -map 0:a:1 -vn -acodec copy track2.m4a
To extract every audio track at once:
ffmpeg -i input.mkv -map 0:a:0 -acodec copy a0.m4a \ -map 0:a:1 -acodec copy a1.m4a
Without -map, FFmpeg picks one track by its own rules, which on a multilingual file is often not the one you meant.
Batch extraction
for f in *.mp4; do
ffmpeg -i "$f" -vn -c:a libmp3lame -q:a 2 "${f%.mp4}.mp3"
done
Quote the variable so filenames with spaces survive. Add -n to the FFmpeg command if you want it to skip files that already exist rather than prompting, which matters when a long batch is interrupted and restarted.
Normalising loudness
When extracting from several sources, levels vary and the result is a set of files at inconsistent volume. The loudnorm filter brings them to a common target:
ffmpeg -i input.mp4 -vn -af loudnorm=I=-16:TP=-1.5:LRA=11 -c:a libmp3lame -q:a 2 output.mp3
Those values are a common target for spoken-word content. This requires re-encoding, since the audio is being altered, so it cannot be combined with stream copying.
What goes wrong
Output file is empty. The source has no audio stream. Confirm with ffprobe.
Codec not currently supported in container. The codec and the extension disagree. Either change the extension to match, or re-encode to something the container accepts.
Unknown encoder libmp3lame. The build does not include the MP3 encoder. Check with ffmpeg -encoders | grep mp3; use AAC if it is not there.
Wrong language track extracted. No -map was given. List the streams and select explicitly.
It took far longer than expected. -ss was placed after -i, or the audio was re-encoded when copying would have worked.
For pulling a still image or a short preview out instead, How to Create Video Thumbnails and Previews with FFmpeg walks through it.
Going the other way (audio that needs a picture because a platform only accepts video) is a different job with one setting that decides the file size: How to Turn Audio into Video for Podcasts and Music.
Read what is in the file before extracting
The audio you want is not always the first track, and extracting the default produces the wrong language or a commentary.
ffprobe -v error -select_streams a -show_entries stream=index,codec_name,channels,bit_rate:stream_tags=language,title \ -of default=nw=1 input.mkv
Read the language tags and the channel counts. A file with three tracks usually has one main mix, one alternative language and one with fewer channels for compatibility.
Select by index rather than by position once you know what is there, since the ordering is not guaranteed to be meaningful and can differ between files from the same source.
Copy rather than convert wherever possible
Extracting audio should be instant, and it becomes slow the moment a conversion is introduced unnecessarily.
ffmpeg -i input.mkv -map 0:a:0 -c:a copy output.m4a ffprobe -v error -select_streams a:0 -show_entries stream=codec_name,bit_rate -of csv=p=0 output.m4a
Compare the codec and bitrate against the source. Identical values mean the stream was copied and nothing was lost.
The container has to support the codec being copied into it, which is the usual reason a copy fails. Choosing a container that matches the codec avoids the conversion entirely, and converting the container is not the same as converting the audio.
Confirm the whole track came out
An extraction that stops early produces a valid file that is shorter than the source, and nothing reports it.
for f in input.mkv output.m4a; do printf '%-14s %s\n' "$f" "$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$f")" done
The durations should match within a fraction of a second. A meaningful difference means the source is damaged or the extraction was interrupted.
This matters most in a batch, where one truncated file among a hundred is invisible until somebody plays it. Adding the comparison to the loop turns it into a job that reports its own failures.