kaltura / nginx-vod-module

NGINX-based MP4 Repackager
GNU Affero General Public License v3.0
1.98k stars 439 forks source link

Manifest switch to version 6 when using drm encryption #1304

Open kolevgeorgie opened 3 years ago

kolevgeorgie commented 3 years ago

I have a running configuration that serves HLS VOD and I'm trying to test integration with Widevine DRM. The configuration seems to be working and nginx successfully serves manifest but it's changed in a way that breaks delivery.

My working configuration:

    location /remote/ {
        log_subrequest off;

        vod hls;
        vod_mode remote;

        vod_upstream_location /vod_upstream;

        vod_bootstrap_segment_durations 2000;
        vod_bootstrap_segment_durations 3000;
        vod_bootstrap_segment_durations 4000;

        vod_max_upstream_headers_size 8k;

        rewrite /remote/(.*) /$1 break;

        add_header X-Via-Source 'remote';
    }

which deliveres the following:

#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:2.000,
seg-1-v1-a1.ts
#EXTINF:4.762,
seg-2-v1-a1.ts

To that configuration I add the following:

        vod_hls_encryption_method sample-aes-cenc;
        vod_drm_enabled on;
        vod_drm_clear_lead_segment_count 0;
        vod_drm_upstream_location /key_proxy;

but this generates different m3u8:

#EXTM3U
#EXT-X-TARGETDURATION:6
#EXT-X-ALLOW-CACHE:YES
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=SAMPLE-AES-CENC,URI="data:text/plain;base64,AAAAK3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAsiAzEyM0jj3JWbBg=="
#EXT-X-VERSION:6
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-MAP:URI="http://domain/file.mp4/init-v1-a1.mp4"
#EXTINF:2.000,
seg-1-v1-a1.m4s
#EXTINF:4.762,
seg-2-v1-a1.m4s

(domain/file are dummy, replacing the real path to file for the purpose of issue) So I see that EXT-X-VERSION changed to 6 and the EXT-X-MAP:URI which points in my case to a file that does not exist. Also the segments changed from ts to m4s.

I really can't find any reason for nginx-vod doing this and also no documentation on the issue. Any help is appreciated.

erankor commented 3 years ago

Use of SAMPLE-AES-CENC (renamed to SAMPLE-AES-CTR in later versions) requires fMP4 container. That is the reason you get EXT-X-MAP, and also the reason you get version 6, from the HLS spec - Use of the EXT-X-MAP tag in a Media Playlist that DOES NOT contain the EXT-X-I-FRAMES-ONLY tag REQUIRES a compatibility version number of 6 or greater. This encryption scheme works only with unmuxed video/audio, from what you pasted, I'm guessing you are requesting index.m3u8... If you will request master.m3u8 instead, you will get separate index.m3u8's for video/audio, and the URLs inside them will work.

kolevgeorgie commented 3 years ago

Thanks for the input. Any recommendation that will not require intervention of the source and keep the MP4 container?

erankor commented 3 years ago

AFAIK there's no such thing cenc scheme using MPEG-TS, if that is the question...

kolevgeorgie commented 3 years ago

The question is - how can I apply drm without adding EXT-X-MAP:URI which actually points to mp4 that does not exist.

erankor commented 3 years ago

So, as I wrote above, you can't have video+audio muxed on the same segment when you use SAMPLE-AES-CENC, meaning - request for index.m3u8 will not work, but index-v1.m3u8 / index-a1.m3u8 are expected to work fine. If you use master.m3u8, it will return a manifest that uses EXT-X-MEDIA in order to have the video/audio separate.

kolevgeorgie commented 3 years ago

Right, thanks for clarification. I tested with simple configuration and it "seems" to be working - master.m3u8 delivers both audio and video streams and they are loaded, but cannot be played. I suspect that something with the encryption/decryption might not be ok, but then even adding vod_drm_clear_lead_segment_count 5; so that first 5 segments are not encrypted, player fails to load any content.

I'm testing with hls.js here: https://hls-js.netlify.app/demo/

erankor commented 3 years ago

IIRC I tested this configuration only on Shaka player, but you will need the latest code - they changed the spec at some point, and renamed METHOD=SAMPLE-AES-CENC to METHOD=SAMPLE-AES-CTR