Custom and Styled Receiver Application Registration

Register Chromecast Receiver App

Your custom receiver application be it your own or using the provided receiver as a base requires to be registered to obtain an application ID.

It is not required to be published for debugging and testing. Once it is published it will become available on Google systems to advertise your application.

Choose the "Custom Receiver" or "Styled Receiver" option and enter the location of the custom receiver url.

For the "Styled Receiver" application configure a url to the provided css file to custom style the Google supplied receiver.

Once registered you will be provided with an application ID which you configure into the "castAppID" config. More Info

Chromecast Device Registration For Debugging

The Chromecast device is required to also be registered for debugging purposes and to gain access to the debug console port.

At the end of the registration page explains how to also register your device by entering in it's serial number.

To enable remote debugging of the receiver after the dongle serial is registered, in chrome go into the device inspection.

chrome://inspect

It is possible to debug the receiver application into a chromecast console by entering the Chromecast dongle's ip address with a port 9222 on the end like

localip:9222

To obtain the ip address you can obtain this from the DHCP table of your router.

Once the receiver has been launched locate to the Chromecast ip address and port and click "Remote Debugging (AppEngine)". For non-HTTPS connections, click the grey shield icon in the address bar in the top right hand corner and then click "load unsafe scripts".

More Information: https://developers.google.com/cast/docs/debugging/remote_debugger

Configuration

Here is a list of the configuration options:

Property Description Default
autoJoinPolicy The chrome cast auto join policy. either origin, tab or page. See https://developers.google.com/cast/docs/reference/chrome/chrome.cast.AutoJoinPolicy origin
castAppID For custom receiver applications set the application id for the custom receiver.
messages The connection and playing message status text. { connecting: "CONNECTING TO", playing: "PLAYING ON" }
msgNamespace The custom message channel namespace to use for sending messages to the receiver application. org.electroteque.cast.player
resolveRedirect For live origin / edge HLS streams with redirections. Use the origin url and enable redirection url resolving. Chromecast cannot follow redirects for HLS.

Supported Formats

  • Mp4,webm
  • Mpeg Dash with Widevine DRM encryption.
  • Smooth Streaming with Playready.
  • Apple Http Live Streaming with AES encryption.
  • AAC, AC-3 audio tracks.

Custom Receiver Options

Property Description Default
msgNamespace The custom message channel namespace for receiving messages from the sender. org.electroteque.cast.player
fragmentedMp4Hls HLS only. Enable for Fragmented MP4 HLS streams. false
hlsAudio HLS only. The audio format for HLS audio formats. ts, aac,fmp4, ac3. ts
licenseUrl Widevine DRM license server url.
useCredentials Enable xhr credentials. false
mediaUrlResolver Turn on a media url resolver. Available is an option to turn on redirect resolving support for live edge streams when used in conjunction with resolveRedirect on the sender.
mediaUrlResolver: (resolver) => { return chromecast.CastReceiverUtils.getRedirectUrl(resolver); }

Chromecast Playlist Custom Data

Property Description Default
title The video title.
contentId Identifies the content.
customData Custom data to send to the custom receiver application.
images An image to send to the custom receiver application. Required in the format of images:
[{'url': "//static.electroteque.org/images/stills/bbb_still.jpg" }]
live If the video is a live stream.

Appending to the Queue while casting

An api method is available to add new sources to the queue and videojs playlist. It will immediately switch to that item.

player.src({
    castInfo: {
        title: "Elephants Dream",
        subtitle: "Subtitle",
        images:  [{'url': "//static.electroteque.org/images/stills/ed_still.jpg" }]
    },
    sources: [
        {type: "video/webm", src: "//videos.electroteque.org/bitrate/elephants_dream_600k.webm"},
        {type: "video/mp4", src: "//videos.electroteque.org/bitrate/elephants_dream_600k.mp4"},
        {type: "video/ogg", src: "//videos.electroteque.org/bitrate/elephants_dream_600k.ogv"}
    ]
});

Javascript API

Javascript events api

var player = videojs("player");
player.senderMessage({ type: "message", value: 1 }));

player.on("castavailable", function() {
    console.log("Chromecast Available");
});
player.on("castmessage", function(e, message) {
    console.log("CASTMESSAGE ", message);
});
player.on("airplay-available", function() {
    console.log("Airplay Available");
});
player.on("start-airplay", function() {
    console.log("start airplay");
});
player.on("stop-airplay", function() {
    console.log("stop airplay");
});
method Description
requestSession Manually request a Chromecast session.

Javascript API Method

Manually request a Chromecast session.

var api = videojs("player");
api.requestSession();

Subtitle Setup

Configure subtitles as normal and they should display in any of the receivers.

NOTE: CORS headers are required for VTT files to load correctly. See below for CORS setup details.

CORS headers are required for both the video and the VTT files because it seems to be activated on the video rather than just the text tracks in the Google supplied receiver applications.

See https://flowplayer.org/docs/subtitles.html for more details.

The currently loaded subtitles will become active in the receiver and the subtitle menu can control switching languages in the receiver.

When stopping a cast the currently loaded subtitles will become active again in the player.

{
  "textTracks": [
    {
      "default": 1,
      "kind": "subtitles",
      "srclang": "en",
      "label": "English",
      "src": "/standalone/basics/subtitles-en.vtt"
    },
    {
      "kind": "subtitles",
      "srclang": "de",
      "label": "Deutsch",
      "src": "/standalone/basics/subtitles-de.vtt"
    }
  ],
  "sources": [
    {
      "type": "video/webm",
      "src": "//stream.flowplayer.org/functional.webm"
    },
    {
      "type": "video/mp4",
      "src": "//stream.flowplayer.org/functional.mp4"
    }
  ]
}

Chromecast Dongle Network Setup

https://support.google.com/chromecast/answer/2998456?hl=en-AU

For the first time for everyone the Chromecast dongle is required to be setup to join your wifi network.

The Google setup instructions explains how to setup depending which platform you are on. With the OSX and Windows tool the program will trigger the dongle to setup a temporary Wireless Access Point called "Chromecast".

It is a requirement that your network location is set to automatic for the duration of the setup or else it will fail to connect if you have manual ip addresses enabled.<

The program will ask to verify a code, then you enter the wifi passport and then it is connected.

For testing you are not required to have a custom receiver application if only testing with mp4 files.

Custom Receiver Application

Provided is a custom CAF receiver application which supports HLS / Dash DRM Streaming, text and audio track switching and VAST ads.

const receiver = new chromecast.CastReceiverNative({
  //msgNamespace: "org.electroteque.cast.player",
  //fragmentedMp4Hls: false,
  licenseUrl: "//widevine-dash.ezdrm.com/proxy?pX=39010C&uid=demo&pass=demo",
  //licenseCustomData: "",
  //licenseUrl: "widevinelicencerserver",
  //contentProtection: "widevine",
  //useCredentials: false,
  //licenseRequestHandler: null,
  //manifestRequestHandler: null,
  //segmentRequestHandler: null,
  //mediaUrlResolver: (resolver) => {
  //  return resolver.media.contentId;
  //},
  debug: false,
});

receiver
  .on("message", (event, message) => {
    console.log("on message", message);
  })
  .on("audiotrackschanged", (event, track) => {
    console.log("audio track changed", track);
  })
  .on("texttrackschange", (event, track) => {
    console.log("text track changed", track);
  })
  .on("loadsuccess", () => {
    console.log("Chromecast Receiver Ready");
  })
  .on("loadfailed", (event, error) => {
    console.log("Chromecast Receiver Load Failed ", error);
  })
  .on("receiverready", (event, arg) => {
    console.log("Receiver Ready ", arg);
  })
  .on("ready", (event, arg) => {
    console.log("Media Loaded ", arg);
  })
  .on("capabilities", (event, capabilities) => {
    console.log("Device capabilities", capabilities);
  })
  .on("licencedata", (event, customData) => {
    console.log("Received Licence Data From Sender ", customData);
  })
  .on("loadedmetadata", (event) => {
    console.log("Received Metadata ", event);
  })
  .on("playing", (event) => {
    console.log("Media Playing", event);
  })
  .on("pause", (event) => {
    console.log("Media Paused", event);
  })
  .on("bitratechanged", (event) => {
    console.log("Bitrate Changed ", event);
  })
  .on("buffering", (event) => {
    console.log("Media Buffering ", event);
  })
  .on("finish", (event) => {
    console.log("Media Finished ", event);
  })
  .on("breakstarted", (event) => {
    console.log("Ad Break Started ", event);
  })
  .on("breakended", (event) => {
    console.log("Ad Break Ended ", event);
  });

Custom events can be handled to manage displaying custom information sent from the sender.

Events

event Description
castMedia When a new media is loaded from the sender. In the media argument provides the custom properties sent from the sender. castMedia: function(e, api, media) {
senderdisconnect When a sender has connected.
senderdisconnect When a sender has disconnnected.
caststandby When the chromecast device has gone into standby.
castvisibility When the chromecast device has changed visibility.
castmessage When the sender has sent a custom chromecast message to handle.
appstop When the custom receiver application is stopping.

Styled Receiver Application

A styled receiver requires a onfigured css url for custom styling the Google supplied receiver application.

.background {
    background: center no-repeat url(images/background.png);
}

.logo {
    background-image: url(images/logo.png);
}

.progressBar {
    background-color: rgb(238, 255, 65);
}

.splash {
    background-image: url(images/splash.png);
}

.watermark {
    background-image: url(images/watermark.png);
    background-size: 57px 57px;
}

CORS Requirements for HLS, Mpeg-Dash and Smoothstreaming Formats

For HLS, Mpeg-Dash and Smoothstreaming streaming formats Cross Origin Resource Sharing rules are required to be enabled. This is required for byte downloading of fragments over Ajax.

The header of the cors request must expose a Access-Control-Allow-Origin header with either a multiple list of domains including ports if using ports or an asterix wildcard to allow all domains. A Access-Control-Allow-Methods can be exposed to control what request methods are allowed. For authenticated logins with cookies the Access-Control-Allow-Credentials header must be enabled and the feature will pass cookie sessions and other cookies along with the request.

An example request header can look like the following:

Access-Control-Allow-Origin: http://localhost:8000
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Content-Type, Accept
Access-Control-Allow-Credentials: true

Testing CORS Server Requests

CORS server requests can be initiated with the following curl command:

curl -I -H "Origin: http://localhost:8000" http://path/to/server

Enabling CORS on S3

Follow the guide here to enable CORS rules on the bucket. Cloudfront does not function just yet because Chrome will send an OPTIONS request method which it does not allow.

The CORS header should look like the following:

Access-Control-Allow-Origin: http://localhost:8000
Access-Control-Allow-Methods: GET, HEAD
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method

Custom Receiver API Documentation

To build your own receiver application more details can be found in the Chromecast API Google docs. https://developers.google.com/cast/docs/custom_receiver