
Offers smart auto-detection and parsing for various lyrics formats, karaoke-ready syllable timing, translation support, and extensibility for custom formats. Includes metadata extraction.
Accompanist released a group of artifacts, including:
lyrics-core - Parsing lyrics file, holding data and exporting to other formats.
lyrics-ui - Standard lyrics interface built on Jetpack Compose
This repository hosts the lyrics-core code.
.lrc files.Add the dependency to your build.gradle.kts:
dependencies {
implementation("com.mocharealm.accompanist:lyrics-core:VERSION")
}Replace VERSION with the latest version from Maven Central.
For most use cases, AutoParser is the easiest way to parse lyrics without needing to know the format beforehand.
// 1. Get your lyrics content from a file or network
val lyricsContent: String = fetchLyrics()
// 2. Create a default AutoParser instance
val autoParser = AutoParser()
// 3. Parse the content
val lyrics = autoParser.parse(lyricsContent)
// Now you have a unified SyncedLyrics object!
println(lyrics.metadata.title)
println(lyrics.lines.first().text)Pass fallbackPhoneticProvider to AutoParser to enrich every supported format, including ordinary LRC SyncedLine captions. Standalone TTML parsing supports the same provider. SyncedLine now has optional phonetic and languageTag fields; enrichment preserves source timing, supplied captions, nested accompaniment and lyrics metadata.
Contextual providers override PhoneticProvider.resolve(PhoneticRequest). The request contains the complete original text, UTF-16 language hint ranges and requested projection ranges. Resolve the complete context once; return a line caption and ordered PhoneticProjection values. phonetic=null, aligned=true deliberately omits a caption (for example Latin text), while aligned=false means word-to-fragment alignment is unknown and requires a line caption fallback. Projection separatorBefore is formatter-owned boundary metadata, propagated to KaraokeSyllable.phoneticSeparatorBefore; renderers preserve it when merging captions. Legacy string providers remain supported. SyncedLyrics.withPhonetics(provider) exposes the same enrichment outside parsers.
If you know the exact format, you can use a specific parser directly.
val lrcLines = listOf(
"[00:39.96]I lean in and you move away",
"[00:39.96]我靠在里面,你就离开"
)
val lyrics = LrcParser.parse(lrcLines)
println(lyrics.lines)You can also use EnhancedLrcParser, TTMLParser, or LyricifySyllableParser.
Accompanist Lyrics is designed to be extensible. You can add support for any custom format by implementing the ILyricsParser interface and registering it with the AutoParser.
Create a class that implements the parsing logic for your custom format.
class MyCustomParser : ILyricsParser {
override fun canParse(content: String): Boolean {
// Check if your parser can parse or not
// Example: check for a unique tag
return content.startsWith("##MY_COOL_LYRICS##")
}
override fun parse(lines: List<String>): SyncedLyrics {
// Your parsing logic here...
}
override fun parse(content: String): SyncedLyrics {
// Your parsing logic here...
}
}Pass your custom parser to the AutoParser constructor. Custom formats are checked in the order they are provided in the list, ensuring they are prioritized over built-in ones if placed first.
// Build an AutoParser instance with your custom parser alongside built-in ones
val autoParser = AutoParser(
listOf(
MyCustomParser(), // Checked first
KugouKrcParser,
TTMLParser,
LyricifySyllableParser,
EnhancedLrcParser,
LrcParser
)
)
// This parser now understands both built-in and your custom format!
val lyrics = autoParser.parse(myCustomLyricsContent)Join the community, ask questions, and share your projects!
Contributions are welcome! Please feel free to submit a pull request or open an issue to discuss your ideas. For major changes, please open an issue first.
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
TTML supplied transliterations take precedence over generated captions. Supplied caption fragments attach to the original KaraokeSyllable.phonetic and inherit its timing. The importer groups finer metadata fragments using association hints without requiring identical timing boundaries, changing the source syllables, or exposing a separate pronunciation clock. Untimed one-to-one fragments remain supported; plain line metadata remains a line caption.
Accompanist released a group of artifacts, including:
lyrics-core - Parsing lyrics file, holding data and exporting to other formats.
lyrics-ui - Standard lyrics interface built on Jetpack Compose
This repository hosts the lyrics-core code.
.lrc files.Add the dependency to your build.gradle.kts:
dependencies {
implementation("com.mocharealm.accompanist:lyrics-core:VERSION")
}Replace VERSION with the latest version from Maven Central.
For most use cases, AutoParser is the easiest way to parse lyrics without needing to know the format beforehand.
// 1. Get your lyrics content from a file or network
val lyricsContent: String = fetchLyrics()
// 2. Create a default AutoParser instance
val autoParser = AutoParser()
// 3. Parse the content
val lyrics = autoParser.parse(lyricsContent)
// Now you have a unified SyncedLyrics object!
println(lyrics.metadata.title)
println(lyrics.lines.first().text)Pass fallbackPhoneticProvider to AutoParser to enrich every supported format, including ordinary LRC SyncedLine captions. Standalone TTML parsing supports the same provider. SyncedLine now has optional phonetic and languageTag fields; enrichment preserves source timing, supplied captions, nested accompaniment and lyrics metadata.
Contextual providers override PhoneticProvider.resolve(PhoneticRequest). The request contains the complete original text, UTF-16 language hint ranges and requested projection ranges. Resolve the complete context once; return a line caption and ordered PhoneticProjection values. phonetic=null, aligned=true deliberately omits a caption (for example Latin text), while aligned=false means word-to-fragment alignment is unknown and requires a line caption fallback. Projection separatorBefore is formatter-owned boundary metadata, propagated to KaraokeSyllable.phoneticSeparatorBefore; renderers preserve it when merging captions. Legacy string providers remain supported. SyncedLyrics.withPhonetics(provider) exposes the same enrichment outside parsers.
If you know the exact format, you can use a specific parser directly.
val lrcLines = listOf(
"[00:39.96]I lean in and you move away",
"[00:39.96]我靠在里面,你就离开"
)
val lyrics = LrcParser.parse(lrcLines)
println(lyrics.lines)You can also use EnhancedLrcParser, TTMLParser, or LyricifySyllableParser.
Accompanist Lyrics is designed to be extensible. You can add support for any custom format by implementing the ILyricsParser interface and registering it with the AutoParser.
Create a class that implements the parsing logic for your custom format.
class MyCustomParser : ILyricsParser {
override fun canParse(content: String): Boolean {
// Check if your parser can parse or not
// Example: check for a unique tag
return content.startsWith("##MY_COOL_LYRICS##")
}
override fun parse(lines: List<String>): SyncedLyrics {
// Your parsing logic here...
}
override fun parse(content: String): SyncedLyrics {
// Your parsing logic here...
}
}Pass your custom parser to the AutoParser constructor. Custom formats are checked in the order they are provided in the list, ensuring they are prioritized over built-in ones if placed first.
// Build an AutoParser instance with your custom parser alongside built-in ones
val autoParser = AutoParser(
listOf(
MyCustomParser(), // Checked first
KugouKrcParser,
TTMLParser,
LyricifySyllableParser,
EnhancedLrcParser,
LrcParser
)
)
// This parser now understands both built-in and your custom format!
val lyrics = autoParser.parse(myCustomLyricsContent)Join the community, ask questions, and share your projects!
Contributions are welcome! Please feel free to submit a pull request or open an issue to discuss your ideas. For major changes, please open an issue first.
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
TTML supplied transliterations take precedence over generated captions. Supplied caption fragments attach to the original KaraokeSyllable.phonetic and inherit its timing. The importer groups finer metadata fragments using association hints without requiring identical timing boundaries, changing the source syllables, or exposing a separate pronunciation clock. Untimed one-to-one fragments remain supported; plain line metadata remains a line caption.