Skip to main content

Convert M4A and TTML lyric files to Enhanced LRC (word-by-word karaoke format)

Project description

lrc-maker

Convert M4A and TTML lyric files into Enhanced LRC — the word-by-word karaoke format supported by players like Poweramp, Plexamp, foobar2000, and others.

Lyrics are sourced from LyricsPlus (Apple Music, Spotify, Musixmatch) with Musixmatch as a fallback. No Apple Music or Spotify credentials required.


Features

  • 🎵 Word-by-word Enhanced LRC from Apple Music TTML data
  • 🔄 Automatic fallback chain: Apple Music → Spotify → Musixmatch (word) → Musixmatch (line)
  • 🏷️ Full metadata in LRC headers: artist, album, year, genre, ISRC, composer, etc.
  • 📁 Batch processing — point at a folder and convert everything recursively
  • 🔍 Smart matching — handles accented characters, smart quotes, featured artists
  • 📄 TTML support — convert raw Apple Music .ttml files directly

Installation

From PyPI (once published)

pip install lrc-maker

From source

git clone https://github.com/YOUR_USERNAME/lrc-maker.git
cd lrc-maker
pip install -e .

Requirements: Python 3.10+, mutagen (installed automatically)


Usage

M4A → Enhanced LRC

Convert a single file or an entire music folder:

# Single file
m4a-to-lrc "path/to/song.m4a" --musixmatch-token-file data.json

# Entire folder (recursive)
m4a-to-lrc "G:\Music\Apple Music" --musixmatch-token-file data.json

# Overwrite existing .lrc files
m4a-to-lrc "G:\Music" --musixmatch-token-file data.json --overwrite

# Preview without writing files
m4a-to-lrc "G:\Music" --musixmatch-token-file data.json --dry-run

Example output:

Converted [Apple (word)]:      Cigarettes After Sex - Apocalypse -> ...lrc
Converted [Apple (line)]:      Cigarettes After Sex - Affection -> ...lrc
Converted [Spotify (word)]:    The Marías - Blur -> ...lrc
Converted [Musixmatch (word)]: Some Track -> ...lrc
Converted [Musixmatch (line)]: Some Track -> ...lrc
Done. 27 file(s) processed, 0 failed.

The label in brackets tells you the source and timing type:

Label Meaning
Apple (word) Apple Music TTML, word-by-word ✨ best quality
Apple (line) Apple Music, line-by-line
Spotify (word) Spotify synced, word-by-word
Spotify (line) Spotify synced, line-by-line
Musixmatch (word) Musixmatch RichSync, word-by-word
Musixmatch (line) Musixmatch Subtitle, line-by-line

TTML → Enhanced LRC

Convert raw Apple Music .ttml files:

# Single file
ttml-to-lrc "song.ttml"

# Folder
ttml-to-lrc "path/to/ttml/folder" --overwrite

# With Musixmatch RichSync as primary source
ttml-to-lrc "path/to/ttml/folder" --musixmatch-token-file data.json --overwrite

Getting a Musixmatch Token

The Musixmatch token is used as a fallback when LyricsPlus can't find a track. To get one:

  1. Open musixmatch.com in your browser
  2. Open DevTools → Network tab
  3. Search for any song and filter requests by apic-desktop
  4. Copy the usertoken value from any request URL
  5. Save it to data.json:
{
  "tokens": {
    "web-desktop-app-v1.0": "YOUR_TOKEN_HERE"
  }
}

How It Works

m4a-to-lrc
    │
    ▼
Read M4A tags (artist, title, album, year, genre, ISRC, ...)
    │
    ▼
LyricsPlus API  ──► Apple Music TTML  (word-by-word) ✨
(no auth)       ──► Spotify           (word or line)
                ──► Musixmatch        (word or line)
                ──► own cache
    │
    │  if nothing found
    ▼
Musixmatch API  ──► RichSync  (word-by-word)
(token needed)  ──► Subtitle  (line-by-line)
    │
    ▼
Write .lrc file next to the .m4a

Artist and title are read from the M4A tags. If tags are missing, the filename is parsed as Artist - Title.m4a. Multiple candidate spellings are tried (smart quotes → straight, accented → ASCII, strip featured artist credits) to maximise match rate.


LRC Format

Enhanced LRC files look like this:

[ar:Cigarettes After Sex]
[ti:Apocalypse]
[al:Cigarettes After Sex]
[yr:2017]
[re:lyricsplus-apple]

[00:13.15]<00:13.15>Oh <00:13.55>it <00:13.80>was <00:14.20>the <00:14.50>night
[00:16.80]<00:16.80>Things <00:17.10>were <00:17.40>different

Each [timestamp] is the line start; each <timestamp>word is when that individual word is sung.


Project Structure

lrc-maker/
├── src/lrc_maker/
│   ├── __init__.py
│   ├── m4a_to_elrc.py   # M4A → LRC (LyricsPlus + Musixmatch)
│   └── ttml_to_elrc.py  # TTML → LRC (direct parse + optional Musixmatch)
├── pyproject.toml
├── README.md
└── LICENSE

Contributing

Pull requests welcome. Please open an issue first for significant changes.


License

MIT — see LICENSE.


Credits

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lrc_maker-0.2.0.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lrc_maker-0.2.0-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

Details for the file lrc_maker-0.2.0.tar.gz.

File metadata

  • Download URL: lrc_maker-0.2.0.tar.gz
  • Upload date:
  • Size: 18.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for lrc_maker-0.2.0.tar.gz
Algorithm Hash digest
SHA256 54c27463f56a594c2da9f3bd4995b0049842df869d8fdcc48493be7b1fa1978c
MD5 28142aceff1d83a170a4f0e3ce92ee76
BLAKE2b-256 1ddeb3da07848caa58caf8907d12f967c40be9cf8c709ab1d6f0a6bf156c1c25

See more details on using hashes here.

File details

Details for the file lrc_maker-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: lrc_maker-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 17.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for lrc_maker-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1ff53314d16b34a4c1c1e7a983fd166614e2d7b57ccb3ab7f5888fb6b57147a1
MD5 977ae01659f6af55d3e36cfc762091c9
BLAKE2b-256 5476d76b074e8efbb76d8726a038f7c4ddbc088c5d7bb8c56f1756c0df6dac59

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page