31

Both ALAC and FLAC are lossless audio formats and files will usually have more or less the same size when converted from one format to the other. I use ffmpeg -i track.flac track.m4a to convert between these two formats but I notice that the resulting ALAC files are much smaller than the original ones. When using a converter software like the MediaHuman Audio Converter, the size of the ALACs will remain around the same size as the FLACs so I guess I'm missing some flags here that are causing ffmpeg to downsample the signal.

1
  • ffmpeg generally needs the -acodec for any destination to be sure you get the conversation done right. There are lots of front ends that use ffmpeg but I've noticed many do not include ALAC as an output option. Commented Aug 21, 2018 at 18:07

2 Answers 2

45

Ok, I was probably a little quick to ask here but for the sake of future reference here is the answer:

One should pass the flag -acodec alac to ffmpeg for a lossless conversion between FLAC and ALAC:

ffmpeg -i track.flac -acodec alac track.m4a

2
  • 9
    To explain what's happening here: .m4a is an Apple variant of the MP4 file format. FFmpeg and most other s/w will default to the AAC encoder when outputting to mp4 or m4a, hence the express -acodec option is needed.
    – Gyan
    Commented Jan 8, 2018 at 7:15
  • 5
    Some FLAC files contain an album cover thumbnail. You can add -vcodec copy to include those in your new ALAC files.
    – Sean
    Commented Nov 20, 2019 at 1:31
3

And for converting a whole directory...

Usage

pushd './Music/Some Album [flac]'
bash flac-to-alac.sh 

flac-to-alac.sh:

#!/usr/bin/env bash
my_bin="$(dirname $0)/flac-to-alac-ffmpeg.sh"
find . -type f -name '*.flac' -exec "$my_bin" {} \;

flac-to-alac-ffmpeg.sh:

#!/usr/bin/env bash
set -e # fail if there's any error
set -u

my_file=$1
my_new="$(echo $(dirname "$my_file")/$(basename "$my_file" .flac).m4a)"
echo "$my_file"
ffmpeg -y -v 0 -i "$my_file" -acodec alac "$my_new"
# only gets here if the conversion didn't fail
#rm "$my_file"

Alternative:

I thought I could get this to work in a single command, but it doesn't escape special characters, such as [.

It seemed so promising...

#!/usr/bin/env bash
set -e # exit immediately on error
set -u # error if a variable is misspelled

while read -r my_file; do
  # ./foo/bar.flac => ./foo/bar.m4a
  my_new="$(dirname "$my_file")/$(basename "$my_file" .flac).m4a"

  ffmpeg -i "$my_file" -acodec alac "$my_new"

  # safe because of set -e, but still do a test run
  #rm "$my_file"
done <<< "$(find . -type f -name '*.flac')"
5
  • 8
    Here's a one-liner I use for conversion: for i in *.flac; do echo $i; ffmpeg -i "$i" -y -v 0 -vcodec copy -acodec alac "${i%.flac}".m4a && rm -f "$i"; done Commented Mar 13, 2020 at 7:52
  • @PaulLindner That looks like a perfect option for single directories, no recursion.
    – coolaj86
    Commented Mar 13, 2020 at 17:29
  • I did this (borrowing from @PaulLindner, whose solution didn't quite work on my system): for i in *.flac; do echo $i; ffmpeg -i "$i" -y -acodec alac "${i%.flac}".m4a; done
    – minisaurus
    Commented Feb 10, 2021 at 20:56
  • 1
    audio files have the gnarliest filenames ever. I had 10cc and 10CC conflicting on a big job recently. im using clementine and audiobrainz to sanitise it all.
    – Tomachi
    Commented Oct 11, 2021 at 13:34
  • I do NOT recommend deleting in the same command after encoding, do it manually to be sure, here is my version of the one-liner: for i in *.flac; do ffmpeg -i "$i" -y -vn -c:a alac "${i%.flac}".m4a; done Commented May 18, 2022 at 10:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .