Mar. 10, 2023
This whitepaper explains how to enable offline playback of DRM-protected videos. DRM (Digital Rights Management) protected videos are encrypted to prevent unauthorized distribution and copying. Enabling offline playback means allowing users to download and view these encrypted videos without an internet connection while maintaining the DRM protection. The tutorial describes a solution that adopts a standard format, utilizes the existing platform’s DRM, and avoids re-transcoding. The recommended solution employs a SPEKE server to generate and distribute DRM keys. To play the video offline, the key is extracted from the SPEKE server and provided to the player through a local file. The solution runs as a script within a Docker container on AWS Fargate, launched by a Lambda function triggered by S3 events or manually for backlog processing.
———————————————————————————–
DRM (Digital Rights Management) protected videos are videos that are encrypted to prevent unauthorized distribution and copying. To provide offline playback of HLS-encoded DRM-protected videos means allowing users to download and view these encrypted videos without an internet connection.
The challenge is to maintain encrypted protection when played offline. It is hence critical to ensure that the DRM protection remains intact even when the video is played without an internet connection.
This article describes a solution that enables the offline playback of DRM-protected videos.
The following constraints were taken into consideration:
The recommended platform solution employs a SPEKE server for the generation and distribution of DRM keys. The SPEKE server will generate an AES-128 encryption key for each video during transcoding, which is then provided to the player through a unique URL when the video is played.
The player deciphers the video segments using this key. In order to play the video offline, the key must be provided to the player without accessing the SPEKE server. To achieve this, the key is extracted from the SPEKE server and provided to the player through a local file.
The below HLS files are stored on S3 and are structured as follows:
{course_id}/{lesson_id}/index.m3u8
{course_id}/{lesson_id}/index_{720/1080/2160}.m3u8
{course_id}/{lesson_id}/index_{720/1080/2160}_{1/…}.ts
Here, index.m3u8 is the master index file that points to each resolution’s index file. index_{720/1080/2160}.m3u8 is the index file for each resolution and contains a list of video segments and a URL to the SPEKE server, which provides the DRM decryption key for the segments.
The following is a high-level tutorial of the implementation:
This will result in the creation of a zip file for each resolution that can be downloaded by the user.
The following outlines the process for downloading and playing the video on the client side:
Download the zip file for the desired resolution.
Download the SPEKE DRM key from the SPEKE server. This file can be downloaded and stored alongside the zip file, it is identified by the {course_id}-{lesson_id} ID pair.
Since a standard HLS format is used, the video will play without any additional work.
Access control can be managed through a lifecycle rule on the SPEKE DRM key file, which can delete the key after a specified amount of time offline. Once the key is deleted, the user will be required to re-authenticate and download the key again, the video does not need to be downloaded again.
Solution requirements:
The solution runs as a script within a Docker container on AWS Fargate. The container is launched by a Lambda function, which can be triggered by S3 events or manually for backlog processing.
The container has the following input parameters, which are passed through environment variables:
The container task definition will be created once, and the environment variables will be filled in at runtime using the S3 event data by the Lambda function, which will then launch the task on Fargate.
A more detailed description of the logic of the script is provided below, along with a pseudo-code outline of the logic.
Copy the HLS files for the lesson locally:
aws s3 cp s3://{input_bucket}/{lesson_key} . –recursive |
Redirect the SPEKE DRM URL to a local file:
sed -i ‘s|https://speke.foo.com/{lesson_key}/{UUID}|./{UUID}|g’ index.m3u8 |
Parse the available resolutions from the master HLS manifest:
# The following command will extract the available resolutions from the master HLS manifest, here the “1440” from the following line : # EXT-X-STREAM-INF:BANDWIDTH=2658558,AVERAGE-BANDWIDTH=895257,CODECS=”avc1.4d4032,mp4a.40.2″,RESOLUTION=2560×1440,FRAME-RATE=29.970 RESOLUTIONS=$(cat index.m3u8 | grep EXT-X-STREAM | sed -nr ‘s|.*RESOLUTION=[0-9]*x([0-9]*),.*|\1|p’) |
For each resolution, the following steps are performed:
mkdir temp && cd temp |
mv ../index_{resolution}.m3u8 ../index_{resolution}_*.ts . |
# Copy the master manifest header head -n 3 ../index.m3u8 > index.m3u8 # Copy the current resolution from the master manifest cat ../index.m3u8 | grep -A 1 “x$resolution“ >> index.m3u8 |
zip -r ../{lesson_key}_{resolution}.zip index.m3u8 index_{resolution}.m3u8 index_{resolution}_*.ts |
aws s3 cp ../{lesson_key}_{resolution}.zip s3://{output_bucket}/{lesson_key}_{resolution}.zip |
cd .. && rm -rf temp |
The complete script is as follows:
#!/bin/sh # Copy the HLS files for the lesson locally aws s3 cp s3://${input_bucket}/${lesson_key} . –recursive # Redirect the SPEKE DRM URL to a local file sed -i ‘s|https://speke.foo.com/${lesson_key}/${UUID}|./${UUID}|g’ index.m3u8 # Parse the available resolutions from the master HLS manifest RESOLUTIONS=$(cat index.m3u8 | grep EXT-X-STREAM | sed -nr ‘s|.*RESOLUTION=[0-9]*x([0-9]*),.*|\1|p’) # For each resolution for resolution in $RESOLUTIONS; do # Create a temporary folder and move into it mkdir temp && cd temp # Move the current resolution video segments and associated manifest to the temporary folder mv ../index_${resolution}.m3u8 ../index_${resolution}_*.ts . # Create a new master manifest file pointing to the current resolution from the main master manifest # Copy the master manifest header head -n 3 ../index.m3u8 > index.m3u8 # Copy the current resolution from the master manifest cat ../index.m3u8 | grep -A 1 “x$resolution“ >> index.m3u8 # Create a zip file containing the master manifest, the resolution manifest and the current resolution video segments zip -r ../${lesson_key}_${resolution}.zip index.m3u8 index_${resolution}.m3u8 index_${resolution}_*.ts # Copy the resulting zip file to S3 aws s3 cp ../${lesson_key}_${resolution}.zip s3://${output_bucket}/${lesson_key}_${resolution}.zip # Move back to the parent folder and delete the temporary folder cd .. && rm -rf temp done |
The solution described in this article offers a way to enable offline playback of DRM-protected videos by performing the following steps:
The solution addresses the challenge of offline playback of DRM-protected videos by ensuring that the necessary HLS files and manifests are accessible locally and the DRM protection remains intact. The resulting zip file is then copied to S3, providing an easily accessible method for offline playback.