摩托罗拉Moto G20离线Widevine DRM播放报错‘Crypto key not available’求助
问题分析
在摩托罗拉Moto G20上离线播放已下载的Widevine DRM保护DASH流时,触发android.media.MediaCodec$CryptoException: Crypto key not available错误,但在线播放正常,且同文件在三星Galaxy S24可正常离线播放。错误栈指向MediaCodec无法获取解密密钥,核心问题大概率是设备DRM框架兼容性或离线密钥加载配置问题。
排查与修复措施
验证设备Widevine等级与密钥兼容性
Moto G20作为中低端设备,Widevine等级通常为L3,部分DRM提供商对L3设备的离线许可证有额外限制(如绑定硬件标识)。可通过代码检查设备Widevine信息:val widevineUuid = UUID.fromString("edef8ba9-79d6-4ace-a3c8-27dcd51d21ed") val mediaDrm = MediaDrm(widevineUuid) val securityLevel = mediaDrm.getPropertyString(MediaDrm.PROPERTY_SECURITY_LEVEL) val vendor = mediaDrm.getPropertyString(MediaDrm.PROPERTY_VENDOR) Log.d("WidevineCheck", "Security Level: $securityLevel, Vendor: $vendor") mediaDrm.release()确认DRM服务器是否允许L3设备下载离线许可证,或是否需要在许可证请求时提交设备唯一标识(如Android ID)。
检查离线密钥的存储与加载逻辑
- 验证
keySetId对应的密钥是否有效存储:val offlineHelper = OfflineLicenseHelper.newWidevineInstance(drmLicenseUrl.url, dataSourceFactory, DrmSessionEventListener.EventDispatcher()) val keyStatus = offlineHelper.getKeyStatus(keySetId) Log.d("DRMKey", "Valid keys count: ${keyStatus.size}") offlineHelper.release() - 避免创建
HttpMediaDrmCallback时传入null许可证URL,部分设备DRM框架需该参数初始化:val drmSessionManager = DefaultDrmSessionManager.Builder() .build( HttpMediaDrmCallback( drmLicenseUrl.url, // 传入实际DRM许可证地址 false, DefaultHttpDataSource.Factory() ) )
- 验证
调整ExoPlayer DRM配置
- 添加DRM事件监听,获取密钥加载的详细日志:
drmSessionManager.addListener(object : DrmSessionEventListener { override fun onDrmSessionError(sessionId: DrmSessionId, error: DrmSessionException) { Log.e("DRMError", "Session error: ${error.cause?.message}", error) } override fun onDrmKeysLoaded(sessionId: DrmSessionId) { Log.d("DRMEvent", "Keys loaded successfully") } }) - 利用
DownloadRequest自带的keySetId自动处理DRM,无需手动绑定:val player = ExoPlayer.Builder(context) .setMediaSourceFactory( DefaultMediaSourceFactory(context) .setDataSourceFactory(cacheDataSourceFactory) .setDrmSessionManagerProvider { DefaultDrmSessionManager.Builder() .build(HttpMediaDrmCallback(drmLicenseUrl.url, DefaultHttpDataSource.Factory())) } ) .build() // 直接使用download.request.toMediaItem(),无需手动设置keySetId player.setMediaSource(mediaSource)
- 添加DRM事件监听,获取密钥加载的详细日志:
检查设备DRM框架状态
- 升级设备系统到最新版本,修复可能存在的DRM框架bug;
- 清除应用的DRM存储:进入设置 -> 应用 -> 你的应用 -> 存储 -> 清除媒体DRM数据,重新下载许可证测试;
- 测试其他分辨率/编码格式的离线视频,确认是否为当前AVC编码(avc1.42C028)的解密兼容性问题。
确认下载媒体文件完整性
检查缓存文件是否完整,对比下载文件大小与在线流大小:val download = downloads.download Log.d("DownloadCheck", "Total size: ${download.totalBytes}, Downloaded: ${download.downloadedBytes}")若文件不完整,重新触发下载流程。
内容的提问来源于stack exchange,提问作者Thomas Joulin
相关产品推荐
相关产品推荐

