FFMPEG: Convert m4a to mp3 without significant loss

Solution 1:

Use Variable Bit Rate (VBR)

You can use the -q:a option in ffmpeg to create a variable bitrate (VBR) MP3 output:

ffmpeg -i input.m4a -c:v copy -c:a libmp3lame -q:a 4 output.mp3

What -q:a values to use

From FFmpeg Wiki: MP3:

Control quality with -q:a (or the alias -qscale:a). Values are encoder specific, so for libmp3lame the range is 0-9 where a lower value is a higher quality.

  • 0-3 will normally produce transparent results
  • 4 (default) should be close to perceptual transparency
  • 6 usually produces an "acceptable" quality.

The option -q:a is mapped to the -V option in the standalone lame command-line interface tool.

You'll have to experiment to see what value is acceptable for you. Also see Hydrogen Audio: Recommended LAME Encoder Settings.

Encoding multiple files

In Linux and macOS you can use a Bash "for loop" to encode all files in a directory:

$ mkdir newfiles
$ for f in *.m4a; do ffmpeg -i "$f" -codec:v copy -codec:a libmp3lame -q:a 2 newfiles/"${f%.m4a}.mp3"; done

Solution 2:

Use FFmpeg command line version.

MP3 is officially discontinued (from 2017) and obsolete codec (I call it a dead now). World has already switched to AAC (more efficient & quality codec), and everyone should use this, instead of mp3:

ffmpeg -i filenameee.m4a -acodec copy output.aac

Update: Even though I don't recommend that, unfortunately, some low-quality and obsolete hardware developers still produce appliances which use mp3 and some people still request for that format... Well, here it is:

ffmpeg -i filenameee.m4a -acodec libmp3lame -ab 256k output.mp3

Solution 3:

This worked for me:

ffmpeg -i testing.m4v -b:a 192K -vn testing.mp3

Solution 4:

Using existing answers as a basis I wrote a bash script which should do exactly what the question asks on an Ubuntu machine (tested on 16.04). You'll need to install avprobe which is in the libav-tools package. You can install avprobe with the following command

sudo apt-get install libav-tools

NOTE: It would be wise to make a backup of any folder in which you run this script as well as make your best effort to read and understand what it is doing before running.

I have not tested very rigorously so YMMV.

#!/bin/bash

mkdir "mp3s"
for f in *.m4a;
do
    bitrate=$(avprobe "${f}" 2> >(grep bitrate) | sed 's/^.*bitrate://g' | sed 's/[^0-9]*//g')
    bitrate="${bitrate}K"
    new_filename=$(echo "${f}" | sed 's/.m4a$/.mp3/g')
    ffmpeg -y -i "${f}" -acodec libmp3lame -ab "${bitrate}" "mp3s/${new_filename}"
done