Kotlin实现:根据播放位置匹配Spotify歌词API对应歌词行
Kotlin实现Spotify歌词行匹配逻辑
核心逻辑:Spotify返回的歌词切换时间数组是严格递增的(按歌词播放顺序排列),我们需要找到数组中小于等于当前播放位置的最大时间戳,其对应的索引就是当前要显示的歌词行——这和你之前找"小于播放位置的最小值"的思路完全相反,这也是你拿到第一个元素的原因。
以下是两种实用实现方式:
1. 遍历法(简单直观,适合小容量数组)
fun findCurrentLyricIndex(playbackPositionMs: Long, lyricTimestamps: List<Long>): Int { var currentIndex = 0 // 从第二个元素开始遍历,默认初始行是第一个元素 for (i in 1 until lyricTimestamps.size) { // 播放位置未达到下一行的切换时间,停止遍历 if (playbackPositionMs < lyricTimestamps[i]) { break } currentIndex = i } return currentIndex }
逻辑说明:逐个检查后续时间戳,只要播放位置还没到下一行的切换点,就更新当前行索引,直到找到第一个大于播放位置的时间戳,此时的索引就是目标歌词行。
2. 二分查找法(高效,适合大容量数组)
因为时间戳数组是有序的,用二分查找能将时间复杂度降到O(log n),比遍历的O(n)效率更高:
fun findCurrentLyricIndexBinarySearch(playbackPositionMs: Long, lyricTimestamps: List<Long>): Int { var low = 0 var high = lyricTimestamps.size - 1 var result = 0 while (low <= high) { val mid = (low + high) / 2 when { lyricTimestamps[mid] == playbackPositionMs -> return mid lyricTimestamps[mid] < playbackPositionMs -> { // 当前时间戳符合条件,记录索引后继续找更大的匹配值 result = mid low = mid + 1 } else -> high = mid - 1 } } return result }
逻辑说明:通过不断缩小查找范围,快速定位到最大的、小于等于播放位置的时间戳索引。
注意事项
- 确保
lyricTimestamps是升序排列的,Spotify API返回的数组默认满足此条件,无需额外排序 - 自动处理边界场景:播放位置小于所有时间戳(歌曲刚开始)返回0;大于所有时间戳(歌曲结尾)返回最后一个索引
- 可直接配合播放器每50ms的位置更新调用,两种实现的性能都能满足需求
内容的提问来源于stack exchange,提问作者Bobby ESP
相关产品推荐
相关产品推荐

