Как добавить стандартные элементы управления мультимедиа в приложение Google Cast?

Я разрабатываю пользовательское приложение приемника Google Cast с использованием WebTorrent (https://webtorrent.io, https://github.com/feross/webtorrent) и приложение отправителя Google Cast с использованием JavaScript (Chrome) SDK.

Идея моего приложения заключается в отправке идентификатора торрента (URI магнита, например magnet:?xt=urn:btih:6a9759bffd5c0af65319979fb7832189f4f3c35d или URL HTTP / HTTPS в файл * .torrent, например https://webtorrent.io/torrents/sintel.torrent) от отправителя Google Cast к приемнику Google Cast и использование WebTorrent в приемнике Google Cast для отображения мультимедиа (видео или аудио) с торрента.

Обратите внимание, что идентификатор торрента не является прямым URL-адресом медиафайла.

Теперь я использую пространство имен Google Cast и messageBus для отправки и получения идентификатора торрента.

WebTorrent API предоставляет 2 способа отображения мультимедиа:

Вот код моего приемника:

<html>
  <head>
    <script src="https://www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
    <script src="https://cdn.jsdelivr.net/webtorrent/latest/webtorrent.min.js"></script>
  </head>
  <body>
    <video autoplay id='media' />
    <script>
      window.mediaElement = document.getElementById('media');
      window.mediaManager = new cast.receiver.MediaManager(window.mediaElement);
      window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
      window.messageBus = window.castReceiverManager.getCastMessageBus('urn:x-cast:com.google.cast.sample.helloworld');
      window.messageBus.onMessage = function(event) {
        displayVideo(event.data);
        // Inform all senders on the CastMessageBus of the incoming message event
        // sender message listener will be invoked
        window.messageBus.send(event.senderId, event.data);
      };
      function displayVideo(torrentId) {
        var client = new WebTorrent();
        client.add(torrentId, function (torrent) {
          var file = torrent.files[0];
          file.renderTo('video');
        });
      }
      window.castReceiverManager.start();
    </script>
  </body>
</html>

Вот код моего отправителя:

<!--
Copyright (C) 2014 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<style type="text/css">
html, body, #wrapper {
   height:100%;
   width: 100%;
   margin: 0;
   padding: 0;
   border: 0;
}
#wrapper td {
   vertical-align: middle;
   text-align: center;
}
input {
  font-family: "Arial", Arial, sans-serif;
  font-size: 40px;
  font-weight: bold;
}
.border {
    border: 2px solid #cccccc;
    border-radius: 5px;
}
.border:focus { 
    outline: none;
    border-color: #8ecaed;
    box-shadow: 0 0 5px #8ecaed;
}
</style>
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"></script>
<script type="text/javascript">
var applicationID = 'F5304A3D';
var namespace = 'urn:x-cast:com.google.cast.sample.helloworld';
var session = null;

/**
 * Call initialization for Cast
 */
if (!chrome.cast || !chrome.cast.isAvailable) {
  setTimeout(initializeCastApi, 1000);
}

/**
 * initialization
 */
function initializeCastApi() {
  var sessionRequest = new chrome.cast.SessionRequest(applicationID);
  var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
    sessionListener,
    receiverListener);

  chrome.cast.initialize(apiConfig, onInitSuccess, onError);
};

/**
 * initialization success callback
 */
function onInitSuccess() {
  appendMessage("onInitSuccess");
}

/**
 * initialization error callback
 */
function onError(message) {
  appendMessage("onError: "+JSON.stringify(message));
}

/**
 * generic success callback
 */
function onSuccess(message) {
  appendMessage("onSuccess: "+message);
}

/**
 * callback on success for stopping app
 */
function onStopAppSuccess() {
  appendMessage('onStopAppSuccess');
}

/**
 * session listener during initialization
 */
function sessionListener(e) {
  appendMessage('New session ID:' + e.sessionId);
  session = e;
  session.addUpdateListener(sessionUpdateListener);
  session.addMessageListener(namespace, receiverMessage);
}

/**
 * listener for session updates
 */
function sessionUpdateListener(isAlive) {
  var message = isAlive ? 'Session Updated' : 'Session Removed';
  message += ': ' + session.sessionId;
  appendMessage(message);
  if (!isAlive) {
    session = null;
  }
};

