HLS with fragmented MP4
When streaming fMP4 over HLS, Apple specifies the 'cbcs' encryption scheme for encrypting content. This is the only encryption scheme of the 3rd edition of the Common Encryption (CENC) specification that Apple supports.
Because the 'cbcs' is part of CENC, adding it to Origin's fMP4 HLS output requires you to signal the encryption information as being compatible with CENC in addition to signaling the information for HLS.
Signaling the CENC related information is done with the parameters that start
with iss
, while the information necessary for HLS is signaled using the
parameters starting with hls
. The result is that the CEK and KIV need to
be signaled twice.
Adding 'cbcs' Encryption
Below an example command-line for adding encryption according to CENC's 'cbcs' scheme. Please read HLS with fragmented MP4 for some necessary background information.
#!/bin/bash
CEK=3a2a1b68dd2bd9b2eeb25e84c4776668
KID=10000000100010001000100000000001
KIV=f9d9d5f5f3b5bc0372856df068f9f6a2
# Store binary representation of CEK in cek.key file
echo ${CEK} | xxd -p -r > cek.key
# URL that resolves to the cek.key file
LA_URL=https://license-server/cek.key
mp4split -o tos-fmp4-hls-cbcs.ism \
--hls.fmp4 \
--iss.key=${KID}:${CEK} \
--iss.key_iv=${KIV} \
--hls.key=:${CEK} \
--hls.key_iv=${KIV} \
--hls.license_server_url=${LA_URL} \
--hls.playout=sample_aes \
tears-of-steel-aac-128k.cmfa \
tears-of-steel-avc1-1500k.cmfv
Note
In case you are only concerned with adding encryption to your fMP4
HLS according to CENC's 'cbcs' scheme, the KID that you input as the first
part of the value for the --iss.key
parameter can be blank, because Apple
does not specify the use of a KID. The same is true for the value signaled for
--iss.license_server_url
, which is not relevant in such cases either.
Adding FairPlay DRM
Find below an example command-line for adding FairPlay DRM with encryption
according to CENC's 'cbcs' scheme. Please read HLS with fragmented MP4 for some
necessary background information. The '<license-server-url>' that you pass on
the command-line using --hls.license_server_url
is dependent on your
FairPlay implementation (i.e., you have to provide the exact information
yourself).
#!/bin/bash
CEK=3a2a1b68dd2bd9b2eeb25e84c4776668
KID=10000000100010001000100000000001
KIV=f9d9d5f5f3b5bc0372856df068f9f6a2
mp4split -o tos-fmp4-hls-cbcs.ism \
--hls.fmp4 \
--iss.key=${KID}:${CEK} \
--iss.key_iv=${KIV} \
--hls.key=:${CEK} \
--hls.key_iv=${KIV} \
--hls.license_server_url=<license-server-url> \
--hls.playout=sample_aes_streamingkeydelivery \
tears-of-steel-aac-128k.cmfa \
tears-of-steel-avc1-1500k.cmfv
Note
In case you do not require any multi-DRM functionality and are
only concerned with adding FairPlay, the KID that you input as the first part
of the value for the --iss.key
parameter can be a dummy, because Apple
does not specify the use of a KID. The same goes for the value signaled for
--iss.license_server_url
, which is not relevant in such cases either.
Adding PlayReady DRM
PlayReady requires the DRM related information to be signaled in a base64
encoded PlayReady Object, which you should provide yourself. This PlayReady
Object will be a blob of data that you can pass on the command-line using the
--iss.drm_specific_data
. Unified Origin will extract the PlayReady Header
(WRMHeader encoded as UTF16) from the PlayReady Object and signal it in the
playlist.
#!/bin/bash
KID=10000000100010001000100000000001
CEK=5b7d5b7d5b7d5b7d5b7d5b7d5b7d5b7d
KIV=3B3A3B3A3B3A3B3A3B3A3B3A3B3A3B3A
PR_OBJECT=uAIAAAEAAQCuAjwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADMALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAOgAvAC8AZQB4AHAAZQByAGkAbQBlAG4AdABhAGwAMQAuAGEAegB1AHIAZQB3AGUAYgBzAGkAdABlAHMALgBuAGUAdAAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4AD8AYwBmAGcAPQAoAGMAawA6AFcAMwAxAGIAZgBWAHQAOQBXADMAMQBiAGYAVgB0ADkAVwAzADEAYgBmAFEAPQA9ACwAYwBrAHQAOgBBAEUAUwAxADIAOABCAGkAdABDAEIAQwApADwALwBMAEEAXwBVAFIATAA+ADwAUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABLAEkARABTAD4APABLAEkARAAgAEEATABHAEkARAA9ACIAQQBFAFMAQwBCAEMAIgAgAFYAQQBMAFUARQA9ACIAQQBBAEEAQQBFAEEAQQBRAEEAQgBBAFEAQQBCAEEAQQBBAEEAQQBBAEEAUQA9AD0AIgA+ADwALwBLAEkARAA+ADwALwBLAEkARABTAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A
mp4split -o hls-fmp4-playready.ism \
--hls.fmp4 \
--iss.key=$KID:$CEK \
--iss.key_iv=$KIV \
--iss.drm_specific_data=$PR_OBJECT \
--hls.playout=playready \
--hls.minimum_fragment_length=6 \
cmaf/tears-of-steel-aac-64k.cmfa \
cmaf/tears-of-steel-aac-128k.cmfa \
cmaf/tears-of-steel-avc1-400k.cmfv \
cmaf/tears-of-steel-avc1-750k.cmfv \
cmaf/tears-of-steel-avc1-1000k.cmfv \
cmaf/tears-of-steel-avc1-1500k.cmfv
Note
Currently (March 2018), the playout support for PlayReady with 'cbcs' encryption is very limited. The only known client to support this combination is the Xbox upgraded to software version 1709 or higher.
Adding Widevine DRM
For Widevine, you put the DRM information in a CPIX file (for more info on this format, see Introduction to CPIX):
#!/bin/bash
mp4split -o hls-fmp4-widevine.ism \
--hls.fmp4 \
--hls.cpix=hls-fmp4-widevine.cpix \
--hls.playout=widevine \
--hls.minimum_fragment_length=6 \
cmaf/tears-of-steel-aac-64k.cmfa \
cmaf/tears-of-steel-aac-128k.cmfa \
cmaf/tears-of-steel-avc1-400k.cmfv \
cmaf/tears-of-steel-avc1-750k.cmfv \
cmaf/tears-of-steel-avc1-1000k.cmfv \
cmaf/tears-of-steel-avc1-1500k.cmfv
Where hls-fmp4-widevine.cpix
contains the following (note that the PSSH data
for Widevine contains explicit signaling for the cbcs
encryption scheme):
<CPIX xmlns:pskc="urn:ietf:params:xml:ns:keyprov:pskc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:dashif:org:cpix" xsi:schemaLocation="urn:dashif:org:cpix cpix.xsd">
<ContentKeyList>
<ContentKey kid="d69109a4-380b-59eb-8473-1c4c73d5c2e6">
<Data>
<pskc:Secret>
<pskc:PlainValue>3EoZk8ABlJ7JLzP9nryzzw==</pskc:PlainValue>
</pskc:Secret>
</Data>
</ContentKey>
</ContentKeyList>
<DRMSystemList>
<DRMSystem kid="d69109a4-380b-59eb-8473-1c4c73d5c2e6" systemId="edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
<PSSH>AAAAOHBzc2gBAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAAAAAAUIgx3aWRldmluZWNiY3NI88aJmwY=</PSSH>
<HLSSignalingData playlist="media"></HLSSignalingData>
<HLSSignalingData playlist="master"></HLSSignalingData>
</DRMSystem>
</DRMSystemList>
</CPIX>