A2 Player Verification¶
output.word_sync_mode can put per-word ("A2" / Enhanced LRC) timing markers into
a .lrc file (replace; see Configuration).
Support for those markers is not universal, and the failure mode is three-way,
not two-way: a player can render them, silently ignore them, or display them as
literal text mixed into the lyrics. Only the third is visibly broken. This page
is the procedure for finding out which of the three your player does, before you
turn replace on for a whole library.
If you only want word timings kept without touching the .lrc at all, use the
default both mode instead: it writes the markers to a companion .elrc
file and leaves every .lrc exactly as it would be with word sync off. Nothing
in this procedure applies to both or off -- there is nothing in the .lrc
for a player to misinterpret. (sidecar and inline are deprecated aliases
for both and replace, #1072.)
1. Get a word-synced track¶
Word-level timings come from two lanes today: Musixmatch (via its bundled richsync call, most commonly on synced results) and Petit Lyrics' word-synced tier. Not every track that has line-synced lyrics also has word timings, so picking a track at random from your library and getting no markers at all does not mean anything is broken -- it may simply mean neither lane served word data for that track.
Set output.word_sync_mode to replace, then fetch or re-fetch a single album. Confirm at least one resulting
.lrc actually carries <mm:ss.cc> markers before moving on -- that is your
positive sample.
Note that a line whose words all share one timestamp is refused for markers by
design (see a2Words in internal/lyrics/a2.go): that line falls back to a
plain line-level cue instead of claiming per-word detail the data does not
carry. On one verified word-synced track, 10 of 86 lines fell into this
category, so it is normal and expected for some lines in your sample .lrc to
have no markers even though the file overall is word-synced. Confirm those
lines still play as ordinary line-synced cues, not as broken output -- that
fallback path is part of what this procedure is verifying.
2. Play it in your target player and classify the result¶
Copy the .lrc (and its audio) to wherever your player reads from, play the
track, and watch the lyric display. First confirm the player shows lyrics at
all for an ordinary line-synced .lrc. If no lyrics appear, the test is
inconclusive: fix how the player finds the file before judging A2 support.
Once lyrics load, there are exactly three outcomes:
- Highlights per word. The player understands A2. This is the intent of
replace, and you can enable it for that player's library. - Markers silently absent, plain line-sync shown. The player does not
understand A2 but degrades gracefully. Harmless:
replacecosts you nothing extra here, but it also does not do anything the defaultbothmode's clean.lrcdid not already do. You may as well useboth. - Markers rendered as literal text, e.g.
<00:12.34>wordshowing up in the displayed lyric line. Visibly broken. Do not enablereplacefor this player. Usebothoroffinstead.
3. Optional pre-check: lrcsong.com¶
lrcsong.com accepts A2-format .lrc files and will tell
you whether the file itself parses as well-formed A2. Use it only to separate
"our file is malformed" from "this player lacks support" before you spend time
blaming a player. It cannot substitute for step 2: by its own documentation it
highlights at line granularity, so a file that fails there is informative, but a
file that passes there tells you nothing about whether a given player renders
word-level detail.
What is known so far¶
No player in this table is a verified positive control (confirmed to render A2 word-level highlighting). Confidence varies sharply between rows; read the confidence column, not just the verdict.
| Player | Verdict | Confidence |
|---|---|---|
| Music Assistant | does not support | solid -- maintainer's own bug report, 2026-07-15 |
| Symfonium | strips markers (expect clean line-sync) | forum-sourced, ~3 years stale, unverified against current build |
| Emby | unknown | nothing found |
| foobar2000 | UNVERIFIED | see below |
foobar2000 has no built-in lyrics display; lyrics come from the third-party
foo_openlyrics component, whose README never mentions word-level, Enhanced
LRC, karaoke, or angle-bracket timestamps, and whose component
page lists
supported systems as Windows 32-bit and Windows 64-bit only -- it is not an
option on foobar2000 for Mac at all. An earlier claim that foobar2000 was a
confirmed-supporting positive control was wrong: it traced back to a format
guide's general compatibility list, a secondary source about the LRC format in
general, not evidence about this specific plugin.
If you verify a player against this procedure, the result belongs in this table (with its confidence noted) rather than assumed elsewhere.
Format notes and known limits¶
These describe the files Canticle writes, whichever player reads them.
The last word's end time. A word-timed line ends with one more tag that has
no word after it, for example [00:01.50]<00:01.50>alpha <00:02.00>beta<00:02.50>.
Readers that understand word tags take it as the time the last word ends, so
the highlight on that word stops there instead of staying on until the next
line starts. The tag is left out when the provider gave no end later than the
word's start, or when the two stamps are equal at the file's hundredths
precision (a 2000 to 2009 ms word gets no tag). Files written before this was added do not have the tag, and
Canticle does not go back and add it: an older word-timed file gains it only
when that file is next rewritten (a re-fetch, an upgrade, or a word-timing
re-check that lands). Until then old and new files differ by that one tag per
line, and both are valid.
The end tag is the provider's own end time for the last word. Canticle does not cap it at the next line's start, so it can run past it if the provider's data does.
Under word_sync_mode = "replace" with output.bump_audio_mtime on, an older
word-timed .lrc gets one audio-mtime bump the first time it is rewritten,
because its body now differs by the tag. The default both is unaffected (the
.lrc carries no tags, so only the .elrc changes).
Checked against Navidrome v0.64.2's own lyrics parser (the parser only, not a server with a client attached): with the tag, the last word of a line ends at the tag's time; without it, the same word runs until the next line starts. One exception in that parser: when the file ends with a newline (Canticle's always do), the tag on the very last line of the file is not used, so that one line reads exactly as it did before the tag existed. Nothing is shown as text and no word is lost.
Tracks of 100 minutes or more. Canticle writes minutes without wrapping, so
a cue at 100 minutes is [100:00.00]. Navidrome accepts one or two minute
digits, does not read that as a timestamp, and joins the line onto the previous
lyric as text. This affects the plain .lrc as well as the .elrc, and only
cues at 100:00 or later. There is no spelling every reader accepts (Navidrome
would take [hh:mm:ss.xx], which Jellyfin's parser does not), so the writer
is left as it is.
replace needs a reader that understands inline word tags. replace puts
the word tags in the plain .lrc. A reader without Enhanced LRC support shows
them as raw text. Navidrome reads them from 0.63; on an older Navidrome, or any
other reader you have not checked with the procedure above, use the default
both, which keeps the .lrc free of tags.
What this procedure does not cover¶
There is no automated (e.g. browser-driven) classifier for this, and none is planned: the players above are native desktop/mobile/server clients, not browser surfaces, and the one web tool available (lrcsong.com) is disqualified as a positive control for the reason given in step 3. A synthetic audio fixture built from the same timings a renderer emits was tried and discarded as tautological -- it can only prove the renderer agrees with itself, not that a real player supports A2. There is no shortcut around actually playing a word-synced file in the target player.
Privacy note¶
If you share a result from this procedure (an issue, a forum post, a
screen recording), use a public-domain or synthetic-text track. Do not post
.lrc content, screenshots, or descriptions that reveal titles from a private
library.