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

如何通过ExoPlayer SubtitleView同步展示音频歌词?(v2.18.3)

ExoPlayer 2.18.3 实现音频歌词同步显示方案

针对你遇到的SubtitleView无法同步展示歌词的问题,核心是需要把自定义JSON格式的歌词转换成ExoPlayer可识别的字幕源,以下是具体实现步骤:

1. 解析JSON歌词数据

首先从目标JSON数据源提取歌词条目,每条歌词需包含时间戳与文本内容。假设JSON结构如下:

{
  "lyrics": [
    {"time": 1000, "text": "第一句歌词"},
    {"time": 3000, "text": "第二句歌词"}
    // 更多歌词条目
  ]
}

解析时将时间戳转换为ExoPlayer使用的微秒(1毫秒=1000微秒),示例代码(Kotlin + Gson):

data class LyricItem(val time: Long, val text: String)
data class SongData(val lyrics: List<LyricItem>)

private fun parseLyricsJson(jsonContent: String): List<LyricItem> {
    return Gson().fromJson(jsonContent, SongData::class.java).lyrics
}

2. 构造ExoPlayer兼容的字幕源

将解析后的歌词列表转换为SpannedSubtitle,并通过SingleSubtitleSource封装:

private fun createLyricSubtitleSource(lyricItems: List<LyricItem>): SingleSubtitleSource {
    val subtitleCues = mutableListOf<Cue>()
    lyricItems.forEachIndexed { index, item ->
        val startTimeUs = item.time * 1000
        // 下一句歌词的时间作为当前句的结束时间,最后一句持续到音频结束
        val endTimeUs = if (index < lyricItems.size - 1) {
            lyricItems[index + 1].time * 1000
        } else {
            Long.MAX_VALUE
        }
        val cue = Cue.Builder()
            .setText(item.text)
            .setStartTimeUs(startTimeUs)
            .setEndTimeUs(endTimeUs)
            .build()
        subtitleCues.add(cue)
    }
    val subtitle = SpannedSubtitle(subtitleCues)
    return SingleSubtitleSource(
        subtitle,
        Format.createTextSampleFormat(
            id = "lyric-track",
            mimeType = MimeTypes.TEXT_VTT,
            selectionFlags = C.SELECTION_FLAG_DEFAULT
        )
    )
}

3. 将字幕源附加到音频MediaItem

创建音频MediaItem时,把自定义字幕源添加到轨道信息中:

// 替换为你的音频Uri
val audioUri = Uri.parse("your-audio-url")
val parsedLyrics = parseLyricsJson(jsonContentFromSource)

val mediaItem = MediaItem.Builder()
    .setUri(audioUri)
    .addMediaSource(createLyricSubtitleSource(parsedLyrics))
    .build()

exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()

4. 配置SubtitleView并关联播放器

在布局中添加SubtitleView:

<com.google.android.exoplayer2.ui.SubtitleView
    android:id="@+id/subtitleView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:padding="16dp"
    app:subtitleTextColor="#FFFFFF"
    app:subtitleTextSize="22sp" />

代码中关联ExoPlayer:

val subtitleView = findViewById<SubtitleView>(R.id.subtitleView)
subtitleView.setPlayer(exoPlayer)
// 可选:自定义字幕样式
subtitleView.setStyle(R.style.CustomSubtitleStyle)

关键注意点

  • 确认JSON中的时间戳单位(毫秒/秒),转换时需对应调整为ExoPlayer的微秒单位
  • 若歌词包含富文本(如换行、颜色),可使用Html.fromHtml()生成Spanned文本传入Cue
  • 若字幕仍不显示,检查:
    • 字幕时间范围是否与音频时长匹配
    • Format的mimeType是否设置正确(如MimeTypes.TEXT_VTT)
    • SubtitleView是否已正确关联到ExoPlayer

内容的提问来源于stack exchange,提问作者YellowC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:58:16