/**
 * utility function to log messages from the receiver
 * @param {string} namespace The namespace of the message
 * @param {string} message A message string
 */
function receiverMessage(namespace, message) {
  appendMessage("receiverMessage: "+namespace+", "+message);
};

/**
 * receiver listener during initialization
 */
function receiverListener(e) {
  if( e === 'available' ) {
    appendMessage("receiver found");
  }
  else {
    appendMessage("receiver list empty");
  }
}

/**
 * stop app/session
 */
function stopApp() {
  session.stop(onStopAppSuccess, onError);
}

/**
 * send a message to the receiver using the custom namespace
 * receiver CastMessageBus message handler will be invoked
 * @param {string} message A message string
 */
function sendMessage(message) {
  if (session!=null) {
    session.sendMessage(namespace, message, onSuccess.bind(this, "Message sent: " + message), onError);
  }
  else {
    chrome.cast.requestSession(function(e) {
        session = e;
        session.sendMessage(namespace, message, onSuccess.bind(this, "Message sent: " + message), onError);
      }, onError);
  }
}

/**
 * append message to debug message window
 * @param {string} message A message string
 */
function appendMessage(message) {
  console.log(message);
  var dw = document.getElementById("debugmessage");
  dw.innerHTML += '\n' + JSON.stringify(message);
};

/**
 * utility function to handle text typed in by user in the input field
 */
function update() {
  sendMessage(document.getElementById("input").value);
}

/**
 * handler for the transcribed text from the speech input
 * @param {string} words A transcibed speech string
 */
function transcribe(words) {
  sendMessage(words);
}
</script>
</head>
<body>
  <table id="wrapper">
    <tr>
        <td>
            <form method="get" action="JavaScript:update();">
                <input id="input" class="border" type="text" size="30" onwebkitspeechchange="transcribe(this.value)" x-webkit-speech/>
            </form>
        </td>
    </tr>
  </table>

  <!-- Debbugging output -->
  <div style="margin:10px; visibility:hidden;">
    <textarea rows="20" cols="70" id="debugmessage">
    </textarea>
  </div>

<script type="text/javascript">
  document.getElementById("input").focus();
</script>
</body>
</html>

Проблема: получатель обрабатывает идентификатор торрента от отправителя, и видео воспроизводится должным образом. Но официальное приложение Google Cast или официальное расширение Google Cast для Chrome не показывает стандартные элементы управления мультимедиа для воспроизведения видео, паузы, остановки, поиска и т. Д.

Вот что у меня есть (это скриншот стандартного встроенного модального диалога для Google Cast в последней версии Google Chrome):

«Скриншот

Вот чего я хочу добиться (это снимок экрана стандартного встроенного модального диалога для Google Cast в последней версии Google Chrome):

«Скриншот

Добавление

window.mediaElement = document.getElementById('media');
window.mediaManager = new cast.receiver.MediaManager(window.mediaElement);

за

<video autoplay id='media' />

элемент не помогает.

Должен ли я добавить что-то отправителю и / или получателю, чтобы добавить стандартные средства управления мультимедиа для <video autoplay id='media' /> для всех отправителей?

Может быть, есть другой способ отправлять и получать торрент-идентификатор без использования пространства имен Google Cast и messageBus?

UPD

Похоже, я нашел корень своей проблемы ...

Как включить средства управления мультимедиа по умолчанию для существующего воспроизводимого видео в ресивере?

Например, в приложении-приемнике уже есть воспроизведение видео:

<video autoplay id='media'
src='https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'
/>

Как включить элементы управления мультимедиа по умолчанию - рабочие кнопки «Воспроизвести / Пауза», рабочий индикатор выполнения (на всех отправителях, таких как официальное расширение Google Cast для Chrome) для этого воспроизводимого видео?

Похоже, добавление следующего кода не помогает:

window.mediaElement = document.getElementById('media');
window.mediaManager = new cast.receiver.MediaManager(window.mediaElement);
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
window.castReceiverManager.start();

Вот полный исходный код приемника:

