最近在开发中遇到了 Android TV 无法通过 L1 的检测。代码检测如下:
async function checkWidevineL1Support() {
const keySystem = 'com.widevine.alpha';
// Robustness levels to test, from most secure (L1 equivalent) to least secure (L3 equivalent)
const robustnessLevels = [
'HW_SECURE_DECODE', // Likely L1: decryption and decoding in TEE
'HW_SECURE_CRYPTO', // Likely L2: decryption in TEE, decoding in software
'SW_SECURE_DECODE', // Likely L3: software-based, with decode in software
'SW_SECURE_CRYPTO' // Likely L3: software-based, with crypto in software
];
for (const level of robustnessLevels) {
const config = [{
initDataTypes: ['cenc'], // Common Encryption
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.42E01E"', // Example codec
// You might need to add other properties like robustness
robustness: level
}],
audioCapabilities: [{
contentType: 'audio/mp4; codecs="mp4a.40.2"', // Example codec
robustness: level // Audio often doesn't need L1
}]
// persistentState: 'required', // Only if you need offline playback
// distinctiveIdentifier: 'optional' // Optional, not usually required for L1 check
}];
try {
console.log(`Attempting to request Widevine with robustness: ${level}`);
const keySystemAccess = await navigator.requestMediaKeySystemAccess(keySystem, config);
// If we reach here, this robustness level is supported.
// Check the exact configuration that was negotiated.
const negotiatedConfig = keySystemAccess.getConfiguration();
console.log(`Widevine supported with negotiated robustness:`, negotiatedConfig);
// If the highest level (HW_SECURE_DECODE) was successfully negotiated,
// or a sufficiently high hardware-backed level, you can infer L1 support.
if (negotiatedConfig.videoCapabilities && negotiatedConfig.videoCapabilities[0].robustness === 'HW_SECURE_DECODE') {
console.log('🎉 Widevine L1 (or equivalent hardware-backed decoding) is likely supported!');
return 'L1 Supported';
} else if (negotiatedConfig.videoCapabilities && negotiatedConfig.videoCapabilities[0].robustness === 'HW_SECURE_CRYPTO') {
console.log('💡 Widevine L2 (hardware-backed crypto) is likely supported.');
return 'L2 Supported';
} else {
console.log(`⚠️ Widevine L3 (software-based) is likely supported with robustness: ${negotiatedConfig.videoCapabilities ? negotiatedConfig.videoCapabilities[0].robustness : 'unknown'}.`);
return 'L3 Supported';
}
} catch (error) {
console.warn(`Widevine with robustness ${level} NOT supported:`, error.message);
}
}
console.log('❌ Widevine is not supported with any tested robustness level.');
return 'Not Supported';
}
// Call the function to check
checkWidevineL1Support().then(result => {
console.log("Overall Widevine L1 check result:", result);
});
自己第一时间怀疑的是,Android TV 作为盒子,难道天生不就应该有更好的视频播放支持么?
目前可以确认的是桌面端,Chrome 确实不支持 L1, 只支持到 L3 级别: https://www.vdocipher.com/blog/widevine-drm-hollywood-video/#:~:text=system in use.-,Widevine DRM Compatibility,higher security features than L3.
然而原生确实是支持 L1,Android TV 很早就开始支持了 Widevine L1 的播放。 这里有个疑问点其实就是 WebView 的播放和原生播放是不是存在一些限制?
WebView VS Chrome in Android
Android 开发中的 WebView 组件 和 Chrome 浏览器 都是基于 Chromium 开源项目,因此它们共享相同的渲染引擎(Blink)。这意味着在大多数情况下,同一个网页在 WebView 和 Chrome 中会有相似的渲染效果。然而,它们在功能、用途和独立性方面存在显著区别。
特性 | Android WebView 组件 | Chrome 浏览器 |
---|---|---|
类型 | Android 应用内的 UI 组件 | 独立的 完整浏览器应用 |
UI | 无 内置的浏览器UI(需开发者实现) | 有 完整的浏览器UI和功能 |
用途 | 在应用内嵌入显示网页内容 | 独立的网页浏览体验 |
控制 | 通过 API 由应用开发者编程控制 | 用户直接交互和控制 |
数据 | 不 与Chrome共享数据 | 可以 与Google账号同步数据 |
更新 | 通常随系统或“Android System WebView”应用更新 | 独立通过应用商店更新,更频繁 |
功能 | 功能相对 受限 | 功能 齐全,提供高级浏览体验 |
在 DRM 上差异:
Chrome 浏览器 在 DRM 支持方面通常更全面、稳定且更新及时,因为它是一个旨在提供完整浏览体验的独立应用。它默认启用了对 Widevine DRM 的支持,并且会随着浏览器更新而不断提升兼容性。
Android WebView 组件虽然基于相同的 Chromium 内核,但作为嵌入式组件,它需要应用开发者进行额外的配置和权限处理才能启用 DRM 支持。在某些高级 DRM 功能(如持久性许可)方面,或者对于对播放环境有严格要求的服务,WebView 可能存在限制或兼容性问题。
所以这里会有两个问题:
- 我们是否做好相应的 WebView 配置
- WebView 支持 L1 这块限制是不是本身就一直存在
我们尝试做过一些配置的更改,但是都没能达到效果。目前我们的数据采集给出的结论是,目前都不支持 L1。支持到 L3 级别。所以我更倾向于这块被限制了。
也欢迎评论分享有没有别的解法?