videojs / videojs-contrib-eme

Supports Encrypted Media Extensions for playback of encrypted content in Video.js
Other
203 stars 72 forks source link

FairPlay getContentId has sinf box (should have something from which skd can get extracted) #119

Open AwokeKnowing opened 4 years ago

AwokeKnowing commented 4 years ago

I was getting errors extracting contentId so I logged the init data:

{
  "com.apple.fps.1_0": {
    "certificateUri": "https://contentlicense-js9gan4za5h4mz7f6.knowledgecity.com/fpscert",
    "licenseUri": "https://contentlicense-js9gan4za5h4mz7f6.knowledgecity.com?assetid=173d970b1d8eba9687b21d403e9854c3",

    "getContentId": function(emeOptions, initData) {
        const strData = String.fromCharCode.apply(null, new Uint8Array(initData.buffer));
        console.log(strData)
        return "abc"
    }
  }
}

The results of strData are:

"{
  \"sinf\" : [
    \"AAAADGZybWFtcDRhAAAAFHNjaG0AAAAAY2JjcwABAAAAAAA5c2NoaQAAADF0ZW5jAQAAAAAAAQBVfi4NGlUpptLaOvCQxUuIEK6Awu7gJUgka4p2J91djjU=\"
  ]
}"

that seems pretty odd to me since I expected eg skd://173d970b1d8eba9687b21d403e9854c3

What can I do?

Note that based on issue #86 I also tried adding:

{
    "com.apple.fps.1_0": {
        initDataTypes: ['sinf'],
        videoCapabilities: [{
            contentType: 'video/mp4'
        }],
        "certificateUri": "https://contentlicense-js9gan4za5h4mz7f6.knowledgecity.com/fpscert",
        "licenseUri": "https://contentlicense-js9gan4za5h4mz7f6.knowledgecity.com?assetid=173d970b1d8eba9687b21d403e9854c3",
        "getContentId": function(emeOptions, initData) {
            const strData = String.fromCharCode.apply(null, new Uint8Array(initData.buffer));
            debugger;
            const hostname = "173d970b1d8eba9687b21d403e9854c3";
            return hostname;
        }
    }
}

here's my stream

https://cdn0.knowledgecity.com/vendors/videojs-contrib-eme/FPSTEST2/en/FPSTEST2-m2u1p/fp_hls/1587654321/FPSTEST2-m2u1p--v123445.m3u8

I'm on safari 13.1

AwokeKnowing commented 4 years ago

So it seems that contrib-eme only supports default .ts encoded streams which with the prefixed eme would generate the normal skd:// initData instead of the sinf initData.

I'm reading through : https://www.w3.org/TR/encrypted-media/#mediaencryptedevent for info on handling the sinf style

I'll report if i get it to work, though any example would be appreciated

AwokeKnowing commented 4 years ago

Problem was actually the mime type on the video was set to mp4 causing it to pull the sinf style data instead of skd

since the default get license method doesn't work on most drm providers, the errors thrown led me down long rabbit trail where I learned how to manually implement unprefixed mse directly with mp4 fairplay segments in safari.

so to clarify, I'm not using .ts and it's working fine in safari desktop and mobile, and skd is showing now. probably should have a doc like this somewhere

<!DOCTYPE html>
<html>
<head></head>
<body>
<link rel="stylesheet" href="https://vjs.zencdn.net/7.6.6/video-js.min.css">
<script src="https://vjs.zencdn.net/7.6.6/video.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/videojs-contrib-eme@3.7.0/dist/videojs-contrib-eme.js"></script>
<video preload="auto" width=960 id="myvideo" class="video-js vjs-default-skin" controls data-setup='{"plugins":{"eme":{}}}'></video>
<script>
    var serverProcessSPCPath  = 'https://fps.exmple.com'; 
    var serverCertificateURI = 'fps.cer';
    var m3u8Url = 'https://cdn.example.com/video.m3u8';
    player = videojs('myvideo');
    player.src({
        src: m3u8Url,
        type: 'application/x-mpegURL',
        keySystems: {
            'com.apple.fps.1_0': { 
                certificateUri: serverCertificateURI,
                getContentId: function(emeOptions, initData) {
                    return new TextDecoder('utf-16').decode(initData.slice(16));
                },
                getLicense: function(emeOptions, contentId, spc, callback)
                {
                    fetch(serverProcessSPCPath, {
                        method:  "post",
                        headers:{"Content-type":"application/x-www-form-urlencoded"},
                        body:    'spc='+encodeURIComponent(btoa(String.fromCharCode(...spc))) +
                                 '&assetId='+encodeURIComponent(contentId)
                    }).then(r=>r.text().then(ckcText => {
                        let b64key = ckcText.trim().slice(5,-6);// get AAA= from <ckc>AAA=</ckc>
                        let key = new Uint8Array(atob(b64key).split('').map(c=>c.charCodeAt(0)));
                        callback(null, key)
                    }));
                }
            } 
        }
    });
</script>
</body>
</html>