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

Jetpack Media3中MediaController与TextToSpeechPlayer时间轴不同步问题

Jetpack Media3 TTS播放器与MediaController时间轴不同步问题修复

核心问题根源

Media3的MediaController完全依赖Player通过Listener机制同步时间轴状态。你遇到的"初始39条最终剩1条"的问题,本质是自定义TextToSpeechPlayer在时间轴构建、状态通知或委托切换环节,没有严格遵循Media3的Player接口规范。

分步修复方案

1. 确保时间轴构建符合Media3要求

自定义Player返回的时间轴必须是不可变的ImmutableTimeline,且每个MediaItem必须携带唯一mediaId——这是MediaController识别条目唯一性的核心依据。如果你的TTS内容是39个文本片段,构建时间轴时要为每个片段生成独立的MediaItem:

// 示例:构建包含39个TTS条目的时间轴
val ttsMediaItems = List(39) { idx ->
    MediaItem.Builder()
        .setMediaId("tts_segment_$idx") // 必须唯一,不能重复
        .setUri("tts://content_$idx") // 自定义URI标识TTS片段
        .build()
}
val ttsTimeline = ImmutableTimeline(
    ttsMediaItems,
    windowCount = ttsMediaItems.size,
    shuffleModeEnabled = false,
    repeatMode = Player.REPEAT_MODE_OFF
)
// 确保Player的getTimeline()始终返回这个完整的时间轴

2. 主动触发时间轴更新通知

当自定义Player的时间轴发生变化(包括初始化设置),必须立即调用notifyListeners通知所有注册的Listener(包括MediaController):

private var currentTimeline: Timeline = EmptyTimeline()

fun setTtsMediaItems(items: List<MediaItem>) {
    currentTimeline = ImmutableTimeline(items)
    // 必须指定正确的变更原因,MediaController会根据原因处理更新
    notifyListeners { 
        onTimelineChanged(currentTimeline, Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED) 
    }
}

注意:切换委托播放器时,也要在切换完成后触发一次时间轴通知,确保MediaController感知到新的Player时间轴。

3. 规范委托播放器切换流程

切换在线MP3播放器和离线TTS播放器时,必须避免状态冲突:

  • 切换前暂停当前播放器,调用pause();
  • 切换后立即将新Player的时间轴同步,不要调用MediaController.setMediaItems()覆盖原列表(应该由自定义Player内部处理时间轴);
  • 如果新Player需要prepare(),确保在切换后调用,并触发对应的状态通知。

4. 验证Player核心方法的正确性

MediaController依赖Player的以下方法同步状态,必须确保这些方法返回正确值:

  • getTimeline():每次调用都返回完整的39条目的时间轴,不能在某些场景下返回仅含1条的时间轴;
  • getCurrentMediaItemIndex():正确返回当前播放的条目索引,避免MediaController误判播放位置;
  • getMediaItemCount():返回39,而不是1。

5. 排查MediaController的Listener生命周期

确保MediaController.addListener()在Activity/Fragment的onStart()或onResume()中注册,removeListener()在onStop()或onPause()中执行,避免Listener被意外移除导致时间轴更新无法接收。

快速调试技巧

  • 在TextToSpeechPlayer.getTimeline()方法中添加日志,记录每次调用返回的条目数量,确认是否在某些场景下返回了仅1条的时间轴;
  • 在MediaController.onTimelineChanged()回调中打印时间轴条目数,跟踪从39变为1的触发时机,定位是Player主动推送了错误时间轴,还是MediaController自身过滤了条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 00:27:32