### Create Lyrics Data Model in Kotlin Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Demonstrates how to construct a `Lyrics` object with different types of lines: word-synced, line-synced, and unsynced. Each line type requires specific timing and content details. ```kotlin import io.github.alexzhirkevich.klyrics.Lyrics import io.github.alexzhirkevich.klyrics.LyricsLine import io.github.alexzhirkevich.klyrics.LyricsWord import androidx.compose.ui.Alignment // Create word-synced lyrics with timing for each word val wordSyncedLine = LyricsLine.WordSynced( start = 5000, // Line starts at 5 seconds (in milliseconds) end = 12000, // Line ends at 12 seconds alignment = Alignment.Start, // Left-aligned (first artist) words = listOf( LyricsWord( start = 5000, end = 6000, content = "Hello", firstCharIndexInLine = 0, isBackground = false ), LyricsWord( start = 6200, end = 7500, content = "world", firstCharIndexInLine = 6, isBackground = false ), LyricsWord( start = 7700, end = 8500, content = "how", firstCharIndexInLine = 12, isBackground = false ), LyricsWord( start = 8700, end = 10000, content = "are", firstCharIndexInLine = 16, isBackground = false ), LyricsWord( start = 10200, end = 12000, content = "you", firstCharIndexInLine = 20, isBackground = false ) ) ) // Create line-synced lyrics (simpler, whole line highlights at once) val lineSyncedLine = LyricsLine.Default( start = 12500, end = 18000, alignment = Alignment.End, // Right-aligned (second artist/duet) content = "I'm doing fine today" ) // Create unsynced lyrics (always visible/focused) val unsyncedLine = LyricsLine.Unsynced( start = 0, end = 180000, alignment = Alignment.Start, content = "Written by Artist Name" ) // Combine into a Lyrics object val lyrics = Lyrics( duration = 180000, // Total track duration in milliseconds (3 minutes) lines = listOf(wordSyncedLine, lineSyncedLine, unsyncedLine) ) ``` -------------------------------- ### Implementing AudioPlayer Interface Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Implement the AudioPlayer interface using rememberAudioPlayer to manage audio playback, including initialization, play/pause, and seeking. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.rememberCoroutineScope import io.github.alexzhirkevich.klyrics.player.AudioPlayer import io.github.alexzhirkevich.klyrics.player.rememberAudioPlayer import kotlinx.coroutines.launch @Composable fun MusicPlayerScreen(trackDuration: Int) { // Create platform-specific audio player val player: AudioPlayer = rememberAudioPlayer(duration = trackDuration) val scope = rememberCoroutineScope() // Collect playback position as state val playbackPosition = player.playback.collectAsState(initial = 0) // Check if currently playing val isPlaying: Boolean = player.isPlaying // Initialize player with audio source LaunchedEffect(Unit) { // Initialize with URI player.init(uri = "https://example.com/audio.mp3") // Or initialize with ByteArray // val audioBytes: ByteArray = loadAudioFromResource() // player.init(track = audioBytes) } // Playback controls PlayButton( isPlaying = isPlaying, onPlayPause = { scope.launch { if (player.isPlaying) { player.pause() } else { player.play() } } } ) // Seek to specific time Slider( value = playbackPosition.value.toFloat(), valueRange = 0f..trackDuration.toFloat(), onValueChange = { newTime -> scope.launch { player.seek(time = newTime.toInt()) // Time in milliseconds } } ) } ``` -------------------------------- ### Complete Music Player with KLyrics Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Integrates KLyrics with an audio player, featuring UI controls for playback and synchronized lyrics display. Requires KLyrics and Compose dependencies. ```kotlin import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.lerp import androidx.compose.ui.unit.dp import io.github.alexzhirkevich.klyrics.* import io.github.alexzhirkevich.klyrics.player.rememberAudioPlayer import kotlinx.coroutines.launch @Composable fun CompleteMusicPlayer( lyrics: Lyrics, audioUri: String, songTitle: String, artistName: String ) { val player = rememberAudioPlayer(duration = lyrics.duration) val scope = rememberCoroutineScope() val playback = player.playback.collectAsState(0) val lyricsState = rememberLyricsState( lyrics = lyrics, isPlaying = { player.isPlaying } ) { playback.value } // Initialize audio LaunchedEffect(audioUri) { player.init(uri = audioUri) } Scaffold( topBar = { // Song info header Row( modifier = Modifier .fillMaxWidth() .padding(16.dp), verticalAlignment = Alignment.CenterVertically ) { Column(Modifier.weight(1f)) { Text(songTitle, style = MaterialTheme.typography.titleMedium) Text( artistName, style = MaterialTheme.typography.bodyMedium, color = LocalContentColor.current.copy(alpha = 0.6f) ) } } }, bottomBar = { // Playback controls Column( modifier = Modifier .fillMaxWidth() .padding(16.dp) ) { // Progress slider Slider( value = playback.value.toFloat(), valueRange = 0f..lyrics.duration.toFloat(), onValueChange = { scope.launch { player.seek(it.toInt()) } } ) // Time display Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween ) { Text(formatTime(playback.value)) Text(formatTime(lyrics.duration)) } // Play/Pause button FilledIconButton( onClick = { scope.launch { if (player.isPlaying) player.pause() else player.play() } }, modifier = Modifier.align(Alignment.CenterHorizontally) ) { Icon( imageVector = if (player.isPlaying) Icons.Rounded.Pause else Icons.Rounded.PlayArrow, contentDescription = null ) } } } ) { // Lyrics view val focusedColor = LocalContentColor.current val unfocusedColor = lerp( focusedColor, MaterialTheme.colorScheme.background, 0.5f ) Lyrics( state = lyricsState, focusedColor = focusedColor, unfocusedColor = unfocusedColor, modifier = Modifier.fillMaxSize(), contentPadding = PaddingValues( top = padding.calculateTopPadding() + 32.dp, bottom = padding.calculateBottomPadding() + 32.dp, start = 24.dp, end = 24.dp ), lineModifier = { idx -> Modifier.clickable { scope.launch { player.seek(lyrics.lines[idx].start) if (!player.isPlaying) player.play() } } } ) } } private fun formatTime(ms: Int): String { val seconds = (ms / 1000) % 60 val minutes = (ms / 1000) / 60 return "%d:%02d".format(minutes, seconds) } ``` -------------------------------- ### Accessing LyricsDefaults Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Access default configuration values like text styles, fade width, and autoscroll settings from LyricsDefaults. ```kotlin import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.shrinkVertically import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.github.alexzhirkevich.klyrics.LyricsDefaults import io.github.alexzhirkevich.klyrics.LyricsState // Access default values val defaultTextStyle: TextStyle = LyricsDefaults.TextStyle // TextStyle(fontSize = 32.sp, lineHeight = 38.sp, fontWeight = FontWeight.SemiBold) val endAlignedStyle: TextStyle = LyricsDefaults.TextStyleEndAligned // Same as TextStyle but with textAlign = TextAlign.End val backgroundStyle: TextStyle = LyricsDefaults.BackgroundTextStyle // TextStyle(fontSize = 16.sp, lineHeight = 20.sp, fontWeight = FontWeight.SemiBold) val fadeWidth = LyricsDefaults.Fade // 32.dp val autoscrollDelay = LyricsDefaults.AutoscrollDelay // 3.seconds val autoscrollMode = LyricsDefaults.AutoScrollMode // AutoscrollMode.Docked ``` -------------------------------- ### Initialize LyricsState with rememberLyricsState in Jetpack Compose Source: https://context7.com/alexzhirkevich/klyrics/llms.txt This composable function initializes and remembers the `LyricsState`, which manages the lyrics display, playback tracking, and auto-scroll behavior. It requires the `Lyrics` data and optionally a `LazyListState`. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.foundation.lazy.rememberLazyListState import io.github.alexzhirkevich.klyrics.Lyrics import io.github.alexzhirkevich.klyrics.LyricsState import io.github.alexzhirkevich.klyrics.rememberLyricsState @Composable fun LyricsPlayer( lyrics: Lyrics, player: AudioPlayer ) { val playback = player.playback.collectAsState(0) val lazyListState = rememberLazyListState() val lyricsState: LyricsState = rememberLyricsState( lyrics = lyrics, lazyListState = lazyListState, // Optional, will create one if not provided isPlaying = { player.isPlaying }, playbackTime = { playback.value } ) // Access state properties // lyricsState.firstFocusedLine - Index of the first currently highlighted line // lyricsState.lastFocusedLine - Index of the last highlighted line (for overlapping lines) // lyricsState.isAutoScrolling - Whether automatic scrolling is active // lyricsState.lyrics - The Lyrics object // lyricsState.lazyListState - The underlying LazyListState for manual control } ``` -------------------------------- ### Lyrics Composable Implementation Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Renders a synchronized lyrics view with animations, auto-scrolling, and customization. Use this composable to display lyrics that sync with audio playback. It requires a Lyrics object and an AudioPlayer instance. ```kotlin import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import io.github.alexzhirkevich.klyrics.AutoscrollMode import io.github.alexzhirkevich.klyrics.Lyrics import io.github.alexzhirkevich.klyrics.LyricsDefaults import io.github.alexzhirkevich.klyrics.rememberLyricsState import kotlin.time.Duration.Companion.seconds @Composable fun SongLyricsView( lyrics: Lyrics, player: AudioPlayer ) { val playback = player.playback.collectAsState(0) val lyricsState = rememberLyricsState( lyrics = lyrics, isPlaying = { player.isPlaying } // Provide a lambda to check if audio is playing ) { playback.value } // Provide a lambda to get current playback time val focusedColor = Color.White val unfocusedColor = Color.White.copy(alpha = 0.5f) Lyrics( state = lyricsState, focusedColor = focusedColor, // Color for highlighted/active lyrics unfocusedColor = unfocusedColor, // Color for inactive lyrics modifier = Modifier.fillMaxSize(), // Customize text style per line textStyle = { lineIndex -> when { lyrics.lines[lineIndex].alignment == Alignment.End -> LyricsDefaults.TextStyleEndAligned else -> LyricsDefaults.TextStyle } }, // Style for background/harmony vocals backgroundTextStyle = { baseStyle -> baseStyle.copy(fontSize = baseStyle.fontSize / 2) }, // Gradient fade width between highlighted and unhighlighted text fade = 32.dp, // Default: LyricsDefaults.Fade // Auto-scroll behavior autoscrollMode = AutoscrollMode.Docked, // Options: Docked, Continuous, or Disabled autoscrollDelay = 3.seconds, // Delay before auto-scroll resumes after user scroll // Content padding for scroll area contentPadding = PaddingValues( top = 100.dp, bottom = 80.dp, start = 16.dp, end = 16.dp ), // Per-line modifier (for click handlers, custom styling) lineModifier = { lineIndex -> Modifier.clickable { // Seek to this line when clicked coroutineScope.launch { player.seek(lyrics.lines[lineIndex].start) } } }, // Custom idle indicator for pauses/intros idleIndicator = { LyricsDefaults.IdleIndicator( index = lineIndex, state = lyricsState, focusedColor = focusedColor, unfocusedColor = unfocusedColor, radius = 8.dp, spacing = 8.dp ) } ) } ``` -------------------------------- ### Customizing Idle Indicator Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Use the default IdleIndicator composable from LyricsDefaults and customize its appearance with specific colors, radius, spacing, and animations. ```kotlin @Composable fun CustomIdleIndicator( index: Int, state: LyricsState ) { LyricsDefaults.IdleIndicator( index = index, state = state, focusedColor = Color.Cyan, unfocusedColor = Color.Gray, radius = 10.dp, // Circle radius spacing = 10.dp, // Space between circles enter = expandVertically() + fadeIn(), exit = shrinkVertically(), modifier = Modifier ) } ``` -------------------------------- ### Define JSON Data Classes for Lyrics Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Defines the data structures for parsing JSON lyrics, including song duration, lines, and words with their timings and content. Ensure these classes are annotated with @Serializable for kotlinx.serialization. ```kotlin import androidx.compose.ui.Alignment import io.github.alexzhirkevich.klyrics.Lyrics import io.github.alexzhirkevich.klyrics.LyricsLine import io.github.alexzhirkevich.klyrics.LyricsWord import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json // JSON data classes @Serializable data class JsonLyrics( val duration: Int, val lines: List ) @Serializable data class JsonLyricsLine( val start: Int, val end: Int, val singer: Int, // 1 for first artist, 2 for second val words: List ) @Serializable data class JsonLyricsWord( val start: Int, val end: Int, val content: String, val bg: Boolean = false // true for background/harmony vocals ) ``` -------------------------------- ### Parse JSON String to Lyrics Object Source: https://context7.com/alexzhirkevich/klyrics/llms.txt Converts a JSON string into a Lyrics object. This function maps the JSON data classes to the internal Lyrics data structures, calculating word timings and alignment based on singer information. ```kotlin // Parse JSON to Lyrics fun parseLyrics(jsonString: String): Lyrics { val json = Json.decodeFromString(jsonString) return Lyrics( duration = json.duration, lines = json.lines.map { var charIndex = 0 LyricsLine.WordSynced( start = it.start, end = it.end, alignment = if (it.singer == 1) Alignment.Start else Alignment.End, words = it.words.map { LyricsWord( start = it.start, end = it.end, content = it.content, firstCharIndexInLine = charIndex, isBackground = it.bg ).also { charIndex += it.content.length + 1 // +1 for space } } ) } ) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.