You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:35:26