ExoPlayer 使用 Android 的 MediaDrm API 来支持受 DRM 保护的播放内容。下表列出了不同受支持 DRM 方案所需的最低 Android 版本,以及它们支持的流式传输格式:
| DRM 方案 | Android 版本号 | Android API 级别 | 支持的格式 |
|---|---|---|---|
| Widevine“cenc” | 4.4 | 19 | DASH、HLS(仅限 FMP4) |
| Widevine“cbcs” | 7.1 | 25 | DASH、HLS(仅限 FMP4) |
| ClearKey“cenc” | 5.0 | 21 | DASH |
| PlayReady SL2000“cenc” | Android TV | Android TV | DASH、SmoothStreaming、HLS(仅限 FMP4) |
为了使用 ExoPlayer 播放受 DRM 保护的内容,必须在构建媒体项时指定 DRM 系统的 UUID,还可以提供其他属性。然后,播放器将使用这些属性构建 DrmSessionManager 的默认实现(称为 DefaultDrmSessionManager),该实现适用于大多数使用情形。对于某些使用情形,可能需要额外的 DRM 属性,如下文各部分所述。
密钥轮替
如需播放具有轮替密钥的流,请在构建媒体项时将 true 传递给 MediaItem.DrmConfiguration.Builder.setMultiSession。
多密钥内容
多密钥内容包含多个视频流,其中一些视频流使用的密钥与其他视频流不同。多密钥内容可以通过以下两种方式之一进行播放,具体取决于许可服务器的配置方式。
情形 1:许可服务器响应内容的所有密钥
在这种情况下,许可服务器配置为在收到一个密钥的请求时,会返回相应内容的所有密钥。ExoPlayer 会处理这种情况,而无需任何特殊配置。即使视频流(例如 SD 和 HD 视频)使用不同的密钥,它们之间的自适应也是无缝的。
我们建议您尽可能将许可服务器配置为以这种方式运行。这是支持播放多密钥内容的最有效且最可靠的方式,因为客户端无需发出多个许可请求即可访问不同的流。
情形 2:许可服务器仅响应所请求的密钥
在这种情况下,许可服务器配置为仅使用请求中指定的密钥进行响应。通过在构建媒体项时将 true 传递给 MediaItem.DrmConfiguration.Builder.setMultiSession,可以使用此许可服务器配置播放多密钥内容。
我们不建议将许可服务器配置为以这种方式运行。它需要额外的许可请求才能播放多密钥内容,与上述替代方案相比,效率和稳健性都较低。
离线密钥
在构建媒体项时,通过将密钥集 ID 传递给 MediaItem.DrmConfiguration.Builder.setKeySetId 即可加载离线密钥集。
这样一来,便可使用存储在具有指定 ID 的离线密钥集中的密钥进行播放。
清晰内容的 DRM 会话
使用占位符 DrmSessions 可让 ExoPlayer 使用与播放加密内容时相同的解码器来解码清晰内容。当媒体同时包含未加密部分和加密部分时,您可能需要使用占位符 DrmSessions,以避免在未加密部分和加密部分之间转换时重新创建解码器。在构建媒体项时,通过将 true 传递给 MediaItem.DrmConfiguration.Builder.forceSessionsForAudioAndVideoTracks,可以启用音频和视频轨道占位符 DrmSessions 的使用。
使用自定义 DrmSessionManager
如果应用想要自定义用于播放的 DrmSessionManager,可以实现 DrmSessionManagerProvider 并将其传递给构建播放器时使用的 MediaSource.Factory。提供方可以选择是否每次都实例化新的管理器实例。如需始终使用同一实例,请执行以下操作:
Kotlin
val customDrmSessionManager: DrmSessionManager = CustomDrmSessionManager() // Pass a drm session manager provider to the media source factory. val mediaSourceFactory = DefaultMediaSourceFactory(context).setDrmSessionManagerProvider { customDrmSessionManager }
Java
DrmSessionManager customDrmSessionManager = new CustomDrmSessionManager(/* ... */ ); // Pass a drm session manager provider to the media source factory. MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(context) .setDrmSessionManagerProvider(mediaItem -> customDrmSessionManager);
提升播放性能
如果您在搭载 Android 6.0(API 级别 23)到 Android 11(API 级别 30)之间任何版本的设备上播放受 DRM 保护的内容时遇到视频卡顿问题,可以尝试启用异步缓冲区排队。