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.
- 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.tomlfile - 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
- Python 3.9+
- Dependencies:
pip install -r requirements.txt
FFmpeg is used to decode FLAC to WAV, which is then piped into mpcenc.
macOS (Homebrew)
brew install ffmpegUbuntu / Debian
sudo apt install ffmpegArch Linux
sudo pacman -S ffmpegFFmpeg 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_bininconfig.toml— pins an exact binary and disables automatic discovery.- A sibling
../musicpack/build/mpcenc/mpcencor../musicpack/build-static/mpcenc/mpcenc. mpcencfrom yourPATH(e.g. Homebrewmusepackor distromusepack-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 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
.mpcvia 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 rsgainUbuntu / Debian
sudo apt install rsgainArch Linux
sudo pacman -S rsgainManual 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 = falsein[loudness]and rsgain is not required.
git clone https://github.com/whepper/flac2mpc.git
cd flac2mpc
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtCopy and edit config.toml:
cp config.toml my_config.toml[paths]
input_dir = "/music/flac"
output_dir = "/music/mpc"
ffmpeg_bin = "ffmpeg"
mpcenc_bin = "mpcenc"
rsgain_bin = "rsgain"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 exampleLeave 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.
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/RAMDiskIn 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# 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| 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 |
| 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 |
| 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) |
| 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.
| 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 |
| 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.
| 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.
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
ARTISTorPERFORMERentries 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/totalform when a total is known (tracktotal/totaltracks,disctotal/totaldiscs, or the combinedn/totalform in the number itself) and tonalone otherwise —7/0is 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 byflac2mpc. - 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.
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
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)
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.
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.
git clone https://github.com/whepper/flac2mpc.git
cd flac2mpcpython3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -r requirements-gui.txtbrew install ffmpeg rsgainFor 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/buildmkdir -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 || trueAlternatively, download pre-built binaries directly:
Portability caveat: Homebrew's
ffmpegandrsgainare dynamically linked against/opt/homebrew/...dylibs. Bundling them this way works on the machine that built the app, but the resulting.appwill not run on a Mac without the same Homebrew libraries installed. Only the MusicPackmpcenc/mpcdec(and alibmpcdecstatic build) ship fully static. For a truly self-contained app, replacevendor/ffmpegandvendor/rsgainwith static builds (compile FFmpeg statically, and download a static rsgain binary from the releases page above).If a Homebrew
rsgainfails to start with aLibrary not loaded: .../libavformat.X.dyliberror, 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.
pyinstaller flac2mpc_gui.specPyInstaller 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.appThe finished app is at dist/flac2mpc.app. Drag it to /Applications or
double-click it directly — no terminal needed.
Note: The
.venvmust be active when runningpyinstallerso it can find all installed packages. If you open a new terminal session, runsource .venv/bin/activateagain 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.specThe ad-hoc signature above is fine for local use. Distributing the app to other Macs requires a Developer ID signature plus notarization.
You can also run the GUI directly from the project directory (no PyInstaller needed):
source .venv/bin/activate
python gui.pyFFmpeg, 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.
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.
MIT — see LICENSE.