Skip to Content

Play DRM protected videos on Google Cast Devices

Learn how to use Google Cast with DRM-protected Mux Video content.

Google Cast is a popular method for sending video from one device to be played on another, often from a phone to a TV. Most players support Google Cast out of the box, but if your video is protected by DRM, you will need to do a little more work.

Overview

Google Cast integrations are made up of two parts, a "sender" and a "receiver". In the example of a phone casting to a TV, the player in a mobile browser is the sender and the receiver is a webpage sent to the TV.

There are quite a few steps in this process, so here's a quick overview:

  1. Create a sender, either with the Mux Player or by writing your own
  2. Create your playback ID, playback token and DRM token, and add them to the sender
  3. Register your test device in the Google Cast dashboard
  4. Create a custom receiver and register it on the Google Cast dashboard
  5. Add the registered receiver ID to the custom sender

Sender Setup

A Google Cast sender is an app with a "cast" button. Clicking the cast button performs two actions.

  1. If you're not yet connected to another device, the cast button helps set up that connection.
  2. Once you're connected to a device, the sender sends everything needed to play a video to the receiver.

In this section we'll walk through how to write your own web-based Google Cast sender.

Mux Player Sender

The easiest way to set up your own sender is with Mux Player for Web. In addition to the usual playback-id property, you'll need to include additional security and Google Cast fields:

This is only supported in Mux Player version 3.4.1 or greater

<script src="https://cdn.jsdelivr.net/npm/@mux/mux-player" defer></script>
<mux-player
  id="player"
  playback-id="your-playback-id"
  playback-token="your-playback-token"
  drm-token="your-drm-token"
  cast-receiver="your-cast-receiver-app-id"
></mux-player>

Custom Web Sender

If you're not using Mux Player, Google offers SDKs for Web, Android and iOS. In this section we'll walk through installing the Web SDK and sending a video with DRM to a custom receiver.

Before you build your own custom web sender, you'll need to create a playback token and a DRM license token.

Note: Google Cast and DRM only works in secure contexts, such as HTTPS or localhost.

Include the following script wherever you want to show a cast button.

<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

Before we can cast any videos we need to configure the cast context. The cast framework gives us a great place to do that, in the global __onGCastApiAvailable function.

window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    cast.framework.CastContext.getInstance().setOptions({
      receiverApplicationId: 'your-receiver-app-id',
      autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED,
    });
  }
};

For DRM, you'll need to build your own receiver and add the ID to receiverApplicationId. We can help you with that in our custom receiver guide.

Let's write a function to encapsulate sending our video over to the receiver.

First we're going to collect all the data we need to play the video in variables at the top.

