Search code examples
androidchromecastmultilingualplayready

Chromecast Multi-language playready not detecting languages


I'm trying to play multi-language audio tracks on chromecast. It plays the video/audio files but it does not switch from English to Spanish. I can switch using the same file in a silverlight player. I've set my chromecast player language and my android phone language to be spanish. In the Google Cast SDK Developer console, I added spanish as an alternate track.

I've added my custom player using the code specified in the google guides, however the code in the guides does not appear to work from a straight copy and paste. Can someone direct me as to why protocol.getStreamCount() is 0? Is the timing of the call correct? Here's the entire player that I'm using, pay particular attention to window.changeLanguage = function()... and the changeLanguage call. Any help is extremely appreciated!

<html>
<head>
  <title>Test Player</title>
  <script type="text/javascript" src="//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
  <script type="text/javascript" src="//www.gstatic.com/cast/sdk/libs/mediaplayer/1.0.0/media_player.js"></script>
  <link rel="stylesheet" type="text/css" href="chromecast.css" />
</head>
<body>
<video id='vid' />


<script type="text/javascript">
if (window.location.href.indexOf('Debug=true') != -1) {
  cast.receiver.logger.setLevelValue(cast.receiver.LoggerLevel.DEBUG);
  cast.player.api.setLoggerLevel(cast.player.api.LoggerLevel.DEBUG);
}

var mediaElement = document.getElementById('vid');
var protocol = null;
// Create the media manager. This will handle all media messages by default.
window.mediaManager = new cast.receiver.MediaManager(mediaElement);
window.defaultOnLoad = mediaManager.onLoad;
mediaManager.onLoad = function (event) {
  if (window.player !== null) {
    player.unload();    // Must unload before starting again.
    window.player = null;
  }
  if (event.data['media'] && event.data['media']['contentId']) {
    console.log('Starting media application');
    var url = event.data['media']['contentId'];
    window.host = new cast.player.api.Host({'mediaElement':mediaElement, 'url':url});
    var ext = url.substring(url.lastIndexOf('.'), url.length);
    var initStart = event.data['media']['currentTime'] || 0;
    var autoplay = event.data['autoplay'] || true;
    mediaElement.autoplay = autoplay;  // Make sure autoplay get's set

    if (url.lastIndexOf('.m3u8') >= 0) 
    {
      // HTTP Live Streaming
      protocol = cast.player.api.CreateHlsStreamingProtocol(host);
    } 
    else if (url.lastIndexOf('.mpd') >= 0) 
    {
      // MPEG-DASH
      protocol = cast.player.api.CreateDashStreamingProtocol(host);
    } 
    else if (url.indexOf('.ism/') >= 0) 
    {
      // Smooth Streaming
      protocol = cast.player.api.CreateSmoothStreamingProtocol(host);
    }
    // How to override a method in Host. I know that it's safe to just provide this
    // method.
    host.onError = function(errorCode) {
      console.log("Fatal Error - " + errorCode);
      if (window.player) {
        window.player.unload();
        window.player = null;
      }
    };
    console.log("we have protocol " + ext);
    if (protocol !== null) {
      console.log("Starting Media Player Library");
      window.player = new cast.player.api.Player(host);
      window.player.load(protocol, initStart);
      changeLanguage();
    }
    else {
      window.defaultOnLoad(event);    // do the default process
    }
  }
}

window.changeLanguage = function() {
 var currentLanguage = null;
 var streamCount = protocol.getStreamCount();
 console.log("streamCount: " + streamCount);
 var streamInfo;
 for (var i = 0; i < streamCount; i++) {
   console.log("isStreamEnabled " + i + "? " + protocol.isStreamEnabled(i));
   if (protocol.isStreamEnabled(i)) {
     streamInfo = protocol.getStreamInfo(i);
     console.log("streamInfo isAudio? " + streamInfo.mimeType.indexOf('audio'));
     if (streamInfo.mimeType.indexOf('audio') === 0) {
       if (streamInfo.language) {
     console.log("streamInfo.language: " + streamInfo.language);
     currentLanguage = i;
     break;
       }
     }
   }
 }

 if (currentLanguage === null) {
   currentLanguage = 0;
 }

 i = currentLanguage + 1;
 console.log("i: " + i);
 console.log("currentLanguage: " + currentLanguage);
 while (i !== currentLanguage) {
   if (i === streamCount) {
     console.log("resetting i to 0");
     i = 0;
   }

   streamInfo = protocol.getStreamInfo(i);
   if (streamInfo.mimeType.indexOf('audio') === 0) {
     protocol.enableStream(i, true);
     protocol.enableStream(currentLanguage, false);

     console.log("Enabling: " + i);
     console.log("Disabling: " + currentLanguage);
     break;
   }

   i++;
 }

 if (i !== currentLanguage) {
   console.log("reloading window player" + window.player);
   window.player.reload();
 }
};

window.player = null;
console.log('Application is ready, starting system');
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
castReceiverManager.start();
</script>
</body>
</html>

Chromecast Console:

Application is ready, starting system

Starting media application

we have protocol .ism/manifest

Starting Media Player Library

streamCount: 0

i: 1

currentLanguage: 0

EDIT

I went into console and post loading called the following command:

this.protocol.getStreamCount()

2

So this is clearly a timing issue. I need to call changeLanguage once the stream has fully loaded. I'm investigating when the appropriate time to call it is. I'd appreciate any help but I'll try to google this answer now that I'm positive it's a timing issue.


Solution

  • Answer is:

    host.onManifestReady = function() {
      changeLanguage();
    };
    

    This will provide the correct timing for when to pull the alternate audio tracks.