<html>
<head>
<script src="https://www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"></script>
</head>
<body>
<video autoplay id='media'
src='https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'
/>
<script>
window.mediaElement = document.getElementById('media');
window.mediaManager = new cast.receiver.MediaManager(window.mediaElement);
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
window.castReceiverManager.start();
</script>
</body>
</html>

UPD2:

Похоже, можно использовать любую текстовую строку (идентификатор торрента в моем случае) вместо URL-адреса мультимедиа в chrome.cast.media.MediaInfo и использовать пространство имен мультимедиа вместо использования настраиваемого пространства имен и настраиваемой шины сообщений (то есть без использования https://developers.google.com/cast/docs/reference/receiver/cast.receiver.CastReceiverManager#getCastMessageBus и https://developers.google.com/cast/docs/reference/receiver/cast.receiver.CastMessageBus и https://developers.google.com/cast/docs/reference/chrome/chrome.cast.Session.#sendMessage):

function cast() {
  url = 'magnet:?xt=urn:btih:6a9759bffd5c0af65319979fb7832189f4f3c35d';
  chrome.cast.requestSession(function(session) {
    var mediaInfo = new chrome.cast.media.MediaInfo(url);
    //mediaInfo.contentType = 'video/mp4';
    //mediaInfo.contentType = 'audio/mpeg';
    //mediaInfo.contentType = 'image/jpeg';
    var request = new chrome.cast.media.LoadRequest(mediaInfo);
    request.autoplay = true;
    session.loadMedia(request, function() {}, onError);
  }, onError);
}

Но как это сделать на ресивере в таком случае?


person Alexey Rodionov    schedule 26.04.2016    source источник


Ответы (2)


На самом деле существуют правила Google Cast UX, в которых говорится, что приложение-отправитель должно предоставлять кнопку трансляции верхнего уровня. Есть три способа поддержки кнопки трансляции, которые подробно обсуждались в разработке приложений для отправки сообщений для Android

  • Использование провайдера MediaRouter ActionBar: android.support.v7.app.MediaRouteActionProvider
  • Использование кнопки MediaRouter Cast: android.support.v7.app.MediaRouteButton
  • Разработка пользовательского интерфейса с помощью MediaRouter API и MediaRouter.Callback

Чтобы отображать стандартные элементы управления мультимедиа после воспроизведения мультимедиа, приложение-отправитель может управлять воспроизведением мультимедиа с помощью экземпляра RemoteMediaPlayer. Шаги и примеры можно найти в документации.

Полный список всех классов, методов и событий в SDK Google Cast для Android см. В Справочник по API Google Cast для Android.

person Teyam    schedule 27.04.2016
comment
Спасибо за ответ, но этот вопрос о разработке отправителя JavaScript (Chrome) Google Cast (developers.google .com / cast / docs / chrome_sender), а не отправитель Android. - person Alexey Rodionov; 27.04.2016
comment
Приносим извинения за отправку документов, относящихся к Android, а не к JavasScript. В любом случае, спасибо за редактирование вашего сообщения и за добавление тегов JavaScript. :) - person Teyam; 27.04.2016

Я понимаю, что прошло уже 3 года, но что меня бросает в глаза, так это то, что вам не хватает атрибута "control" в вашем теге видео! Без атрибута проигрыватель отобразит видео, но не предоставит пользовательского интерфейса для управления воспроизведением ....

Синтаксис такой же, как и для автовоспроизведения: атрибут controls является автономным и не имеет значения. Это все или ничего - стандартный набор элементов управления со стилем по умолчанию или вообще без него ... если вы создавали для браузера, вы можете опустить атрибут и создать свои собственные элементы управления, соответствующие внешнему виду страница. Но судя по скриншотам, которыми вы поделились, в этом нет необходимости (и это может не работать в среде приемника Chromecast)

Правильный html ниже, и это все, что вам нужно :)

https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 '/>

Пожалуйста, дайте нам знать, если и как вы закончили решение своей проблемы (и отправьте мне DM ... Недавно я начал интегрировать webtorrent в платформу потокового видео, которую я создаю, и пока все хорошо, но документация довольно плохая и У меня есть несколько вопросов. Спасибо!)

person Community    schedule 23.12.2019