ExoPlayer详解——媒体类型(官方文档)
一、DASHExoPlayer支持多种容器格式的DASH。必须对媒体流进行解复用,这意味着必须在DASH清单中的不同AdaptationSet元素中定义视频,音频和文本(CEA-608是一个例外,如下表所述)。还必须支持包含的音频和视频样本格式(有关详细信息,请参阅 示例格式部分)。特征支持评论集装箱FMP4是仅拆分流WebM是仅拆分流Mat...
ExoPlayer详解系列文章
一、DASH
ExoPlayer支持多种容器格式的DASH。必须对媒体流进行解复用,这意味着必须在DASH清单中的不同AdaptationSet元素中定义视频,音频和文本(CEA-608是一个例外,如下表所述)。还必须支持包含的音频和视频样本格式(有关详细信息,请参阅 示例格式部分)。
特征 | 支持 | 评论 |
---|---|---|
集装箱 | ||
FMP4 | 是 | 仅拆分流 |
WebM | 是 | 仅拆分流 |
Matroska | 是 | 仅拆分流 |
MPEG-TS | 否 | 没有支持计划 |
隐藏式字幕/字幕 | ||
TTML | 是 | 根据ISO / IEC 14496-30原始或嵌入FMP4中 |
WebVTT | 是 | 根据ISO / IEC 14496-30原始或嵌入FMP4中 |
CEA-608 | 是 | 携带在FMP4视频流中嵌入的SEI消息 |
元数据 | ||
EMSG元数据 | 是 | 嵌入在FMP4中 |
内容保护 | ||
Widevine | 是 | API 19+(“cenc”方案)和25+(“cbcs”,“cbc1”和“cens”方案) |
PlayReady SL2000 | 是 | 仅限Android TV |
ClearKey | 是 | API 21+ |
1、创建MediaSource
要播放DASH流,请DashMediaSource
像往常一样创建并准备播放器。
// Create a data source factory.
DataSource.Factory dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
// Create a DASH media source pointing to a DASH manifest uri.
MediaSource mediaSource = new DashMediaSource.Factory(dataSourceFactory)
.createMediaSource(dashUri);
// Create a player instance.
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);
// Prepare the player with the DASH media source.
player.prepare(mediaSource);
ExoPlayer将自动调整清单中定义的表示,同时考虑可用带宽和设备功能。
2、访问清单
您可以通过调用Player.getCurrentManifest
来检索当前清单。对于DASH,您应该将返回的对象强制转换为DashManifest
。该onTimelineChanged
回调Player.EventListener
也被称为清单加载。对于点播内容,这将发生一次,对于直播内容可能会发生多次。下面的代码片段显示了应用程序在加载清单时如何执行操作。
player.addListener(
new Player.EventListener() {
@Override
public void onTimelineChanged(
Timeline timeline,
@Nullable Object manifest,
@Player.TimelineChangeReason int reason) {
if (manifest != null) {
DashManifest dashManifest = (DashManifest) manifest;
// Do something with the manifest.
}
}
});
3、侧载清单
对于特定用例,有一种替代方法可以通过将DashManifest
对象传递给构造函数来提供清单。
DataSource.Factory dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
// Create a dash media source with a dash manifest.
MediaSource mediaSource = new DashMediaSource.Factory(dataSourceFactory)
.createMediaSource(dashManifest);
// Create a player instance which gets an adaptive track selector by default.
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);
// Prepare the player with the dash media source.
player.prepare(mediaSource);
4、自定义DASH播放
ExoPlayer提供多种方式让您根据应用的需求定制播放体验。以下部分简要介绍了构建DashMediaSource
时可用的一些自定义选项。有关更多常规自定义选项,请参阅“ 自定义”页面。
(1)、自定义服务器交互
某些应用可能希望拦截HTTP请求和响应。您可能希望注入自定义请求标头,读取服务器的响应标头,修改请求的URI等。例如,您的应用程序可以通过在请求媒体段时将标记作为标头注入来验证自身。您可以通过将自定义HttpDataSources注入到你创建的DashMediaSource
中来实现这些行为。以下代码段显示了标头注入的示例:
DashMediaSource dashMediaSource =
new DashMediaSource.Factory(
() -> {
HttpDataSource dataSource = new DefaultHttpDataSource(userAgent);
// Set a custom authentication request header.
dataSource.setRequestProperty("Header", "Value");
return dataSource;
})
.createMediaSource(dashUri);
(2)、自定义错误处理
实现自定义LoadErrorHandlingPolicy允许应用程序自定义ExoPlayer对加载错误的反应方式。例如,应用程序可能希望快速失败而不是多次重试,或者可能想要自定义控制player在每次重试之间等待多长时间的退避逻辑。以下代码段显示了在创建DashMediaSource
以下内容时如何实现自定义退避逻辑:
DashMediaSource dashMediaSource =
new DashMediaSource.Factory(dataSourceFactory)
.setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy() {
@Override
public long getRetryDelayMsFor(...) {
// Implement custom back-off logic here.
}
})
.createMediaSource(dashUri);
您可以在我们的媒体帖子中找到有关错误处理的更多信息。
5、BehindLiveWindowException
在播放具有有限可用性的直播流的情况下,如果播放器暂停或缓冲足够长的时间段,则播放器可能落后于该实况窗口。在这种情况下,抛出一个BehindLiveWindowException
,可以捕获它并在现场边缘恢复player。演示应用程序的PlayerActivity举例说明了这种方法。
@Override
public void onPlayerError(ExoPlaybackException e) {
if (isBehindLiveWindow(e)) {
// Re-initialize player at the live edge.
} else {
// Handle other errors
}
}
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
return false;
}
Throwable cause = e.getSourceException();
while (cause != null) {
if (cause instanceof BehindLiveWindowException) {
return true;
}
cause = cause.getCause();
}
return false;
}
二、HLS
ExoPlayer支持多种容器格式的HLS。还必须支持包含的音频和视频样本格式(有关详细信息,请参阅 示例格式部分)。我们强烈鼓励HLS内容制作产生高品质的HLS流,描述 在这里。
特征 | 支持 | 评论 |
---|---|---|
集装箱 | ||
MPEG-TS | 是 | |
FMP4 / CMAF | 是 | |
ADTS(AAC) | 是 | |
MP3 | 是 | |
隐藏式字幕/字幕 | ||
CEA-608 | 是 | |
WebVTT | 是 | |
元数据 | ||
ID3元数据 | 是 | |
内容保护 | ||
AES-128 | 是 | |
样品AES-128 | 没有 | |
Widevine | 是 | API 19+(“cenc”方案)和25+(“cbcs”方案) |
PlayReady SL2000 | 是 | 仅限Android TV |
1、创建MediaSource
要播放HLS流,请像往常一样创建HlsMediaSource
并准备播放器。
// Create a data source factory.
DataSource.Factory dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
// Create a HLS media source pointing to a playlist uri.
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
// Create a player instance.
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);
// Prepare the player with the HLS media source.
player.prepare(hlsMediaSource);
URI传递给HlsMediaSource.Factory.createMediaSource()
可以指向媒体播放列表或主播放列表。如果URI指向声明多个#EXT-X-STREAM-INF
标签的主播放列表,则ExoPlayer将自动调整变体,同时考虑可用带宽和设备功能。
2、自定义HLS播放
ExoPlayer提供多种方式让您根据应用的需求定制播放体验。以下部分简要介绍了构建HlsMediaSource
时可用的一些自定义选项。有关更多常规自定义选项,请参阅“自定义”页面。
(1)、启用更快的启动时间
通过启用无块准备,您可以显着提高HLS启动时间。当您启用无块准备并且#EXT-X-STREAM-INF
标签包含该 CODECS
属性时,ExoPlayer将避免在准备过程中下载媒体段。以下代码段显示了如何启用无块准备:
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory)
.setAllowChunklessPreparation(true)
.createMediaSource(hlsUri);
您可以在我们的关于无框准备的媒体帖子中找到更多详细信息。
(2)、自定义服务器交互
某些应用可能希望拦截HTTP请求和响应。您可能希望注入自定义请求标头,读取服务器的响应标头,修改请求的URI等。例如,您的应用程序可以通过在访问媒体段的URI中注入自定义标记来验证自身。您可以通过将自定义HttpDataSources注入到创建的HlsMediaSource
中来实现这些行为。以下代码段显示了请求标头注入的示例:
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(
dataType -> {
HttpDataSource dataSource =
new DefaultHttpDataSource(userAgent);
if (dataType == C.DATA_TYPE_MEDIA) {
// The data source will be used for fetching media segments. We
// set a custom authentication request header.
dataSource.setRequestProperty("Header", "Value");
}
return dataSource;
})
.createMediaSource(hlsUri);
(3)、自定义错误处理
实现自定义LoadErrorHandlingPolicy允许应用程序自定义ExoPlayer对加载错误的反应方式。例如,应用程序可能希望快速失败而不是多次重试,或者可能想要自定义控制player在每次重试之间等待多长时间的退避逻辑。以下代码段显示了在创建以下HlsMediaSource
内容时如何实现自定义退避逻辑:
HlsMediaSource hlsMediaSource =
new HlsMediaSource.Factory(dataSourceFactory)
.setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy() {
@Override
public long getRetryDelayMsFor(...) {
// Implement custom back-off logic here.
}
})
.createMediaSource(hlsUri);
您可以在我们的媒体帖子中找到有关错误处理的更多信息。
3、创建高质量的HLS内容
为了充分利用ExoPlayer,您可以遵循某些指导原则来改进您的HLS内容。阅读我们在ExoPlayer中关于HLS播放的媒体帖子,以获得完整的解释。要点是:
- 使用精确的段持续时间。
- 使用连续媒体流; 避免跨段的媒体结构的变化。
- 使用
#EXT-X-INDEPENDENT-SEGMENTS
标签。 - 更喜欢分离的流,而不是包含视频和音频的文件。
- 包括主播放列表中的所有信息。
以下指南专门适用于直播流:
- 使用
#EXT-X-PROGRAM-DATE-TIME
标签。 - 使用
#EXT-X-DISCONTINUITY-SEQUENCE
标签。 - 提供一个长时间存在的窗口。一分钟或时间越长越好。
4、BehindLiveWindowException
在播放具有有限可用性的直播流的情况下,如果播放器暂停或缓冲足够长的时间段,则播放器可能落后于该实况窗口。在这种情况下,抛出一个BehindLiveWindowException
,可以捕获它并在现场边缘恢复player。演示应用程序的PlayerActivity举例说明了这种方法。
@Override
public void onPlayerError(ExoPlaybackException e) {
if (isBehindLiveWindow(e)) {
// Re-initialize player at the live edge.
} else {
// Handle other errors
}
}
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
return false;
}
Throwable cause = e.getSourceException();
while (cause != null) {
if (cause instanceof BehindLiveWindowException) {
return true;
}
cause = cause.getCause();
}
return false;
}
三、Smoothtreaming
ExoPlayer支持使用FMP4容器格式的SmoothStreaming。必须对媒体流进行解复用,这意味着必须在SmoothStreaming清单中的不同StreamIndex元素中定义视频,音频和文本。还必须支持包含的音频和视频样本格式(有关详细信息,请参阅 示例格式部分)。
特征 | 支持 | 评论 |
---|---|---|
集装箱 | ||
FMP4 | 是 | 仅拆分流 |
隐藏式字幕/字幕 | ||
TTML | 是 | 嵌入在FMP4中 |
内容保护 | ||
PlayReady SL2000 | 是 | 仅限Android TV |
1、创建媒体源
要播放SmoothStreaming
流,请像往常一样使用它创建SsMediaSource
并准备播放器。
// Create a data source factory.
DataSource.Factory dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
// Create a SmoothStreaming media source pointing to a manifest uri.
MediaSource mediaSource =
new SsMediaSource.Factory(dataSourceFactory).createMediaSource(ssUri);
// Create a player instance.
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);
// Prepare the player with the SmoothStreaming media source.
player.prepare(mediaSource);
ExoPlayer将自动调整清单中定义的流,同时考虑可用带宽和设备功能。
2、访问清单
您可以通过调用来检索当前清单Player.getCurrentManifest。对于SmoothStreaming,您应该将返回的对象强制转换为SsManifest。该 onTimelineChanged回调Player.EventListener每当清单加载也被称为。对于点播内容,这将发生一次,对于直播内容可能会发生多次。下面的代码片段显示了应用程序在加载清单时如何执行操作。
player.addListener(
new Player.EventListener() {
@Override
public void onTimelineChanged(
Timeline timeline,
@Nullable Object manifest,
@Player.TimelineChangeReason int reason) {
if (manifest != null) {
SsManifest ssManifest = (SsManifest) manifest;
// Do something with the manifest.
}
}
});
3、侧载清单
对于特定用例,有一种替代方法可以通过将SsManifest对象传递给构造函数来提供清单。
DataSource.Factory dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
// Create a smooth streaming media source with a smooth streaming manifest.
MediaSource mediaSource =
new SsMediaSource.Factory(dataSourceFactory).createMediaSource(ssManifest);
// Create a player instance which gets an adaptive track selector by default.
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);
// Prepare the player with the media source.
player.prepare(mediaSource);
4、自定义SmoothStreaming回放
ExoPlayer提供多种方式让您根据应用的需求定制播放体验。以下部分简要介绍了构建SsMediaSource
时可用的一些自定义选项。有关更多常规自定义选项,请参阅“ 自定义”页面。
(1)、自定义服务器交互
某些应用可能希望拦截HTTP请求和响应。您可能希望注入自定义请求标头,读取服务器的响应标头,修改请求的URI等。例如,您的应用程序可以通过在访问媒体段的URI中注入自定义标记来验证自身。您可以通过将自定义HttpDataSources注入到创建的SsMediaSource
中来实现这些行为。以下代码段显示了请求标头注入的示例:
SsMediaSource ssMediaSource =
new SsMediaSource.Factory(
() -> {
HttpDataSource dataSource = new DefaultHttpDataSource(userAgent);
// Set a custom authentication request header.
dataSource.setRequestProperty("Header", "Value");
return dataSource;
})
.createMediaSource(ssUri);
(1)、自定义错误处理
实现自定义LoadErrorHandlingPolicy允许应用程序自定义ExoPlayer对加载错误的反应方式。例如,应用程序可能希望快速失败而不是多次重试,或者可能想要自定义控制player在每次重试之间等待多长时间的退避逻辑。以下代码段显示了在创建以下SsMediaSource
内容时如何实现自定义退避逻辑:
SsMediaSource ssMediaSource =
new SsMediaSource.Factory(dataSourceFactory)
.setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy() {
@Override
public long getRetryDelayMsFor(...) {
// Implement custom back-off logic here.
}
})
.createMediaSource(ssUri);
您可以在我们的媒体帖子中找到有关错误处理的更多信息。
5、BehindLiveWindowException
在播放具有有限可用性的直播流的情况下,如果播放器暂停或缓冲足够长的时间段,则播放器可能落后于该实况窗口。在这种情况下,抛出一个BehindLiveWindowException
,可以捕获它并在现场边缘恢复player。演示应用程序的PlayerActivity举例说明了这种方法。
@Override
public void onPlayerError(ExoPlaybackException e) {
if (isBehindLiveWindow(e)) {
// Re-initialize player at the live edge.
} else {
// Handle other errors
}
}
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
return false;
}
Throwable cause = e.getSourceException();
while (cause != null) {
if (cause instanceof BehindLiveWindowException) {
return true;
}
cause = cause.getCause();
}
return false;
四、Progressive
以下容器格式的流可以由ExoPlayer直接播放。还必须支持包含的音频和视频样本格式(有关详细信息,请参阅 示例格式部分)。
容器格式 | 支持 | 评论 |
---|---|---|
MP4 | 是 | |
M4A | 是 | |
FMP4 | 是 | |
WebM | 是 | |
Matroska | 是 | |
MP3 | 是 | 有些流只能使用恒定比特率寻求** |
Ogg | 是 | 包含Vorbis,Opus和Flac |
WAV | 是 | |
MPEG-TS | 是 | |
MPEG-PS | 是 | |
FLV | 是 | 不可寻求* |
ADTS(AAC) | 是 | 只能使用恒定比特率寻求** |
Flac | 是 | 仅使用Flac扩展名 |
AMR | 是 | 只能使用恒定比特率寻求** |
*寻求不受支持,因为容器不提供元数据(例如,样本索引)以允许媒体播放器以有效的方式执行搜索。如果需要寻求,我们建议使用更合适的容器格式。
**这些提取器具有FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
用于使用恒定比特率假设来实现近似搜索的标志。默认情况下不启用此功能。最简单的方法来启用此功能支持它的是使用所有提取 DefaultExtractorsFactory.setConstantBitrateSeekingEnabled
,描述 在这里。
1、创建MediaSource
要播放渐进流,请像往常一样创建ProgressiveMediaSource
并准备播放器。
// Create a data source factory.
DataSource.Factory dataSourceFactory =
new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
// Create a progressive media source pointing to a stream uri.
MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(progressiveUri);
// Create a player instance.
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);
// Prepare the player with the progressive media source.
player.prepare(mediaSource);
2、自定义渐进式播放
ExoPlayer提供多种方式让您根据应用的需求定制播放体验。以下部分简要介绍了构建ProgressiveMediaSource
时可用的一些自定义选项。有关更多常规自定义选项,请参阅“ 自定义”页面。
(1)、设置提取器标志
提取器标志可用于控制如何提取单个格式。它们可以设置为 DefaultExtractorsFactory
,然后可以在实例化时使用ProgressiveMediaSource.Factory
。以下示例传递一个标志,该标志禁用MP4流的编辑列表解析。
DefaultExtractorsFactory extractorsFactory =
new DefaultExtractorsFactory()
.setMp4ExtractorFlags(Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS);
ProgressiveMediaSource progressiveMediaSource =
new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
.createMediaSource(progressiveUri);
(2)、启用恒定比特率搜索
对于MP3,ADTS和AMR流,您可以使用带FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
标志的恒定比特率假设启用近似搜索。可以使用上述方法为各个提取器设置这些标志。要为所有支持它的提取器启用恒定比特率搜索,请使用DefaultExtractorsFactory.setConstantBitrateSeekingEnabled
。
DefaultExtractorsFactory extractorsFactory =
new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
ProgressiveMediaSource progressiveMediaSource =
new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
.createMediaSource(progressiveUri);
(3)、自定义服务器交互
某些应用可能希望拦截HTTP请求和响应。您可能希望注入自定义请求标头,读取服务器的响应标头,修改请求的URI等。例如,您的应用程序可以通过在请求媒体段时将标记作为标头注入来验证自身。您可以通过将自定义HttpDataSources注入到ProgressiveMediaSourcecreate
中来实现这些行为。以下代码段显示了标头注入的示例:
ProgressiveMediaSource progressiveMediaSource =
new ProgressiveMediaSource.Factory(
() -> {
HttpDataSource dataSource =
new DefaultHttpDataSource(userAgent);
// Set a custom authentication request header.
dataSource.setRequestProperty("Header", "Value");
return dataSource;
})
.createMediaSource(progressiveUri);
(1)、自定义错误处理
实现自定义LoadErrorHandlingPolicy允许应用程序自定义ExoPlayer对加载错误的反应方式。例如,应用程序可能希望快速失败而不是多次重试,或者可能想要自定义控制玩家在每次重试之间等待多长时间的退避逻辑。以下代码段显示了在创建以下ProgressiveMediaSource
内容时如何实现自定义退避逻辑 :
ProgressiveMediaSource progressiveMediaSource =
new ProgressiveMediaSource.Factory(dataSourceFactory)
.setLoadErrorHandlingPolicy(
new DefaultLoadErrorHandlingPolicy() {
@Override
public long getRetryDelayMsFor(...) {
// Implement custom back-off logic here.
}
})
.createMediaSource(progressiveUri);
您可以在我们的媒体帖子中找到有关错误处理的更多信息。
您的关注和点赞是我分享的动力,如有帮助请勿吝啬!ヽ( ̄▽ ̄)ノ
更多推荐
所有评论(0)