Skip to content

Repository files navigation

flac2mpc

A fast, parallel FLAC-to-Musepack converter with full metadata preservation, cover art handling, and ReplayGain 2.0 analysis.

Optionally uses a working directory (e.g. a RAM disk) for encoding and tagging before completed tracks are moved to the output album. Loudness is then calculated over the complete output album, including tracks retained from earlier runs.


Features

  • Parallel FLAC-to-Musepack encoding via FFmpeg (decode) + mpcenc (quality 0–10, default Q6)
  • Full FLAC metadata → APEv2 tag mapping (title, artist, album, year, track, disc, …)
  • Extended tag pass-through: BPM, compilation, grouping, MusicBrainz IDs, ISRC, label, catalogue number, barcode
  • Sort fields: title sort, artist sort, album sort, album artist sort, composer sort
  • Unknown/custom Vorbis Comment fields are preserved automatically (semantic preservation, not byte-for-byte)
  • Standalone cover art copied or extracted per album at original size/format
  • Optional embedded artwork as an APEv2 "Cover Art (Front)" binary tag (off by default)
  • EBU R128 / ReplayGain 2.0 track & album gain tagging (via rsgain)
  • Working directory support — encode to RAM disk, move to output when done
  • Recursive directory scanning with mirrored output structure
  • Configurable via a single config.toml file
  • Correct full-album gain on partial reruns
  • Post-encode output verification and persistent failed-track retry state
  • Existing-file policies: skip, newer-only, retag, or full rebuild
  • GUI profiles, saved settings, preflight checks, pause-between-albums, per-album status, retry-failed, and reveal-output controls

Requirements

Python

  • Python 3.9+
  • Dependencies: pip install -r requirements.txt

FFmpeg

FFmpeg is used to decode FLAC to WAV, which is then piped into mpcenc.

macOS (Homebrew)

brew install ffmpeg

Ubuntu / Debian

sudo apt install ffmpeg

Arch Linux

sudo pacman -S ffmpeg

mpcenc (the Musepack encoder)

FFmpeg cannot encode Musepack (it only has decoders), so the mpcenc binary is required. The MusicPack-built encoder (whepper/musicpack) is preferred: it is a maintained Musepack encoder with the same CLI and psychoacoustic quality scale as the historical Musepack encoder, so --quality 6.0 means exactly the same thing.

Recommended — build the MusicPack encoder:

git clone https://github.com/whepper/musicpack.git
cd musicpack
cmake -S . -B build
cmake --build build -j
# Encoder: build/mpcenc/mpcenc   (a static build: cmake -S . -B build-static)

flac2mpc finds it automatically when the checkout is a sibling of this project (../musicpack), or you can point at it explicitly.

Fallbacks (still supported, in resolution order):

  • $MUSICPACK_MPCENC — explicit path, highest priority.
  • mpcenc_bin in config.toml — pins an exact binary and disables automatic discovery.
  • A sibling ../musicpack/build/mpcenc/mpcenc or ../musicpack/build-static/mpcenc/mpcenc.
  • mpcenc from your PATH (e.g. Homebrew musepack or distro musepack-tools). Encoding works, but flac2mpc warns that the MusicPack build is preferred for reproducibility and consistency.

Note: Musepack only supports 32/37.8/44.1/48 kHz sources. The preflight check warns about any FLAC outside these rates before encoding starts.

rsgain

rsgain is required for ReplayGain 2.0 analysis. It is a compiled system binary, not a Python package.

Musepack note: rsgain's tag writer has no Musepack support (writing tags to .mpc via its bundled taglib corrupts SV8 files). The converter therefore runs rsgain in scan-only mode (custom -s s -O) and writes the resulting ReplayGain values as APEv2 tags itself with mutagen, which is safe.

Outputs are additionally checked with mpcdec (the reference decoder most players use) after each album so a file that would play with static elsewhere is caught instead of shipped. mpcdec ships with the same MusicPack checkout as mpcenc.

macOS (Homebrew)

brew install rsgain

Ubuntu / Debian

sudo apt install rsgain

Arch Linux

sudo pacman -S rsgain

Manual install — download a pre-built binary from the rsgain releases page and place it on your PATH, or set rsgain_bin in config.toml to the full path.

If you don't need ReplayGain tagging, set enable_replaygain = false in [loudness] and rsgain is not required.


Installation

git clone https://github.com/whepper/flac2mpc.git
cd flac2mpc
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Configuration

