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.
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:
A Google Cast sender is an app with a "cast" button. Clicking the cast button performs two actions.
In this section we'll walk through how to write your own web-based Google Cast 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:
playback-token
: A signed playback token, as documented in our Guide to Secured Video Playbackdrm-token
: A signed DRM token, as documented in the Sign a DRM license token section of our DRM guidecast-receiver
: The application ID of your custom receiver, as documented in the Custom Receiver section belowThis 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>
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
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.
Before we can write the code, we need to take care of a couple prerequisites.
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.
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.