The following tutorial will show you how to set up offline playback using Bitmovin and ExpressPlay DRM.
On 30th November 2016 Netflix announced the support for offline playback, which has been one of the most requested features from the Netflix user base. With this new feature users are now able, not only to playback content while they are online, but also while they do not have an active data connection. For selected movies and shows a “download” button is available in the app that will download the content on the user’s device and make it available to be watched at a later time without the need for an Internet connection.
After this announcement many customers have approached us wanting to know how to set up offline playback with the Bitmovin services. We are happy to say that we have supported offline playback, together with our partner ExpressPlay, for some time. However, getting so many requests motivated us to write this blog post to explain in detail how offline playback can be achieved with the services of Bitmovin and ExpressPlay.
In general, the following steps required to package and playback protected content in an offline playback scenario are:
- Encode and encrypt your content for offline playback, e.g., one or multiple fMP4 files that can be downloaded
- Request a DRM token for a persistent license from the ExpressPlay service
- Pass the token to a DRM client that will retrieve the corresponding persistent license which will get stored within the device
- Download and play the protected content
The following tutorial will describe how to implement the workflow outlined above with the services from Bitmovin and ExpressPlay. First we will show how to generate multiple encrypted progressive MP4 files using the cloud encoding product from Bitmovin. Then we will use the ExpressPlayer app provided by Intertrust as a client and Marlin Broadband (MBB) licenses for offline playback.
Encode and encrypt your content for offline playback
It is a fun coincidence that we announced our new Bitmovin API at exactly the same day when Netflix announced their support for offline playback. The new Bitmovin API has already full support to encode and package content to be used for offline playback. In the following tutorial I will show you how to do that.
For offline playback you will typically package the content as fMP4 files in different qualities. Just like Netflix, you can then allow your customers to choose between high quality or fast download. The easiest and definitely recommended way to interact with the Bitmovin API is with one of our API clients that are available in multiple programming languages. Currently, we offer API clients for the following languages: PHP, Python, GO, .NET, and JS. More are currently implemented and will be available soon.
For this tutorial we will be using the Bitmovin PHP API client that already has a neat example of how to create content that can be used for offline playback:
Initialize the Bitmovin API Client
$client = new BitmovinClient('INSERT YOUR API KEY HERE');
Create an input configuration
For the sake of simplicity we are using an HTTP(S) input, although many other input sources such as AWS S3, Google Cloud Storage, Microsoft Azure, Aspera, and (S)FTP are also supported.
$videoInputPath = 'INSERT YOUR HTTP VIDEO INPUT PATH HERE'; $input = new HttpInput($videoInputPath);
Create an output configuration
We are using a Google Cloud Storage bucket to directly transfer the encoded fMP4 files. This reduces turn-around times. You could also use other output options like S3, Azure, or (S)FTP. Another option is to store the encoded files on your Bitmovin Cloud Storage from where you can transfer it at a later time.
$gcs_accessKey = 'INSERT YOUR GCS OUTPUT ACCESS KEY HERE'; $gcs_secretKey = 'INSERT YOUR GCS OUTPUT SECRET KEY HERE'; $gcs_bucketName = 'INSERT YOUR GCS OUTPUT BUCKET NAME HERE'; $gcs_prefix = 'path/to/your/output/destination/'; $output = new GcsOutput($gcs_accessKey, $gcs_secretKey, $gcs_bucketName, $gcs_prefix);
Create an encoding profile configuration
An encoding profile configuration contains all the encoding related configurations for video/audio renditions as well as the encoding environment itself. Choose the region and cloud provider where the encoding should take place. Of course it is optimal if it is in the same cloud and region as you store your output 😉
$encodingProfile = new EncodingProfileConfig(); $encodingProfile->name = 'MP4-Muxing-Example'; $encodingProfile->cloudRegion = CloudRegion::GOOGLE_EUROPE_WEST_1;
Add video stream configurations to the encoding profile
In this example we create a full HD H.264 video stream. As said earlier you can also create other video qualities (e.g., 720p, 480p) for your customers to be available for download as well.
$videoStreamConfig_1080 = new H264VideoStreamConfig(); $videoStreamConfig_1080->input = $input; $videoStreamConfig_1080->width = 1920; $videoStreamConfig_1080->height = 1080; $videoStreamConfig_1080->bitrate = 4800000; $encodingProfile->videoStreamConfigs = $videoStreamConfig_1080;
Add an audio stream configuration to the encoding profile
$audioConfig = new AudioStreamConfig(); $audioConfig->input = $input; $audioConfig->bitrate = 128000; $audioConfig->name = 'English'; $audioConfig->lang = 'en'; $audioConfig->position = 1; $encodingProfile->audioStreamConfigs = $audioConfig;
Define the Progressive MP4 Output Format
As we want to create single MP4 files we choose the ProgressiveMp4OutputFormat and define the MP4 filename that should be used to store the file on your cloud storage. Additionally, we define a ClearKeyDrm configuration with a key and kid in hex format to encrypt the MP4 files. You can choose key and kid values on your own. However, please use the same values when you generate the Marlin MBB token.
$clearkey_key = 'CLEARKEY KEY'; $clearkey_kid = 'CLEARKEY KID'; $mp4Muxing1080 = new ProgressiveMp4OutputFormat(); $mp4Muxing1080->fileName = "1080p_4800kbps.mp4"; $mp4Muxing1080->streamConfigs = array($videoStreamConfig_1080, $audioConfig); $mp4Muxing1080->clearKey = new ClearKeyDrm($clearkey_key, $clearkey_kid);
Create Encoding Job and start it
The JobConfig acts as a container for all the previous configurations from above and will be passed to the BitmovinClient. The BitmovinClient will then start the encoding job and wait until it is finished.
$jobConfig = new JobConfig(); $jobConfig->output = $output; $jobConfig->encodingProfile = $encodingProfile; $jobConfig->outputFormat = $mp4Muxing1080; $client->runJobAndWaitForCompletion($jobConfig);
After the encoding job is finished you will have one or more encrypted MP4 files in your cloud storage. Next we will see how to create persistent Marlin tokens that can be used for the offline playback.
Request a MBB token for persistent licenses
ExpressPlay Multi-DRM service can be used to issue persistent licenses for Marlin, PlayReady, Widevine modular, and FairPlay. For this example we will describe how to request tokens and persistent licenses using Marlin DRM. The persistent licence is retrieved by using a MBB token that is requested using the REST API provided by ExpressPlay service.
The MBB token is then passed down the client that will use it to retrieve the actual license that may include all the business rules imposed by the service providers such as rental period, output control and more. The license is permanently stored and it will be used by the client to get access to the protected content as long as the rules expressed within are met.
Below is an example to request a MBB token:
The following is a short description of the attributes used. More details and options can be found in the ExpressPlay API reference:
- customerAuthenticator: Identifies the customer using the API. Can be found at admin.expressplay.com
- contentId: Use the kid that you used for the ClearKeyDrm configuration to derive the contentId, so it looks like ‘urn:marlin:kid:’
- contentKey: Use the same value as you used for the ClearKeyDrm key value.
- rightsType: Specifies the kind of rights. Must be BuyToOwn or Rental.
- actionTokenType: Must be 1. Signifies license action token.
With the above request you can download the token and store it next to your encrypted media files. In the next step we will see how the content can be played.
Currently, the playback of downloaded content is only possible using native players and not browser based players. ExpressPlay provides a client SDK that represents a robust implementation of Marlin DRM thus meeting all the studio requirements. The SDK is used to develop iOS, Android, Mac and Windows applications and is today used by major service providers around the globe. The ExpressPlayer app for Android and iOS, has been developed using the ExpressPlay SDK and is an excellent tool to verify that the entire workflow has been deployed correctly.
Simply start the app and select “Custom Input”. There you can enter the URL to your generated MP4 file and the URL to your generated token. Click “Process Media” to start the playback.
With the ExpressPlay SDK you can develop your Android or iOS app to playback the DRM protected content on your device. ExpressPlay offers a comprehensive tutorial that guides you through the process of creating a barebone Android ExpressPlay enabled media app to playback the content with a persistent license retrieved by a Marlin MBB token. Similar to the tutorial for Android, ExpressPlay also offers a tutorial for iOS.
Beside the presented use-case with Marlin DRM, the ExpressPlay service also supports persistent licences for Widevine, PlayReady and FairPlay that are used to enable offline playback of downloaded protected content.
To get started providing offline playback for your customers, sign up for a free Bitmovin API key and an account with ExpressPlay today and follow the steps in this example.