Copy and edit config.toml:

cp config.toml my_config.toml

Minimal configuration

[paths]
input_dir  = "/music/flac"
output_dir = "/music/mpc"
ffmpeg_bin = "ffmpeg"
mpcenc_bin = "mpcenc"
rsgain_bin = "rsgain"

With RAM disk working directory

Set work_dir to a RAM disk mountpoint. Encoding and metadata work happens there; completed tracks are moved before full-album loudness analysis.

[paths]
input_dir  = "/music/flac"
output_dir = "/music/mpc"
ffmpeg_bin = "ffmpeg"
mpcenc_bin = "mpcenc"
rsgain_bin = "rsgain"
work_dir   = "/Volumes/RAMDisk"   # macOS example
# work_dir = "/mnt/ramdisk"       # Linux example

Leave work_dir commented out (or omit it) to write directly to output_dir as before.

RAM disk sizing: the working directory only needs to hold one album at a time. ~500 MB is sufficient for typical albums at Q6.

Creating a RAM disk

macOS — create a 1 GB RAM disk:

diskutil erasevolume HFS+ RAMDisk $(hdiutil attach -nomount ram://2097152)
# Mountpoint: /Volumes/RAMDisk
# Remove when done:
# hdiutil detach /Volumes/RAMDisk

In the GUI, clicking Create makes the RAM disk for you, and closing the app auto-ejects it. Uncheck Auto-eject on exit in the Folders panel if you want the mount to survive between sessions.

Linux — mount a tmpfs:

sudo mkdir -p /mnt/ramdisk
sudo mount -t tmpfs -o size=1G tmpfs /mnt/ramdisk
# Persist across reboots by adding to /etc/fstab:
# tmpfs  /mnt/ramdisk  tmpfs  defaults,size=1G  0  0

Usage

# Default config
python main.py

# Custom config file
python main.py --config my_config.toml

# Dry run — scan and report without encoding
python main.py --dry-run

# Override config values on the command line
python main.py --input /music/flac --output /music/mpc
python main.py --workers 8 --log-level DEBUG
python main.py --existing-mode newer
python main.py --retry-failed

# Print version and exit
python main.py --version

CLI flags

Flag Overrides Notes
--config PATH Path to TOML file (default: config.toml)
--dry-run Scan and report, no encoding
--input DIR [paths] input_dir
--output DIR [paths] output_dir
--workers N [processing] workers Must be ≥ 1
--log-level LEVEL [processing] log_level DEBUG / INFO / WARNING / ERROR
--existing-mode MODE [processing] existing_mode skip / newer / retag / rebuild
--no-verify-output [processing] verify_output Disable post-encode verification
--retry-failed [processing] retry_failed_only Retry tracks recorded as failed
--version Print version and exit

Exit codes

Code Meaning
0 All files converted successfully
1 One or more files/albums failed, or a fatal runtime error occurred
2 Configuration file not found, invalid, or a CLI override was rejected
130 Interrupted by Ctrl+C

Configuration Reference

[paths]

Key Default Description
input_dir (required) FLAC source directory (scanned recursively)
output_dir (required) Musepack output root directory
ffmpeg_bin "ffmpeg" Path to FFmpeg binary (FLAC → WAV decode)
mpcenc_bin "mpcenc" Path to the Musepack encoder binary. The default resolves automatically: $MUSICPACK_MPCENC → explicit config → sibling MusicPack build → PATH. Any other value pins that exact binary
mpcdec_bin "mpcdec" Path to the reference decoder (output verification)
rsgain_bin "rsgain" Path to rsgain binary
work_dir (disabled) Working directory for intermediate files (RAM disk recommended)

[encoding]

Key Default Description
vbr_quality 6.0 mpcenc quality 0.0–10.0 (see table below; 6 = --extreme)
output_format "mpc" Always mpc (legacy m4a/mp4 values are accepted and ignored)
encode_timeout 1800 Seconds before an encode is killed for a stalled file

mpcenc quality scale (nominal bitrates for stereo):

vbr_quality Profile Approx. bitrate
2.0 --telephone ~60 kbps
3.0 --thumb ~90 kbps
4.0 --radio ~130 kbps
5.0 --standard ~180 kbps
6.0 --extreme ~210 kbps (recommended default)
7.0 --insane ~240 kbps
8.0 --braindead ~270 kbps
10.0 ~350 kbps

Values are centesimal: 6.5 is valid.

[metadata]

Key Default Description
copy_artwork false Embed cover art in MPC files as an APEv2 "Cover Art (Front)" tag
cover_file.enabled true Copy standalone cover file per album
cover_file.search_names ["cover.jpg", …] Cover filenames to look for
cover_file.max_size 0 Max cover dimension in pixels (0 preserves the original)
cover_file.jpeg_quality 95 JPEG quality for resized covers

[loudness]

Key Default Description
enable_replaygain true Analyse loudness with rsgain (scan-only) and write ReplayGain 2.0 APEv2 tags (always targets −18 LUFS)
reuse_existing_replaygain false Skip rsgain analysis when the source FLAC already has ReplayGain tags

iTunes SoundCheck (iTunNORM) is not produced: it is Apple-specific and Musepack is not supported by Apple's software.

Partial reruns analyse every available track in the final output album, so album gain remains correct even when only one missing or newer track is encoded.

[processing]

Key Default Description
workers 4 Parallel encoding threads per album
existing_mode "skip" Existing-output policy: skip, newer, retag, or rebuild
verify_output true Verify duration, channels, and sample rate
retry_failed_only false Process only tracks recorded as failed
log_level "INFO" DEBUG / INFO / WARNING / ERROR

Track state is stored atomically in .flac2mpc-state.json inside the output root, enabling targeted retry after cancellation or per-track failures.

Metadata

Tag transfer is semantic preservation of transferable metadata, not byte-for-byte metadata preservation: FLAC Vorbis Comments and Musepack APEv2 are different tagging systems.

  • Common fields are mapped to their conventional APEv2 names (Title, Artist, Album, Year, Track, Disc, Genre, Composer, Comment, Lyrics, …). Sort fields, MusicBrainz IDs, ISRC, label, catalogue number and barcode are mapped too.
  • Unknown or custom textual Vorbis Comments are preserved automatically: any tag without a canonical mapping is copied to an APEv2 tag of the same name, with every value kept as a separate APEv2 value (e.g. multiple ARTIST or PERFORMER entries stay separate rather than being joined). Vorbis keys are case-insensitive, so passthrough keys are written with the stored spelling — mutagen lowercases keys when reading — and the first spelling seen wins.
  • Track/disc numbers are normalized to the combined n/total form when a total is known (tracktotal/totaltracks, disctotal/totaldiscs, or the combined n/total form in the number itself) and to n alone otherwise — 7/0 is never emitted.
  • ReplayGain is deliberately handled by the loudness pipeline, not copied blindly: source REPLAYGAIN_* and R128 tags are excluded from tag passthrough so stale source values cannot conflict with the values computed by flac2mpc.
  • FLAC-specific structural metadata (stream info, MD5 checksum, block layout) is not represented as APEv2 metadata.
  • Embedded artwork remains governed by the existing [metadata] artwork settings, independent of text-tag passthrough.

Output structure

The input directory tree is mirrored exactly:

input_dir/
  Artist/
    Artist - Album/
      01 - Track.flac
      cover.jpg

output_dir/
  Artist/
    Artist - Album/
      01 - Track.mpc   ← encoded + fully tagged
      cover.jpg         ← copied standalone cover

Pipeline overview

Encode mode (default)

For each album:
  ┌─ work_dir/album/    (RAM disk)    ─── or ─── output_dir/album/
  │
  ├─ 1. Decode FLAC → WAV             (FFmpeg)
  ├─ 2. Encode WAV → MPC              (mpcenc --quality N, parallel)
  ├─ 3. Copy FLAC metadata → MPC      (mutagen, APEv2)
  ├─ 4. Copy / extract cover art      (Pillow)
  ├─ 5. Verify encoded output         (mutagen)
  ├─ 6. Move staged tracks → output   (when work_dir is enabled)
  ├─ 7. EBU R128 full-album analysis  (rsgain, scan-only)
  ├─ 8. Write ReplayGain tags         (mutagen, safe APEv2 write)
  └─ 9. Decode-verify album           (mpcdec, reference decoder)

macOS GUI App

A standalone double-click .app for macOS can be built with PyInstaller. No Python, FFmpeg, mpcenc, or rsgain installation is required on the target machine — everything is bundled inside flac2mpc.app.

Runtime UI

The interface provides saved settings, quality profiles, preflight checks, existing-file policies, recovery controls, and settings for Folders, Encoding, Cover Art, and Loudness. The default Recommended (Q6) profile uses quality 6 (--extreme), keeps artwork out of MPC files, and copies/extracts a standalone cover at its original size and format.

During a run the GUI shows:

  • a progress bar that tracks the total number of files being encoded. It only ever moves right — long-running phases like ReplayGain analysis and album moves do not reset the bar to zero.
  • an activity label below the bar with the current phase (Encoding album 3 / 12 — track 5 / 10, Analysing loudness — album 3 / 12, Moving album to output).
  • a log of every pipeline message, capped at the most recent 5000 lines so a long run cannot grow it without bound.
  • an album table with processing, verification, loudness, completion, and failure status for each album.

The RAM disk create/eject buttons use the indeterminate bar style because their duration is unknown up front.

1 — Clone the repository

git clone https://github.com/whepper/flac2mpc.git
cd flac2mpc

2 — Create a virtual environment and install dependencies

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -r requirements-gui.txt

3 — Get the encoder binaries

brew install ffmpeg rsgain

For mpcenc, prefer the MusicPack build (see mpcenc above) so the bundled encoder matches the ecosystem flac2mpc targets:

git clone https://github.com/whepper/musicpack.git
cmake -S musicpack -B musicpack/build && cmake --build musicpack/build

4 — Copy the binaries into the vendor/ directory

mkdir -p vendor
cp "$(brew --prefix ffmpeg)/bin/ffmpeg" vendor/ffmpeg
cp musicpack/build-static/mpcenc/mpcenc vendor/mpcenc
cp musicpack/build-static/mpcdec/mpcdec vendor/mpcdec
cp "$(brew --prefix rsgain)/bin/rsgain" vendor/rsgain
xattr -d com.apple.quarantine vendor/ffmpeg vendor/mpcenc vendor/rsgain 2>/dev/null || true

Alternatively, download pre-built binaries directly:

Portability caveat: Homebrew's ffmpeg and rsgain are dynamically linked against /opt/homebrew/... dylibs. Bundling them this way works on the machine that built the app, but the resulting .app will not run on a Mac without the same Homebrew libraries installed. Only the MusicPack mpcenc/mpcdec (and a libmpcdec static build) ship fully static. For a truly self-contained app, replace vendor/ffmpeg and vendor/rsgain with static builds (compile FFmpeg statically, and download a static rsgain binary from the releases page above).

If a Homebrew rsgain fails to start with a Library not loaded: .../libavformat.X.dylib error, it was bottled against a different FFmpeg version than is installed. Rebuild it from source to relink against the installed libraries: brew reinstall --build-from-source rsgain.

5 — Build the app

pyinstaller flac2mpc_gui.spec

PyInstaller may report a code-signing warning: resource fork, Finder information, or similar detritus not allowed. That happens when files copied into the bundle carry Finder metadata (com.apple.FinderInfo xattrs). Fix it by stripping extended attributes and ad-hoc signing the finished app:

xattr -cr dist/flac2mpc.app
codesign --force --deep --sign - dist/flac2mpc.app

The finished app is at dist/flac2mpc.app. Drag it to /Applications or double-click it directly — no terminal needed.

Note: The .venv must be active when running pyinstaller so it can find all installed packages. If you open a new terminal session, run source .venv/bin/activate again before building.

Tkinter not found? Homebrew Python requires a separate package for the GUI toolkit. Install it matching your Python version, then rebuild:

brew install python-tk@3.14   # adjust to match: python3 --version
rm -rf dist build && pyinstaller flac2mpc_gui.spec

The ad-hoc signature above is fine for local use. Distributing the app to other Macs requires a Developer ID signature plus notarization.

Running without building

You can also run the GUI directly from the project directory (no PyInstaller needed):

source .venv/bin/activate
python gui.py

FFmpeg, mpcenc and rsgain must be available (e.g. installed via Homebrew), or you can place custom builds at vendor/ffmpeg, vendor/mpcenc and vendor/rsgain and the GUI will use them automatically. For mpcenc, a sibling MusicPack checkout or MUSICPACK_MPCENC is preferred; see mpcenc.


Note on Musepack Licensing

Unlike AAC (which is patent-encumbered), Musepack is open source: the encoder and libraries are BSD/LGPL/GPL licensed. There are no AAC-related patent obligations when distributing binaries that encode to Musepack.


License

MIT — see LICENSE.

About

FLAC to Musepack converter

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages