Android ExoPlayer 播放器的媒体来源(Media sources)
在 ExoPlayer 中,每种媒体都由 MediaSource 标识。ExoPlayer 库提供了 MediaSource 的几种流类型的实现:
- DashMediaSource用于DASH。
- SsMediaSource用于SmoothStreaming。
- HlsMediaSource用于HLS。
- ProgressiveMediaSource用于常规媒体文件。
PlayerActivity在主演示应用程序中可以找到实例化这四个实例的示例。
1、MediaSource组成
除上述 MediaSource,ExoPlayer 库还提供 ConcatenatingMediaSource,ClippingMediaSource, LoopingMediaSource和MergingMediaSource。这些MediaSource 实现可通过合成实现更复杂的播放功能。下面描述了一些常见的用例。注意,尽管以下一些示例是在视频播放的上下文中描述的,但它们同样适用于仅音频的播放,实际上也适用于任何支持的媒体类型的播放。
a) 播放播放列表
播放列表使用 ConcatenatingMediaSource,该播放列表允许按顺序播放多个 MediaSource。ConcatenatingMediaSource 允许播放期间动态的添加和删除 MediaSource。
b) 剪辑视频
ClippingMediaSource 可用于剪辑 MediaSource 来仅播放其中的一部分。以下示例将视频播放剪辑为从5秒开始到10秒结束。
MediaSource videoSource = new ProgressiveMediaSource.Factory(...).createMediaSource(videoUri);
// Clip to start at 5 seconds and end at 10 seconds.
ClippingMediaSource clippingSource =
new ClippingMediaSource(
videoSource,
/* startPositionUs= */ 5_000_000,
/* endPositionUs= */ 10_000_000);
要仅剪切源的开始,可以将endPositionUs设置为 C.TIME_END_OF_SOURCE。为了只剪辑特定的持续时间,可以使用带有durationUs参数的构造函数。
剪辑视频文件的开头时,请尽可能使起始位置与关键帧对齐。如果起始位置未与关键帧对齐,则播放器将需要解码并丢弃从前一个关键帧直到起始位置的数据,然后才能开始播放。这将在播放开始时引入短暂的延迟,包括当播放器将 ClippingMediaSource作为列表或循环播放时。
c) 循环播放视频
无限循环,推荐使用 ExoPlayer.setRepeatMode() 而非 LoopingMediaSource() 。可以使用 LoopingMediaSource 来将视频无缝循环固定次数 。以下示例将视频播放两次。
MediaSource source = new ProgressiveMediaSource.Factory(...).createMediaSource(videoUri);
// Plays the video twice.
LoopingMediaSource loopingSource = new LoopingMediaSource(source, 2);
d) 侧面加载字幕文件
给定一个视频文件和一个单独的字幕文件,可以使用 MergingMediaSource 将它们合并为一个源以进行播放。
// Build the video MediaSource.
MediaSource videoSource = new ProgressiveMediaSource.Factory(...).createMediaSource(videoUri);
// Build the subtitle MediaSource.
Format subtitleFormat = Format.createTextSampleFormat(
id, // An identifier for the track. May be null.
MimeTypes.APPLICATION_SUBRIP, // The mime type. Must be set correctly.
selectionFlags, // Selection flags for the track.
language); // The subtitle language. May be null.
MediaSource subtitleSource = new SingleSampleMediaSource.Factory(...)
.createMediaSource(subtitleUri, subtitleFormat, C.TIME_UNSET);
// Plays the video with the sideloaded subtitle.
MergingMediaSource mergedSource = new MergingMediaSource(videoSource, subtitleSource);
2、更多组合类型
可以进一步组合MediaSource以用于更特殊的用例。给定两个视频A和B,以下示例显示了如何 一起使用 LoopingMediaSource 和 ConcatenatingMediaSource 使他们成为播放序列(A,A,B)。
MediaSource firstSource = new ProgressiveMediaSource.Factory(...).createMediaSource(firstVideoUri);
MediaSource secondSource = new ProgressiveMediaSource.Factory(...).createMediaSource(secondVideoUri);
// Plays the first video twice.
LoopingMediaSource firstSourceTwice = new LoopingMediaSource(firstSource, 2);
// Plays the first video twice, then the second video.
ConcatenatingMediaSource concatenatedSource = new ConcatenatingMediaSource(firstSourceTwice, secondSource);
以下示例是等效的,表明可以有多种方法来获得相同的结果。
MediaSource firstSource = new ProgressiveMediaSource.Factory(...).createMediaSource(firstVideoUri);
MediaSource secondSource = new ProgressiveMediaSource.Factory(...).createMediaSource(secondVideoUri);
// Plays the first video twice, then the second video.
ConcatenatingMediaSource concatenatedSource = new ConcatenatingMediaSource(firstSource, firstSource, secondSource);