- 修复“不允许使用明文 HTTP 流量”问题错误
- 修复“SSLHandshakeException”、“CertPathValidatorException”和“ERR_CERT_AUTHORITY_INVALID”错误
- 为什么某些媒体文件无法查找?
- 为什么某些 MP3 文件中的定位不准确?
- 为什么视频的跳转速度很慢?
- 为什么有些 MPEG-TS 文件无法播放?
- 为什么在某些 MPEG-TS 文件中找不到字幕?
- 为什么某些 MP4/FMP4 文件无法播放?
- 为什么有些视频流会失败并显示 HTTP 响应代码 301 或 302?
- 为什么有些流因 UnrecognizedInputFormatException 而失败?
- 为什么 setPlaybackParameters 在某些设备上无法正常工作?
- “在错误的线程上访问播放器”怎么办错误意味着什么?
- 如何解决“意外状态行:ICY 200 OK”这一问题?
- 如何查询正在播放的直播是否为直播?
- 应用在后台运行时,如何继续播放音频?
- 为什么 ExoPlayer 支持我的内容,但 ExoPlayer Cast 库不支持?
- 为什么内容无法播放,但系统未显示任何错误?
- 如何加载解码库并用于播放?
- 我可以直接通过 ExoPlayer 播放 YouTube 视频吗?
- 视频播放卡顿
- 不稳定的 API lint 错误
解决“不允许明文 HTTP 流量”问题错误
如果您的应用请求明文 HTTP 流量(即
http://
,而不是 https://
)
不允许。如果您的应用以 Android 9(API 级别 28)或更高版本为目标平台,则应使用明文
HTTP 流量默认处于停用状态。
如果您的应用需要处理明文 HTTP 流量,则您需要使用
网络安全配置。查看 Android 的
网络安全文档
了解详情。要启用所有 HTTP 明文流量,只需将
android:usesCleartextTraffic="true"
添加到应用的 application
元素中
AndroidManifest.xml
。
ExoPlayer 演示版应用使用默认网络安全配置,因此 它不允许 HTTP 明文流量。您可以按照相关说明启用它 。
修复“SSLHandshakeException”、“CertPathValidatorException”和“ERR_CERT_AUTHORITY_INVALID”错误
SSLHandshakeException
、CertPathValidatorException
和
ERR_CERT_AUTHORITY_INVALID
均表示服务器的 SSL 存在问题
证书。这些错误并非特定于 ExoPlayer。请参阅
Android 的 SSL 文档
了解详情。
为什么某些媒体文件无法查找?
默认情况下,ExoPlayer 不支持在媒体中跳转, 执行准确跳转操作是让播放器扫描 整个文件。ExoPlayer 认为此类文件不可查找。大多数现代媒体 容器格式包括用于跳转的元数据(例如示例索引),具有 定义明确搜索算法(例如,针对 Ogg 的插值对分搜索),或 表明其内容采用恒定比特率高效的跳转操作 在这些情况下由 ExoPlayer 提供支持。
如果您需要跳转,但拥有无法搜索的媒体,我们建议您将 使用更合适的容器格式。对于 MP3、ADS 和 AMR 文件 您也可以在文件具有常量不变的情况下启用搜寻功能 如此处所述 此处。
为什么某些 MP3 文件中的定位不准确?
可变比特率 (VBR) MP3 文件从根本上就不适合 需要精确跳转。这样处理有两个考虑:
- 对于精确跳转,理想情况下,容器格式可以提供精确的 标头中的时间到字节映射。这种映射可让玩家将 请求的寻道时间到相应字节偏移量,然后开始请求 从该偏移量开始解析和播放媒体。可用的标头 在 MP3(如 XING 标头)中指定这种映射 不精确。
- 对于不提供精确时间到字节映射(或者 任何时间到字节的映射),也仍然可以执行精确的 尝试查找容器中的流中的绝对样本时间戳。在 在这种情况下,玩家可以将跳转时间映射到 字节偏移量,开始从该偏移量请求媒体,解析第一个 绝对样本时间戳,并有效地执行引导式二进制搜索 直到找到合适的样本。很遗憾,MP3 在流中包含绝对样本时间戳,因此这种方法
出于这些原因,对 VBR MP3 文件执行精确跳转的唯一方法是
扫描整个文件,然后在
。您可以使用 FLAG_ENABLE_INDEX_SEEKING
启用此策略,
可在 DefaultExtractorsFactory
上设置,方法是使用
setMp3ExtractorFlags
。请注意,在压缩为大型 MP3 文件时
尤其是当用户尝试很快接近直播结尾时
在开始播放后(这需要播放器等到其下载完成)
并在执行跳转之前将整个流编入索引。在 ExoPlayer 中,
在这种情况下,他们决定优化速度而不是准确性,
因此,FLAG_ENABLE_INDEX_SEEKING
默认处于停用状态。
如果您要控制正在播放的媒体,我们强烈建议您使用 相应的容器格式,如 MP4。没有我们已知的应用场景 其中 MP3 是最佳的媒体格式
为什么视频的跳转速度很慢?
当播放器尝试在视频中找到新的播放位置时,它需要执行以下两项操作: 事情:
- 将与新播放位置对应的数据加载到缓冲区中 (如果该数据已缓冲,则可能不需要这样做)。
- 刷新视频解码器并开始从 I-frame(关键帧)解码,然后 新的播放位置,因为大多数视频都采用帧内编码 压缩格式。为了确保定位准确(也就是说, 播放正好从定位位置开始), 需要对上一个 I 帧和定位位置进行解码, (不会显示在屏幕上)。
可以通过以下两种方式之一来缓解第 (1) 项带来的延迟时间: 或将数据预缓存到磁盘。
可以通过降低准确率和延迟,
或使用 ExoPlayer.setSeekParameters
对视频进行重新编码,
具有更高频率的 I-frame(这会导致输出文件越大)。
为什么有些 MPEG-TS 文件无法播放?
某些 MPEG-TS 文件不包含访问单元分隔符 (AUD)。默认情况下 ExoPlayer 依靠 AUD 以低廉的成本检测帧边界。同样, MPEG-TS 文件不包含 IDR 关键帧。默认情况下, ExoPlayer 考虑的关键帧数量。
当系统要求您播放
缺少 AUD 或 IDR 关键帧的 MPEG-TS 文件。如果您需要播放此类文件
您可以使用 FLAG_DETECT_ACCESS_UNITS
和
FLAG_ALLOW_NON_IDR_KEYFRAMES
。这些标记可在
DefaultExtractorsFactory
,使用 setTsExtractorFlags
或在
DefaultHlsExtractorFactory
使用
构造函数。
使用 FLAG_DETECT_ACCESS_UNITS
不会产生任何副作用,
相较于基于 AUD 的帧边界检测,计算开销非常大。使用
FLAG_ALLOW_NON_IDR_KEYFRAMES
可能会导致
开始播放以及播放某些 MPEG-TS 文件时在跳转之后立即。
为什么在某些 MPEG-TS 文件中找不到字幕?
某些 MPEG-TS 文件包含 CEA-608 轨道,但未在
容器元数据,因此 ExoPlayer 无法检测到它们。您可以手动
通过提供预期字幕轨道的列表来指定任何字幕轨道
字幕格式传递给 DefaultExtractorsFactory
,包括无障碍功能
可用于在 MPEG-TS 流中用于识别它们的通道:
Kotlin
val extractorsFactory = DefaultExtractorsFactory() .setTsSubtitleFormats( listOf( Format.Builder() .setSampleMimeType(MimeTypes.APPLICATION_CEA608) .setAccessibilityChannel(accessibilityChannel) // Set other subtitle format info, such as language. .build() ) ) val player: Player = ExoPlayer.Builder(context, DefaultMediaSourceFactory(context, extractorsFactory)).build()
Java
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory() .setTsSubtitleFormats( ImmutableList.of( new Format.Builder() .setSampleMimeType(MimeTypes.APPLICATION_CEA608) .setAccessibilityChannel(accessibilityChannel) // Set other subtitle format info, such as language. .build())); Player player = new ExoPlayer.Builder(context, new DefaultMediaSourceFactory(context, extractorsFactory)) .build();
为什么某些 MP4/FMP4 文件无法播放?
某些 MP4/FMP4 文件包含编辑列表,这些编辑列表可通过以下方式重写媒体时间轴: 跳过、移动或重复样本列表。ExoPlayer 提供部分支持 来应用修改列表。例如,它可能会延迟或重复样本组 从同步样本开始,但不会截断音频样本或 前贴片广告媒体。
如果您发现部分媒体内容意外缺失或重复出现,
尝试设置 Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
或
FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
,这会导致
提取器以完全忽略修改列表。这些可设置
DefaultExtractorsFactory
(使用 setMp4ExtractorFlags
或
setFragmentedMp4ExtractorFlags
。
为什么有些数据流失败并显示 HTTP 响应代码 301 或 302?
HTTP 响应代码 301 和 302 均表示重定向。简要说明 可在维基百科上找到。当 ExoPlayer 发出请求并收到 状态代码为 301 或 302 的响应,则通常遵循重定向 并正常开始播放。默认情况下不会出现这种情况 适用于跨协议重定向跨协议重定向是指 或从 HTTPS 到 HTTP,反之亦然(或者 协议)。您可以使用 wget 命令行工具,如下所示:
wget "https://yourserver.com/test.mp3" 2>&1 | grep Location
输出应类似如下所示:
Location: https://second.com/test.mp3 [following]
Location: http://third.com/test.mp3 [following]
在本例中,有两个重定向。第一个重定向来自
https://yourserver.com/test.mp3
至 https://second.com/test.mp3
。两者都是
HTTPS,因此这不是跨协议重定向。第二个重定向来自
https://second.com/test.mp3
至 http://third.com/test.mp3
。这会重定向
从 HTTPS 到 HTTP,这也属于跨协议重定向。ExoPlayer 不会
遵循此重定向的默认配置,这意味着播放将失败。
如果需要,您可以将 ExoPlayer 配置为遵循跨协议重定向
实例化用于您的服务账号的 DefaultHttpDataSource.Factory
实例时,
应用。了解如何选择和配置网络堆栈
此处。
为什么有些流会因 UnrecognizedInputFormatException 而失败?
此问题涉及以下形式的播放失败:
UnrecognizedInputFormatException: None of the available extractors
(MatroskaExtractor, FragmentedMp4Extractor, ...) could read the stream.
导致此失败的原因可能有两种。最常见的原因是
你尝试播放 DASH (mpd)、HLS (m3u8) 或 SmoothStreaming(ism、isml)
内容,但播放器会尝试以渐进式视频流的形式播放。要播放此类
必须依赖于相应的 ExoPlayer 模块。如果
流 URI 不是以标准文件扩展名结尾,您也可以将
MimeTypes.APPLICATION_MPD
、MimeTypes.APPLICATION_M3U8
或
MimeTypes.APPLICATION_SS
到 setMimeType
,共 MediaItem.Builder
以明确
指定流的类型。
第二个不太常见的原因是 ExoPlayer 不支持容器 你尝试播放的媒体的格式在此例中,失败是 运行正常,但您可以随时向我们提交功能请求, 问题跟踪器,其中包括容器格式和测试数据流的详细信息。 请先搜索现有的功能请求,然后再提交新的功能请求。
为什么 setPlaybackParameters 在某些设备上无法正常工作?
在 Android M 及更低版本上运行应用的调试 build 时,您可能
运行不稳定、有声音的伪像和高 CPU 利用率
使用 setPlaybackParameters
API。这是因为
对于在这些设备上运行的调试 build 停用
Android 版本。
请务必注意,此问题仅影响调试 build。它不会 会影响发布 build,其优化将始终启用。因此, 您提供给最终用户的版本应该不会受此问题影响。
“在错误的线程上访问播放器”怎么办错误意味着什么?
请参阅“使用入门”页面上的关于线程处理的说明。
如何解决“意外状态行:ICY 200 OK”的问题?
如果服务器响应包含 ICY 状态行、 而不是与 HTTP 协议兼容的ICY 状态行已弃用, 因此,如果您控制服务器,就应该更新服务器, 返回符合 HTTP 协议的响应。如果您无法执行此操作,请使用 ExoPlayer OkHttp 库可以解决此问题,因为它能够处理 ICY 状态行。
如何查询正在播放的直播是否为直播?
您可以查询玩家的 isCurrentWindowLive
方法。此外,您还可以
可通过检查 isCurrentWindowDynamic
了解窗口是否为动态窗口
(即,仍在随时间更新)。
当应用在后台运行时,如何继续播放音频?
请按照以下步骤操作,确保在打开应用后,音频继续播放 背景:
- 您需要有一个正在运行的前台服务。这样可以防止 从而避免终止进程以释放资源
- 你需要同时持有一个
WifiLock
和一个WakeLock
。这可确保 系统会使 Wi-Fi 无线装置和 CPU 保持唤醒状态。如果使用ExoPlayer
,请致电setWakeMode
, 在正确的时间获取和释放所需的锁。
请务必释放锁定(如果不使用 setWakeMode
)并停止
服务。
为什么 ExoPlayer 支持我的内容,但 ExoPlayer Cast 库不支持?
您尝试播放的内容可能并非 已启用 CORS。Cast 框架要求在 才能播放相应内容
为什么内容无法播放,但系统未显示任何错误?
您播放内容的设备可能
支持特定的媒体样本格式。只需添加
一个 EventLogger
作为播放器的监听器,并查找
类似于 Logcat 中的以下代码:
[ ] Track:x, id=x, mimeType=mime/type, ... , supported=NO_UNSUPPORTED_TYPE
NO_UNSUPPORTED_TYPE
表示设备无法解码媒体
mimeType
指定的示例格式。请参阅 Android 媒体格式
文档了解支持的示例格式。如何获得
解码库来加载并用于播放?可能也会有帮助。
如何加载解码库以用于播放?
- 大多数解码器库都有手动检出和构建依赖项的步骤, 请确保您已按照相关库的 README 文件中的步骤执行操作。 例如,对于 ExoPlayer FFmpeg 库,必须遵循 library/decoder_ffmpeg/README.md 中的说明,包括通过 配置标记,以便为您要播放的任何格式启用解码器。
- 对于包含原生代码的库,请确保您使用的是正确的
Android NDK 的版本,并查找任何
配置和构建期间出现的错误。您应该会看到
.so
文件会显示在每个文件库路径的libs
子目录中 按照 README 中的步骤进行操作。 - 如需尝试使用演示版应用中的库进行播放,请参阅 启用捆绑式解码器。有关库的 README 文件,请参阅 从您自己的应用中使用该库的说明。
- 如果您使用的是
DefaultRenderersFactory
,您应该会看到一个信息级 类似“Loaded FfmpegAudioRenderer”的日志行在 Logcat 中加载。 如果缺少此参数,请确保应用依赖于 解码库。 - 如果您在 Logcat 中看到来自
LibraryLoader
的警告级日志,则 表示加载库的原生组件失败。如果 发生了什么情况,检查您是否已正确执行了库的 README 文件中的步骤 并且按照说明操作时未输出任何错误。
如果您在使用解码库时仍然遇到问题,请检查 Media3 问题跟踪器。如果您需要提交 一个新问题,它与构建库的原生部分有关,请 包含运行 README 说明后的完整命令行输出,以帮助我们 诊断问题。
我可以直接通过 ExoPlayer 播放 YouTube 视频吗?
不可以,ExoPlayer 无法播放 YouTube 中的视频,例如以下形式的网址:
https://www.youtube.com/watch?v=...
。您应该使用 YouTube
iframe Player API
,这是在 Android 设备上播放 YouTube 视频的官方方式。
视频播放卡顿
在某些情况下,设备可能无法足够快地解码内容,例如 内容比特率或分辨率超出了设备处理能力。您可能需要 使用低质量内容在此类设备上获得良好性能。
在搭载 Android 版本的设备上出现视频卡顿 从 Android 6.0(API 级别 23)一直到 Android 11(API 级别 30), 尤其是在播放受 DRM 保护或高帧速率的内容时,您可以尝试 启用异步缓冲区队列。
不稳定的 API lint 错误
Media3 可保证 API Surface 的子集的二进制文件兼容性。通过
不保证二进制兼容性的部分带有
@UnstableApi
。为了明确这一区别,“不稳定”的用法
除非带有 @OptIn
注解,否则 API 符号会生成 lint 错误。
@UnstableApi
注解并不表示任何 API 的质量或性能,只是表明它并未“API 冻结”。
您可以通过以下两种方式处理不稳定的 API lint 错误:
- 改用可达到相同结果的稳定 API。
- 继续使用不稳定的 API,并为用法添加
@OptIn
注解,如下所示 稍后会展示。
添加 @OptIn
注解
Android Studio 可以帮助您添加注释:
<ph type="x-smartling-placeholder">![屏幕截图:如何添加“选择启用”注释](https://developer.android.google.cn/static/media/media3/exoplayer/images/unstable-api.png?authuser=7&hl=el)
您也可以在 Kotlin 中手动为特定的用法网站添加注解:
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
@OptIn(UnstableApi::class)
fun functionUsingUnstableApi() { ... }
以及在 Java 中:
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
@OptIn(markerClass = UnstableApi.class)
private void methodUsingUnstableApis() { ... }
您可以通过添加 package-info.java
文件来选择启用整个软件包:
@OptIn(markerClass = UnstableApi.class)
package name.of.your.package;
import androidx.annotation.OptIn;
import androidx.media3.common.util.UnstableApi;
若要为整个项目选择启用此功能,请在相应项目的
lint.xml
文件:
<?xml version="1.0" encoding="utf-8"?>
<lint>
<issue id="UnsafeOptInUsageError">
<option name="opt-in" value="androidx.media3.common.util.UnstableApi" />
</issue>
</lint>
此外,还有一个不应使用的 kotlin.OptIn
注解。时间是
务必要使用 androidx.annotation.OptIn
注解。