function playVideo(context) {
  const playbackId = 'your-playback-id';
  const playbackToken = 'your-playback-token';
  const drmToken = 'your-drm-token';
  const mediaUrl = `https://stream.mux.com/${playbackId}.m3u8?token=${playbackToken}`;

Each of these variables help identify a single asset.

  • playbackId: An asset can have one or many playback IDs. This is different from the asset ID. You can find it in the API, or in the Mux Dashboard.
  • playbackToken: A signed playback token, as documented in our Guide to Secured Video Playback.
  • drmToken: A signed DRM token, as documented in the Sign a DRM license token section of our DRM guide.

Then we'll build a MediaInfo object to include all the information Google Cast needs to play the video.

let mediaInfo = new chrome.cast.media.MediaInfo(mediaUrl, 'application/x-mpegurl');

// Mux HLS URLs with DRM will always use `fmp4` segments.
mediaInfo.hlsSegmentFormat = chrome.cast.media.HlsSegmentFormat.FMP4;
mediaInfo.hlsVideoSegmentFormat = chrome.cast.media.HlsVideoSegmentFormat.FMP4;

// Send the information needed to create a new license url.
mediaInfo.customData = {
  mux: {
    playbackId,
    tokens: {
      drm: drmToken
    }
  }
}

And finally we'll ask the receiver to load the video.

const request = new chrome.cast.media.LoadRequest(mediaInfo);

// Cast the video.
context.getCurrentSession().loadMedia(request).then(() => {
  console.log('Successfully loaded the media');
}).catch((err) => {
  console.log(`Media playback error code: ${err}`);
});

Here's the function in its entirety:

Now we need to hook it up to the cast action. In this example we'll send it as soon as possible by listening for the cast session to start.

let context = cast.framework.CastContext.getInstance();
context.addEventListener(cast.framework.CastContextEventType.SESSION_STATE_CHANGED, function(event) {
  switch (event.sessionState) {
    case cast.framework.SessionState.SESSION_STARTED:
    case cast.framework.SessionState.SESSION_RESUMED:
      playVideo(context);
      break;
  }
});

Once all your code is hooked up, adding the button is the easiest part. Put this in the HTML of your page and you're good to go.

<google-cast-launcher>Launch</google-cast-launcher>

More Docs

Receiver Setup

A Google Cast receiver is a web page that receives data from a sender and plays your video. This is always a webpage, written in HTML and JavaScript, even if you're using a mobile SDK for casting.

Receiver Prerequisites

Before we can write the code, we need to take care of a couple prerequisites.

  1. You need a way for devices to access this web page with a public URL. We recommend either you host the files yourself, or use ngrok during development to expose local files on a public URL.
  2. You need to register the receiver's public URL with Google in the Google Cast SDK Developer Console. If you have not joined the Google Cast Developer program, do so now.
  3. Once you have registered your receiver, you will see your app listed in the dashboard with a unique Application ID. This is the same receiver ID you will configure in the Mux Player or Custom Sender.
  4. Until your app is published, you can only cast to registered development devices. This registration requires the destination device's serial number. If you can't find the serial number on the outside of the device, you can use the Chrome browser to cast the dashboard directly to the device. This will show a new screen, prominently displaying the device's serial number.

Receiver Implementation

Google's custom receiver SDK has a lot of functionality built in, so we don't have to do a lot of work. The only thing we need to do is manage the DRM license URL. Before we start working with License URLs, we'll want a small HTML file to describe the playback UI. Here's a minimal example.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title></title>
        <!-- Web Receiver SDK -->
        <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
        <!-- Cast Debug Logger -->
        <script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
    </head>

    <body>
        <cast-media-player></cast-media-player>
        <footer>
            <script src="js/receiver.js"></script>
        </footer>
    </body>
</html>

In the above example, the two script tags in the header load the SDK and the Google Cast logger. Further on you'll see a <cast-media-player>, which the Google Cast SDK automatically turns into a video player, and a script for managing the DRM.

Now let's create that script. To start, we're going to grab a reference to the cast context and configure the logger.

const context = cast.framework.CastReceiverContext.getInstance();

/**
 * DEBUGGING
 */
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MUX';
castDebugLogger.setEnabled(true);

// Debug overlay on tv screen.
// You don't need this if you're debugging using the cast tool (https://casttool.appspot.com/cactool) as it will show the logs in your browser.
castDebugLogger.showDebugLogs(true);

castDebugLogger.loggerLevelByTags = {
  [LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};

Next we're going to intercept all playback requests and see if the request includes DRM license information.

context.getPlayerManager().setMediaPlaybackInfoHandler((loadRequest, playbackConfig) => {
  const customData = loadRequest.media.customData || {};

  if(customData.mux && customData.mux.tokens.drm){

In that conditional, let's build our license URL and add it to the playbackConfig.

playbackConfig.licenseUrl = `https://license.mux.com/license/widevine/${customData.mux.playbackId}?token=${customData.mux.tokens.drm}`;
  }

  playbackConfig.protectionSystem = cast.framework.ContentProtection.WIDEVINE;
  castDebugLogger.debug(LOG_TAG, 'license url', playbackConfig.licenseUrl);

  return playbackConfig;
});

Finally, we start listening for incoming requests with the line

context.start();

Click the button below to view the full JavaScript file.

More docs

Testing

Once you've completed every step (Triple check the overview steps!) load up your sender, click the cast button and choose to cast to your test device. After a quick loading screen your DRM-protected video will start playing.

If you're testing our example, the video will automatically start playing behind the cast log. You can remove the cast log by commenting out the line castDebugLogger.setEnabled(true); in your custom receiver.

Was this page helpful?