How do I convert FLAC files to AAC (preferrably VBR 320k+)?
Solution 1
First of all, -aq
sets a quality-based variable bit rate - I think you're looking for -ab
(note that I'm an ffmpeg user, so my knowledge of avconv syntax is limited - I've no idea how far it's drifted since the fork).
Regardless, the built-in avconv/ffmpeg AAC encoder is pretty bad.
fdk_aac
The only really good AAC encoder for avconv/ffmpeg is libfdk_aac - but the license for that is incompatible with the GPL, so in order to get access to it you'll have to compile your own (that's an ffmpeg compilation guide, since I don't know of one for avconv - the Ubuntu guide should be fine for Debian, since I don't think there's anything Ubuntu-specific in there).
Once you've got it, follow the AAC encoding guide; I strongly recommend trying out fdk_aac's -vbr
option - a setting of 3 sounds transparent to me on all the files I've tried, if you want the placebo of a higher bit rate, or you're a sound engineer, you can try a setting of 5.
ffmpeg -i input.flac -c:a libfdk_aac -vbr 3 output.m4a
No need for -map_metadata
, since ffmpeg will automatically transfer metadata (and I'm pretty sure that avconv will too).
For a fixed bit rate 320 kbit/s (seriously, this isn't worth it, AAC achieves audio transparency vs. original CD audio at around fixed 128 kbit/s):
ffmpeg -i input.flac -c:a libfdk_aac -b:a 320k
neroAacEnc
Nero's AAC encoder should be considered on-par with fdk_aac and qaac (Quicktime AAC). Different people will give different opinions on which one is better, but you'll only notice any differences at very low bit rates, and everyone agrees that they're all very high-quality.
neroAacEnc
is available from the Nero website. Unzip it and put it somewhere in your $PATH.
Unfortunately neroAacEnc
can only take WAV audio as input; you can get around this by using avconv or ffmpeg as a decoder:
avconv -i input.flac -f wav - | neroAacEnc -if - -ignorelength -q 0.4 output.m4a
Unfortunately, this will strip metadata; to transfer that over, use avprobe/ffprobe (with -show_format
) to extract and neroAacTag to insert. A bash script would probably be in order.
See the HydrogenAudio page on neroAacEnc: from memory, a -q
setting of 0.4 sounded great to me. You can target a bit rate with -br
(again, I think this would be way overkill):
avconv -i input.flac -f wav - | neroAacEnc -if - -ignorelength -br 320000 output.m4a
EDIT: here is a script for converting audio files to m4a with neroAacEnc, then tagging with ffprobe and neroAacTag (requires them all to be in a directory in your $PATH). It can take multiple input files, so if you save it as convert-to-m4a
, you can convert every FLAC file in a directory with
convert-to-m4a *.flac
It isn't limited to just FLAC files; any audio format that your ffmpeg/avconv can decode will work. You may want to change ffprobe and ffmpeg to avprobe and avconv:
#!/usr/bin/env bash
until [[ "$1" = '' ]]; do
ffmpeg -i "$1" -f wav - | neroAacEnc -if - -ignorelength -q 0.4 "${1%.*}.m4a"
tags=()
while read -r; do
tags+=("$REPLY")
done < <(ffprobe -i "$1" -show_format 2>/dev/null | sed -ne 's/date/year/' -e '/TAG:/s/TAG/-meta/p')
neroAacTag "${1%.*}.m4a" "${tags[@]}"
shift
done
exit 0
Solution 2
I suggest using FFmpeg to convert from FLAC to AAC. FFmpeg is easily installed on a Mac OS X machine with brew:
brew install ffmpeg
Then run the following command to convert all FLAC files in the current directory to AAC:
for i in *flac;do of="${i/.flac/.m4a}"; ffmpeg -i "${i}" -vn -acodec libvo_aacenc -b:a 320k -f mp4 -y "${of}";done
And to convert them to MP3:
for i in *flac;do of="${i/.flac/.mp3}"; ffmpeg -i "${i}" -vn -acodec mp3 -b:a 320k -f mp3 -y "${of}";done
Solution 3
This is my script wrapping ffmpeg for converting any supported audio format to AAC (using libfdk-aac encoder which is the recommended aac encoder by ffmpeg wiki).
#!/usr/bin/env python2.7
from optparse import OptionParser
from subprocess import call
from os.path import splitext
import sys, os
def ffaac(filename, opts):
cmd = ['ffmpeg', '-hide_banner', '-y', '-i', filename,
'-vn', '-c:a', 'libfdk_aac']
profile = {'lc':'aac_low', 'he':'aac_he', 'he2':'aac_he_v2',
'ld':'aac_ld', 'eld':'aac_eld'}
if not opts.br and not opts.vbr:
cmd.extend(['-b:a', '320k'])
if opts.br:
cmd.extend(['-b:a', str(opts.br)+'k'])
if opts.vbr:
cmd.extend(['-vbr', opts.vbr])
if opts.ar:
cmd.extend(['-ar', opts.ar])
if opts.ch:
cmd.extend(['-ac', opts.ch])
cmd.extend(['-profile:a', profile[opts.prof]])
if opts.prof == 'eld' and opts.sbr:
cmd.extend(['-eld_sbr', '1'])
cmd.extend(['-f', 'adts'])
if filename.lower().endswith('.aac'):
return
outfile = splitext(filename)[0] + '.aac'
cmd.append(outfile)
return call(cmd)
if __name__=='__main__':
parser = OptionParser(sys.argv[0]+' [OPTIONS] FILE ...')
parser.add_option('-b', metavar='NUM', type=int, dest='br', help='bitrate')
parser.add_option('-r', metavar='NUM', choices=['8000','11025','16000','22050','32000', '44100', '48000'], dest='ar', help='sample rate: 8000/11025/22050/32000/44100/48000')
parser.add_option('-c', metavar='NUM', choices=['1','2'],dest='ch', help='channels: 1/2')
parser.add_option('-p', metavar='TYPE',choices=['lc', 'he', 'he2', 'ld', 'eld'], default='lc', dest='prof', help='profile: lc/he/he2/ld/eld')
parser.add_option('-v', metavar='QUAL', choices=['1', '2', '3', '4', '5'], dest='vbr', help='vbr quality: 1/2/3/4/5')
parser.add_option('-s', action='store_true', dest='sbr', help='use SBR for ELD')
parser.add_option('-d', action='store_true', dest='delete',help='delete source after converting')
opts, args = parser.parse_args()
for f in args:
if ffaac(f, opts) == 0 and opts.delete :
try:
os.remove(f)
except OSError:
pass
The command line help message:
Usage: /Users/leon/bin/ffaac.py [OPTIONS] FILE ...
Options:
-h, --help show this help message and exit
-b NUM bitrate
-r NUM sample rate: 8000/11025/22050/32000/44100/48000
-c NUM channels: 1/2
-p TYPE profile: lc/he/he2/ld/eld
-v QUAL vbr quality: 1/2/3/4/5
-s use SBR for ELD
-d delete source after converting
Solution 4
Supplemental Answer (to evilsoup's answer)
To handle
- All files in subdirectories
- Spaces in filenames (
find
's-print0
+xarg
's-0
) - Keep newly created m4a files in same directory as their source flac files (
$1
fromsh -c
's positional argument--FILE
set byxarg
's-I
)
One-liner
find . -name '*.flac' -print0 | xargs -0 -I FILE sh -c 'ffmpeg -i "$1" -c:a libfdk_aac -vbr 3 "${1%.flac}.m4a"' -- FILE
Related videos on Youtube
static
20+ years scripting & coding experience. Fluent in many programming languages. Debian/Ubuntu fan for home, Ubuntu/RHEL at work. RHCSA, working on RHCE.
Updated on September 18, 2022Comments
-
static almost 2 years
I back my CDs up to FLAC and then transcode to AAC (.m4a) files for portability on my android phone and the wife's iPhone. I had been using XLD on Mac and it does a great job but I'd rather not steal her Mac to do this and be able to do it on my own Debian box. The following works:
avconv -i "inputfile.flac" -acodec aac -strict experimental "outputfile.m4a" -map_metadata "inputfile.flac":"outputfile.m4a"
But the following doesn't (well it does, but ignores the 320 for audio quality and results as the same as above):
avconv -i "inputfile.flac" -acodec aac -aq 320 -strict experimental "outputfile.m4a" -map_metadata "inputfile.flac":"outputfile.m4a"
I'd found other commands online such as "ffmpeg" but apparently most or all of them are depreciated in favour of the avconv method above. Any help would be greatly appreciated! I could live with 320 Kbps if not true VBR, but LC VBR of at least 320 would be best.
-
static about 11 yearsI should point out that without specifying I get a file around 192K in quality, and although the man page for avconv says you can specify the audio quality with -aq, there's no difference in the resulting file. I get a segmentation fault if I add a 'k' to the 320.
-
Display Name over 8 yearsIf 320k+ is OK for you, you may be actually safer using WavPack (hybrid mode) (it's playable on Android in third party software, for example in deadbeef). It uses completely different method for compression, which does not have any mandatory lossy transforms, and the only trade-off is the amount of quantization noise vs bitrate, funny artifacts are impossible. I'd suggest at least trying. The iPhone may be the problem here, though :/
-
-
static about 11 yearsI appreciate your response and will try as soon as possible and let you know how it goes. I would prefer the first / ffmpeg option, but ffmpeg is what told me to use avconv because it's the new/preferred way I guess. (FYI)
-
evilsoup about 11 years@static actually, both ffmpeg and avconv are actively developed projects; the 'ffmpeg' in the Debian/Ubuntu repositories isn't the real ffmpeg, but a fake one provided by the avconv developers, and that message has caused a lot of confusion. See 'Who can tell me the difference and relation between ffmpeg, libav, and avconv?' and 'The FFmpeg/Libav situation'.
-
evilsoup about 11 yearsAlso note that the script here hasn't been extensively tested, it may well break with some metadata
-
Jonathan Komar almost 10 years"you'll have to compile your own": since @static mentioned a Mac, I thought it prudent to say that I installed ffmpeg with libfdk_aac easily with homebrew.
brew install ffmpeg --with-fdk-aac
. you can get a list of options withbrew info ffmpeg
. But good idea not to steal your wife's Mac :) -
evilsoup almost 10 years@macmadness86 That's interesting but I think (I'm not a lawyer, obviously) that since FDK-AAC is incompatible with the GPL license that ffmpeg uses, it's actually illegal to distribute a version of ffmpeg with FDK-AAC installed. Whoever is doing that over homebrew could potentially get themselves into a spot of bother.
-
dwlz almost 8 years@evilsoup There's no ffmpeg version being "distributed" by Homebrew. Homebrew downloads the sources and compiles it locally using ffmpeg's built-in configuration. If you were to then distribute that binary that you compiled, then you'd get in trouble (should anyone want to make a stink of it).
-
Yannick Wurm over 7 yearsUsing flac 3.1.4 I had to use the following for AAC conversion:
for i in *flac;do of="${i/.flac/.m4a}"; ffmpeg -i "${i}" -vn -acodec aac -b:a 320k -f mp4 -y "${of}";done
-
Mohnish over 4 yearsFrom FFMPEG wiki -
NOTE: as of 2017 libfdk_aac may not always be better than aac for AAC-LC. The built in aac encoder is quite good.
Ref: https://trac.ffmpeg.org/wiki/Encode/HighQualityAudio