| 4 min read

最近在开发中遇到了 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 级别。所以我更倾向于这块被限制了。

也欢迎评论分享有没有别的解法?

You Can Speak "Hi" to Me in Those Ways