提问人:Ptumster 提问时间:3/11/2023 最后编辑:Ptumster 更新时间:3/31/2023 访问量:549
演员表:拦截(和调整)来自 Widevine 许可证代理的响应
Cast: Intercepting (and adjusting) response from Widevine license proxy
问:
我正在尝试通过自定义接收器将受 DRM 保护的内容投射到我的 Chromecast 设备,但我一直收到此错误:
[ERROR] Event detected: {"type":"ERROR","detailedErrorCode":200,"error":{"shakaErrorCode":6008,"shakaErrorData":["Failed to execute 'update' on 'MediaKeySession': UpdateSession failed"]}}
根据 Shaka 文档,此错误是因为 CDM 不喜欢它从许可证服务器获得的响应:
“许可证响应被清洁发展机制拒绝。对于此 CDM,服务器的响应可能无效或格式不正确。error.data[0] 是来自浏览器的错误消息字符串。
这并不让我特别惊讶,因为我知道我的 CDN 的 Widevine 代理使用 base64(标准)编码,但大多数 Google 产品都需要 base64url 编码。因此,我需要拦截来自许可证服务器的响应,对其进行一些按摩,然后将其传递给CDM。
我该怎么做?似乎没有我可以设置的 playbackConfig.license 响应处理程序来捕获响应......
有没有人可以查看“标准”Widevine licenseRequestHandler 函数的示例?也许我基本上做错了什么?
我的 CDN 的 widevine 代理有时似乎需要对代理 URL(带有其他一些参数,包括身份验证令牌)发出初始质询请求(以获取服务器证书),其 JSON 请求正文如下所示:
{
"getWidevineLicense": {
"releasePid": "2vnevwf3AVz0", // unique identifier for my particular video
"widevineChallenge": "CAQ="
}
}
然后,响应被传递到 CDM,CDM 构建真正的 Widevine 质询,该质询用于对 widevine 代理的第二次调用,该代理返回实际的许可证密钥。
在我的接收器代码中,我尝试使用以下处理程序捕获和预处理许可证请求:
playbackConfig.licenseRequestHandler = requestInfo => {
castDebugLogger.warn(LOG_TAG, 'Unmodified request: ', requestInfo);
requestInfo.url = widevineLicenseServer;
// It doesn't seem to matter if we use requestInfo.body or requestInfo.content
//-- it doesn't work either way.
var wrapped = { "getWidevineLicense": {} };
var base64_string = "CAQ=";
castDebugLogger.warn(LOG_TAG, 'Checking for original content: ', requestInfo.content);
if (requestInfo && requestInfo.content && requestInfo.content.length > 16) {
castDebugLogger.warn(LOG_TAG, 'Detected original content: ', requestInfo.content);
base64_string = btoa(requestInfo.content);
// Shaka expects to be using base64url encoding, but Comcast (my CDN) uses base64 (standard),
// so I have to manually adjust two characters.
base64_string = base64_string.replace(/-/g, '+');
base64_string = base64_string.replace(/_/g, '/');
}
wrapped.getWidevineLicense.widevineChallenge = base64_string;
wrapped.getWidevineLicense.releasePid = releasePid;
castDebugLogger.warn(LOG_TAG, 'Wrapped content: ', wrapped);
// Encode the wrapped request as JSON.
const wrappedJson = JSON.stringify(wrapped);
requestInfo.content = wrappedJson;
castDebugLogger.warn(LOG_TAG, 'Handling license request for DRM with a modified license request: ', requestInfo);
};
我正在使用 Cactool v2 连接到我注册(但尚未发布)的 App ID,并向它传递一个与我正在使用的 releasePid 一致的 DASH 清单 (mpd)。我看到标题加载成功,但是当它尝试解决 Widevine 许可证请求时,它会生成我之前提到的 Shaka 6008 错误。
我希望我提供的初始 Widevine 质询 (CAQ=) 将导致一个质询响应,我可以解析该响应并将其传递给 CDM,以便可以生成“真正的”Widevine 质询,但 CDM 不喜欢它从我的 widevine 代理那里得到的东西。我似乎无法“看到”从 widevine 代理返回的内容,所以我无法解决任何问题。
任何帮助将不胜感激!
答:
就在最近,Web Receiver 有了新的处理程序变量,可以分配给这种情况,称为 playbackConfig.licenseHandler
不过,参数类型是 uint8array,因此需要将其更改为字符串,然后更改为 JSON 对象。
(function(non-null Uint8Array, non-null cast.framework.NetworkResponseInfo) returns (non-null Promise containing non-null Uint8Array or non-null Uint8Array) or undefined)
由于返回类型是 Promise,如果我没记错的话,我相信可以在这里启动 fetch,然后可以将其用于质询。之后,如果服务器返回包装的 JSON 响应,则需要解包。
解包 JSON 响应后,只有通过 licenseRequestHandler 才能转换连续的许可证请求。
评论