FLAC is lossless (~50% smaller than WAV); MP3 is lossy (~10% the size of FLAC at 192k). The conversion is straightforward — every option calls libmp3lame underneath. The interesting choices are bitrate (320k for archival, 192k web standard, 128k voice) and tag preservation (rarely automatic).

Method 1: pydub (easiest, FFmpeg-backed)

pydub is the most ergonomic Python audio library. Wraps FFmpeg under the hood with a clean API.

pip install pydub
apt install ffmpeg  # required
from pydub import AudioSegment

def flac_to_mp3(in_path: str, out_path: str, bitrate: str = "192k") -> None:
    audio = AudioSegment.from_file(in_path, format="flac")
    audio.export(out_path, format="mp3", bitrate=bitrate)

flac_to_mp3("album_track.flac", "album_track.mp3")

Bitrate guide:

  • 320k — max MP3 quality. ~2.4 MB/min stereo. Use for music archival.
  • 192k — high-quality, transparent for most listeners. ~1.4 MB/min. Web standard.
  • 128k — mediocre for music, fine for voice. ~0.95 MB/min.
  • 96k mono — voice/podcast quality. ~0.35 MB/min.

For variable bitrate (better quality at the same average size), pass parameters=['-q:a', '2'] instead of bitrate (q ranges 0-9, lower = better).

Method 2: With ID3 tag preservation (mutagen)

FLAC files have Vorbis-comment tags. MP3 needs ID3v2 tags. mutagen reads both and lets you copy across.

pip install pydub mutagen
apt install ffmpeg
from pydub import AudioSegment
from mutagen.flac import FLAC
from mutagen.id3 import ID3, TIT2, TPE1, TALB, TDRC, TRCK, APIC
from mutagen.mp3 import MP3

FLAC_TO_ID3 = {
    "title": TIT2,
    "artist": TPE1,
    "album": TALB,
    "date": TDRC,
    "tracknumber": TRCK,
}

def flac_to_mp3_with_tags(in_path: str, out_path: str, bitrate: str = "192k") -> None:
    # Convert audio
    audio = AudioSegment.from_file(in_path, format="flac")
    audio.export(out_path, format="mp3", bitrate=bitrate)

    # Copy tags
    flac_meta = FLAC(in_path)
    mp3 = MP3(out_path, ID3=ID3)
    if mp3.tags is None:
        mp3.add_tags()

    for flac_key, id3_class in FLAC_TO_ID3.items():
        if flac_key in flac_meta:
            mp3.tags.add(id3_class(encoding=3, text=flac_meta[flac_key][0]))

    # Embedded cover art
    if flac_meta.pictures:
        pic = flac_meta.pictures[0]
        mp3.tags.add(APIC(
            encoding=3,
            mime=pic.mime,
            type=pic.type,
            desc="Cover",
            data=pic.data,
        ))

    mp3.save()

flac_to_mp3_with_tags("album_track.flac", "album_track.mp3")

Cover art (album image) embedded in FLAC is preserved via APIC frames. Most players show this in their now-playing UI.

Method 3: ChangeThisFile API (no FFmpeg, tags included)

If you don't want FFmpeg in your environment, the API runs FFmpeg server-side and copies tags automatically. Free tier covers 1,000 conversions/month.

import requests

API_KEY = "ctf_sk_your_key_here"

def flac_to_mp3(in_path: str, out_path: str, bitrate: int = 192) -> None:
    with open(in_path, "rb") as f:
        response = requests.post(
            "https://changethisfile.com/v1/convert",
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": f},
            data={
                "source": "flac",
                "target": "mp3",
                "bitrate": bitrate,
            },
            timeout=120,
        )
    response.raise_for_status()
    with open(out_path, "wb") as out:
        out.write(response.content)

flac_to_mp3("album_track.flac", "album_track.mp3", bitrate=192)

Tags (artist, album, title, year, track number, cover art) are copied across automatically. Pass strip_tags=true to skip tag transfer.

When to use each

ApproachBest forTradeoff
pydubMost cases — easiest API, fast prototypingDoesn't preserve tags (use mutagen separately)
pydub + mutagenMusic libraries with tag preservationTwo libraries, manual tag mapping
ChangeThisFile APINo FFmpeg, automatic tag transferNetwork call, file size limit (25MB free)

Production tips

  • 192k is the right default for music. Indistinguishable from FLAC for almost all listeners. 320k for audiophile-grade or master archives.
  • Use VBR for music collections. -q:a 2 gives ~190k average with better quality on complex passages and smaller files on simple ones. CBR is for streaming protocols that need predictable bitrate.
  • Always preserve tags for music libraries. Without tags, the MP3 shows as 'Unknown Artist - Unknown Album' in players. Tag transfer is non-optional for end-user music.
  • For batch jobs, use ProcessPoolExecutor. FFmpeg encoding releases the GIL but pydub adds Python overhead. Process pools parallelize cleanly across cores.
  • Watch FLAC sample rates above 48kHz. Some FLACs are 96kHz/192kHz (audiophile masters). MP3 maxes at 48kHz; FFmpeg auto-downsamples. Quality loss is minimal but audible to trained ears.

For one-off conversions, pydub is the right answer. For music libraries, add mutagen for tag preservation. For environments without FFmpeg, the API. Free tier covers 1,000 conversions/month.