word-timed-karaoke-lyrics
Word-timed karaoke lyrics
A word-level lyric line only stores a start time per word; there is no end time in the data. The renderer infers it as the next word's start time, falling back to the line's own end time (or a guessed duration) only for the line's last word:
data class WordTiming(
val text: String,
val startTimeMs: Long,
)
Each word then animates its own "wipe" independently, driven by a wall-clock Animatable rather than
by reading the playback clock's value directly — that split is where most of the traps live. Above
the word layer, a line degrades through three tiers: word-level wipe when per-word timestamps parse,
a flat per-line highlight when only line timestamps exist, uniform dim text when there is no sync
data. Making the tiers look like a graceful downgrade, not three renderers bolted together, is the
other half of this skill.