跳到主要内容

ExoPlayer 与 Media3

问题

ExoPlayer 的架构是什么?Media3 有什么变化?

答案

ExoPlayer 架构

Media3 基本使用

// Media3 = ExoPlayer + MediaSession + UI 统一到 androidx.media3
val player = ExoPlayer.Builder(context)
.setTrackSelector(DefaultTrackSelector(context).apply {
setParameters(buildUponParameters().setMaxVideoSizeSd())
})
.setLoadControl(DefaultLoadControl.Builder()
.setBufferDurationsMs(
/* minBuffer */ 15_000,
/* maxBuffer */ 50_000,
/* playbackBuffer */ 2_500,
/* rebuffer */ 5_000
).build()
)
.build()

// 设置媒体源
val mediaItem = MediaItem.fromUri("https://example.com/video.m3u8")
player.setMediaItem(mediaItem)
player.prepare()
player.play()

// 绑定到 PlayerView
binding.playerView.player = player

生命周期管理

class VideoPlayerActivity : AppCompatActivity() {
private var player: ExoPlayer? = null

override fun onStart() {
super.onStart()
initializePlayer()
}

override fun onStop() {
super.onStop()
releasePlayer()
}

private fun releasePlayer() {
player?.let {
// 保存播放位置以便恢复
playbackPosition = it.currentPosition
currentItem = it.currentMediaItemIndex
it.release()
}
player = null
}
}

ExoPlayer vs MediaPlayer

维度ExoPlayer / Media3MediaPlayer
格式支持HLS/DASH/SmoothStreaming/MP4MP4/MP3/基础格式
自适应码率
DRM✅ Widevine有限
字幕SRT/WebVTT/TTML有限
自定义能力高(组件可替换)
维护Google 活跃维护基本停滞

常见面试问题

Q1: ExoPlayer 的缓冲策略是什么?

答案

ExoPlayer 通过 LoadControl 控制缓冲。DefaultLoadControl 有四个关键参数:

  • minBufferMs(15s):最小缓冲时长,缓冲低于此值时继续加载
  • maxBufferMs(50s):最大缓冲时长,达到后停止加载
  • bufferForPlaybackMs(2.5s):初次播放前需要缓冲的时长
  • bufferForPlaybackAfterRebufferMs(5s):卡顿后重新播放需要的缓冲时长

可以根据场景调整:短视频可缩短 buffer,长视频/直播可适当增大。

Q2: 如何实现视频列表的预加载?

答案

使用 ExoPlayer 的预缓存能力:

  1. 全局共享缓存:使用 SimpleCache 配置磁盘缓存目录
  2. 预加载:为即将可见的视频提前创建 MediaSource 并调用 preload()
  3. 复用 Player:列表中复用同一个 ExoPlayer 实例,切换 MediaItem 而非创建新 Player

或使用 CacheDataSource.Factory 配合 ProgressiveMediaSource,让已缓存的数据直接从本地读取。

相关链接