浏览器集成Widevine DRM播放器:DRM密钥获取XHR请求疑问
我之前在集成Dash.js和Shaka Player处理Widevine加密流的时候也碰到过一模一样的情况,一开始也纳闷为啥会冒出来多个许可证请求,后来翻了浏览器CDM(内容解密模块)的文档和播放器源码,总结出几个最常见的原因:
多初始化数据触发独立请求
Widevine的许可证请求其实是浏览器内置CDM发起的,播放器只是把媒体的初始化数据传递给CDM而已。如果你的媒体流里包含多份不同的初始化数据(Initialization Data)——比如音频轨和视频轨用了不同的加密密钥,或者同一轨道的不同片段对应不同的密钥ID——CDM会为每一份初始化数据单独发送许可证请求。你可以在开发者工具的Network面板里查看每个请求的请求体,解码message字段的Base64内容,就能看到不同的密钥ID,这就能确认是不是这个原因。许可证自动刷新请求
大部分Widevine许可证都有有效期限制(从几小时到几天不等),当当前许可证快过期时,CDM会自动发起新的请求获取续期后的许可证,避免播放中途中断。这种情况下,第二个请求通常会在播放一段时间后出现,而且请求体里会包含旧许可证的相关信息用于续期。CDM的请求重试机制
如果第一次许可证请求因为网络波动、服务器超时或者临时错误失败,CDM会自动触发重试请求。这类情况你可以看Network面板里的请求状态,重试请求之前通常会有一个状态码非200的失败请求。播放器的预加载/多会话优化
像Dash.js和Shaka Player这类自适应码流播放器,会提前预加载不同码率的媒体片段来优化播放体验。如果不同码率的片段使用了不同的加密密钥,播放器会提前建立对应的DRM会话,每个会话都会触发一个许可证请求。另外,有些播放器会为了快速切换轨道,提前初始化多个DRM会话,这也会产生额外的请求。
如果你想进一步排查,可以用播放器的事件监听来追踪请求细节:
- Shaka Player可以监听
license-requested事件,在回调里查看请求对应的初始化数据和会话信息; - Dash.js可以通过
player.on('licenserequested', function(e) { ... })来获取请求的具体参数。
内容的提问来源于stack exchange,提问作者hixe

