1. ExoPlayer 音轨架构概览:TrackSelector、MediaSource、Renderer、音轨组与轨道格式
ExoPlayer 的音轨切换能力建立在 四层核心组件 之上:TrackSelector、MediaSource、Renderer,以及底层的数据抽象——音轨组与轨道格式(MimeType)。理解这四者的职责与协作关系,是掌握音轨边界切换的前提。
关键认识:ExoPlayer 的“音轨”并非单一视频或音频流,而是由
TrackGroup 组织的一组可选轨道,TrackSelector 根据应用策略动态选出最佳组合。
1.1 四层组件职责概览
| 组件 | 职责 | 与音轨切换的关系 |
|---|---|---|
| TrackSelector | 选择播放器应使用的轨道(视频/音频/字幕)组合 | 切换时重新评估轨道,触发 onTrackSelectionsChanged |
| MediaSource | 提供媒体流的数据源,解析并暴露可用轨道信息 | 负责创建 TrackGroupArray,供 Selector 决策 |
| Renderer | 渲染指定轨道的媒体数据(音频、视频、字幕) | 接收 Selector 选中的 TrackSelection,缓冲并输出 |
| TrackGroup / TrackFormat | 描述一组同质轨道(如多语言音频)与单个轨道的编解码参数 | 通过 MimeType 区分轨道类型,切换时比对映射 |
1.2 协作流程图(第 1 章核心 SVG)
1.3 深入组件细节
1.3.1 TrackSelector —— 决策引擎
- 继承
DefaultTrackSelector可获得默认音视频字幕选择逻辑。 - 核心接口:
selectTracks(RendererCapabilities[], TrackGroupArray)返回TrackSelection[]。 - 音轨边界切换本质是重新触发
selectTracks并应用新选中的TrackSelection。
1.3.2 MediaSource —— 轨道信息提供者
- 常见实现:
DashMediaSource、HlsMediaSource、ProgressiveMediaSource。 - 每个 MediaSource 在预处理阶段(
prepareSource)解析清单,构造TrackGroupArray。 - 一个
TrackGroup包含多个相同类型、不同比特率/语言/角度的轨道。
1.3.3 Renderer —— 轨道消费者
- 每种媒体类型对应一个 Renderer:
MediaCodecVideoRenderer、MediaCodecAudioRenderer、TextRenderer。 - Renderer 通过
RendererCapabilities向 TrackSelector 声明支持的 MimeType 与格式。 - 切换音轨时,Renderer 会 flush 当前缓冲,重新从新选中的 Track 读取数据。
1.3.4 TrackGroup 与 MimeType
- TrackGroup:
com.google.android.exoplayer2.source.TrackGroup,包含多个Format。 Format中包含关键字段:sampleMimeType(如"audio/mp4a-latm")、language、bitrate等。- MimeType 是区分音视频字幕的核心标识:常见有
video/avc、audio/opus、text/vtt。
实践要点:调试音轨切换时,打印
TrackGroupArray 中的每个 TrackGroup 及内部 Format 的 MimeType,能快速定位是解析失败还是选择逻辑未命中。
1.4 常见错误与调优提示
| 错误场景 | 原因 | 解决方向 |
|---|---|---|
| 切换后无声 / 黑屏 | Renderer 未正确接收新 TrackSelection,或缓冲未清空 | 检查 onTrackSelectionsChanged 回调是否触发 |
| MimeType 不匹配 | MediaSource 暴露的格式与 Renderer 声明的支持列表不一致 | 确保 Renderer 注册时包含所需的 MimeType |
| 选择器忽略某些音轨 | TrackSelector 配置了语言/比特率过滤条件 | 暂时禁用过滤,观察 TrackGroupArray 中的完整轨道 |