There's a few variations to cover, including unsynced lyrics for completeness:
- unsynced vs synchronized (also called time-synced or "Live Lyrics")
- 3rd-party apps vs Apple-specific Music apps, like iTunes
- MP3 files vs MP4 containers (M4A is audio-only MP4)
Unsynced lyrics
Unsynced lyrics are fairly easy. You can use the iTunes / Apple Music context menu => "Get Info" and paste in a block of text, which for MP3 files is an ID3 v2.something tag (USLT
, which you can see in the eyeD3 Python library (contrast with SYLT
for synced lyrics)).
- This
lrcput.py
script shows how to use the Python libraries "eyed3" for MP3 files, and "mutagen" to embed them into FLAC.
- MP4 containers are handled similarly, the mutagen MP4 API is nearly identical to its FLAC API.
3rd-party apps
For a non-iTunes app, you can generally download .lrc files for synchronized and name them similarly to the audio file, and the apps wil pick them up (see LRCGET, which uses https://lrclib.net/ to get lyrics).
Synced lyrics with Apple Music
Testing with various MP3 files with synchronized lyrics doesn't show any lyrics at all in Apple Music (source files from this 2021 blog). Unsynchronized lyrics show up fine. Ominously, Apple support docs mention that you won't have access to Live Lyrics without an Apple Music subscription.
Now for the original thing I was trying to do, Apple Music + M4A files: Apple currently uses Musixmatch to provide synchronized lyrics, which looks like anyone can submit lyrics to. These seem to be provided in TTML format, and are then made available to Apple Music subscribers.
Technical notes:
To apply synced lyrics to your local M4A files, it looks like you'll need to put them in the iTunes-specific "\xa9lyr"
field (mutagen docs), and I think these same field names are used in MP3 ID3 tags, as well.
There exists at least one GitHub project that can read content profiles (including TTML data) from Apple Music and somehow embeds it in your audio files. On closer inspection, this project seems to be embedding unsynced lyrics:
api.api.getInfo()
calls Apple Music, passes the response to…
api.parse.parseJson()
, and the data-synced lyrics are in data["relationships"]["lyrics"]["data"][0]["attributes"]["ttml"]
.
- But when tagging actual files,
core.process.tagger.tag()
seems to be pulling lyrics from data["streams"][i]["lyrics"]
.
Outright embedding the contents of a full .lrc or .ttml with mutagen doesn't seem to work, though. I would guess that for Apple Music, synchronized lyrics are brought in through some side channel via the Apple Music subscription service.
mov_text
..m4a
file extension.