How to create Widevine DRM protected content

Overview

Widevine is a Hollywood grade DRM technology initially developed by Widevine Technologies and acquired by Google in 2010. For Google it was not only a technology acquisition it was also a strategic play. The acquisition opened new connections into the premium video sector and deepened also the relationship with Hollywood. Beside, that the technology fits perfect into the Google ecosystem and plays well together with Android and YouTube, which will help to expand their overall video business. Widevine is natively supported on broad range of devices and browsers such as Google Chrome Browser, Android, Chromecast, etc.

Widevine DRM Requirements

  • In order to use Widevine DRM a DRM solution provider (e.g. Irdeto, EZDRM, ExpressPlay, Axinom, etc.) is required, or you integrate it a Widevine Proxy Service yourself.

About this example

The code snippets shown here are based on the full example called CencDrmContentProtection.java, using our Bitmovin SDK for Java.

Hint: If you haven't created any encodings with our Service yet, its recommended to start with our quick start guide called "Get Started with the Bitmovin API" first, before you continue :)

Encoding with DRM Configuration

Encryption details

To encrypt your content so it can be used with Widevine DRM, an encryption key (referred to as DRM_KEY in the example) is required. All other values are optional, however sometimes required by specific DRM vendors, therefore have to be set (DRM_WIDEVINE_KID, DRM_WIDEVINE_PSSH, ...).

These values of the Widevine DRM configuration are expected in the following format:

  • DRM_KEY: (required) You need to provide a key that will be used to encrypt the content (16 byte encryption key, represented as 32 hexadecimal characters)
  • DRM_WIDEVINE_KID: also known as Key ID, or ContentID. Its a unique identifer for your content (16 byte initialization vector, represented as 32 hexadecimal characters)
  • DRM_WIDEVINE_PSSH: Base64 encoded String, PSSH payload Example: QWRvYmVhc2Rmc2FkZmFzZg==

HINT: Some DRM providers provide you with a dedicated service to create and safely store Encryption Keys, so you don't have to create and manage them by yourself. These values are required to generate a proper playback license using DRM solution providers like Irdeto, EZDRM, ExpressPlay, Axinom, etc. to control playback permissions on the client side. Learn more.

Muxing DRM Configuration

When you create an encoding, you define Streams which point to the video track of the input file, and couple them with an Codec Configuration of your choice. These Streams are then used by Muxings which determine the desired output format of your content.

Widevine DRM can be used with fMP4 Muxings or WebM Muxings, therefore works with H264 or VP9. In order to configure a Muxing to create DRM encrypted content, you add a CencDRM Configuration (API reference) to it. Its a general DRM configuration object, where you can provide the required key to encrypt the content, along with DRM solution specific details.


The example creates two Streams - one for the video-Stream (H264) and one for the audio-Stream (AAC). For each of the Streams and fMP4 Muxing is created, without providing a output destination.

Java SDK Example - create Encoding (Line in Example)

Encoding encoding =
    createEncoding("fMP4 muxing with CENC DRM", "Example with CENC DRM content protection");

HttpInput input = createHttpInput(configProvider.getHttpInputHost());
Output output =
    createS3Output(
        configProvider.getS3OutputBucketName(),
        configProvider.getS3OutputAccessKey(),
        configProvider.getS3OutputSecretKey());

H264VideoConfiguration h264Config = createH264VideoConfig();
AacAudioConfiguration aacConfig = createAacAudioConfig();

Stream videoStream =
    createStream(encoding, input, configProvider.getHttpInputFilePath(), h264Config);
Stream audioStream =
    createStream(encoding, input, configProvider.getHttpInputFilePath(), aacConfig);
    
Fmp4Muxing videoMuxing = createFmp4Muxing(encoding, videoStream);
Fmp4Muxing audioMuxing = createFmp4Muxing(encoding, audioStream);
...

In typical DRM Encoding workflows the Output configuration is part of The DRM Config only. It is added to the muxing by the createDrmConfig method. So, it defines which output shall be used to store the encrypted content.

Java SDK Example - Add DRM Config to Muxing (Line in Example)

createDrmConfig(encoding, videoMuxing, output, "video");
createDrmConfig(encoding, audioMuxing, output, "audio");

IMPORTANT: You can still provide an Output config to the fMP4 Muxing as well, but it would push the unencrypted version of your encoded content to this Output destination. So, if you want to create encrypted content only, provide an Output configuration exclusively as part of your DRM Config.

Java SDK Example - createDrmConfig() Method (Line in Example)

private static CencDrm createDrmConfig(
    Encoding encoding, Muxing muxing, Output output, String outputPath) throws BitmovinException {
  CencDrm cencDrm = new CencDrm();
  cencDrm.addOutputsItem(buildEncodingOutput(output, outputPath));
  cencDrm.setKey(configProvider.getDrmKey());
  cencDrm.setKid(configProvider.getDrmWidevineKid());
  
  CencWidevine widevineDrm = new CencWidevine();
  widevineDrm.setPssh(configProvider.getDrmWidevinePssh());
  cencDrm.setWidevine(widevineDrm);
  
  ...
  
  return bitmovinApi.encoding.encodings.muxings.fmp4.drm.cenc.create(
      encoding.getId(), muxing.getId(), cencDrm);
}

That's it, so we can start this encoding now with executeEncoding() and create HLS and MPD manifests for it, after the encoding is finished.

Java SDK Example - Start Encoding and create HLS and MPD Manifests (Line in Example)

executeEncoding(encoding);

generateDashManifest(encoding, output, "/");
generateHlsManifest(encoding, output, "/");

generateDashManifest and generateHlsManifest are using the DefaultManifest API call for MPEG-DASH (Example) and HLS (Example). These methods are easy to configure and enable to you create a simple manifest that for each streaming format that reference all the contents that were created and can be used by the respective Streaming Format.

While your MPD, will only show the DRM protected Video- and Audio track protected with Widevine DRM, your HLS manifest holds the details to play this content with Widevine or Fairplay DRM.

Get Started with a Bitmovin SDK

Bitmovin API SDKDescription
JavaIntegrate the SDK into your Java Project easily and add it to the config of your dependency manager like Maven or Gradle. Learn more
Javascript/TypescriptIntegrate the SDK into your Javascript/Typescript based project easily by adding it as a dependency via NPM. Learn more
PythonIntegrate the SDK into your Python based project easily by adding it as a dependency via pip or Setuptools. Learn more
.NETIntegrate the SDK into your .NET based project easily by adding it as a dependency via nuget. Learn more
PHPIntegrate the SDK into your PHP based project easily by adding it as a dependency via composer. Learn more

Visit our Github Example Repository that provides you with examples for all Bitmovin SDK's available.