Добавьте основные функции в свой собственный веб-приемник

На этой странице содержатся фрагменты кода и описания функций, доступных для приложения Custom Web Receiver.

  1. Элемент cast-media-player , представляющий встроенный пользовательский интерфейс проигрывателя, предоставляемый Web Receiver.
  2. Пользовательский стиль в стиле CSS для элемента cast-media-player позволяющий стилизовать различные элементы пользовательского интерфейса, такие как background-image , splash-image и font-family .
  3. Элемент скрипта для загрузки фреймворка Web Receiver.
  4. Код JavaScript для перехвата сообщений и обработки событий.
  5. Очередь на автовоспроизведение.
  6. Параметры настройки воспроизведения.
  7. Параметры настройки контекста веб-приемника.
  8. Параметры для настройки команд, поддерживаемых приложением Web Receiver.
  9. Вызов JavaScript для запуска приложения Web Receiver.

Конфигурация и параметры приложения

Настройте приложение

CastReceiverContext — это внешний класс, доступный разработчику, который управляет загрузкой базовых библиотек и обрабатывает инициализацию Web Receiver SDK. SDK предоставляет API, которые позволяют разработчикам приложений настраивать SDK через CastReceiverOptions . Эти конфигурации оцениваются один раз при запуске приложения и передаются в SDK при установке необязательного параметра в вызове start .

В примере ниже показано, как переопределить поведение по умолчанию для определения того, активно ли соединение отправителя. Когда Web Receiver не может связаться с отправителем в течение maxInactivity секунд, отправляется событие SENDER_DISCONNECTED . Конфигурация ниже переопределяет это время ожидания. Это может быть полезно при отладке проблем, поскольку не позволяет приложению Web Receiver закрыть сеанс Chrome Remote Debugger, когда нет ни одного подключенного отправителя в состоянии IDLE .

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);

Настройте плеер

При загрузке контента Web Receiver SDK предоставляет способ настройки переменных воспроизведения, таких как информация DRM , конфигурации повторных попыток и обработчики запросов, с помощью cast.framework.PlaybackConfig . Эта информация обрабатывается PlayerManager и оценивается во время создания проигрывателей. Проигрыватели создаются каждый раз, когда новая загрузка передается в Web Receiver SDK. Изменения PlaybackConfig после создания проигрывателя оцениваются при следующей загрузке контента. SDK предоставляет следующие методы для изменения PlaybackConfig .

  • CastReceiverOptions.playbackConfig для переопределения параметров конфигурации по умолчанию при инициализации CastReceiverContext .
  • PlayerManager.getPlaybackConfig() для получения текущей конфигурации.
  • PlayerManager.setPlaybackConfig() для переопределения текущей конфигурации. Эта настройка применяется ко всем последующим загрузкам или до тех пор, пока она не будет переопределена снова.
  • PlayerManager.setMediaPlaybackInfoHandler() для применения дополнительных конфигураций только для загружаемого элемента мультимедиа поверх текущих конфигураций. Обработчик вызывается непосредственно перед созданием проигрывателя. Изменения, внесенные здесь, не являются постоянными и не включаются в запросы к getPlaybackConfig() . При загрузке следующего элемента мультимедиа этот обработчик вызывается снова.

В примере ниже показано, как задать PlaybackConfig при инициализации CastReceiverContext . Конфигурация переопределяет исходящие запросы на получение манифестов. Обработчик указывает, что запросы CORS Access-Control должны выполняться с использованием учетных данных, таких как файлы cookie или заголовки авторизации.

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

В примере ниже показано, как переопределить PlaybackConfig с помощью геттера и сеттера, предоставленных в PlayerManager . Настройка настраивает проигрыватель на возобновление воспроизведения контента после загрузки 1 сегмента.

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

В примере ниже показано, как переопределить PlaybackConfig для определенного запроса загрузки с помощью обработчика информации о воспроизведении мультимедиа. Обработчик вызывает реализованный приложением метод getLicenseUrlForMedia для получения licenseUrl из contentId текущего элемента.

playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
  const mediaInformation = loadRequestData.media;
  playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);

  return playbackConfig;
});

Прослушиватель событий

Web Receiver SDK позволяет вашему приложению Web Receiver обрабатывать события проигрывателя. Слушатель событий принимает параметр cast.framework.events.EventType (или массив этих параметров), который определяет событие(я), которое должно активировать слушателя. Предварительно настроенные массивы cast.framework.events.EventType , которые полезны для отладки, можно найти в cast.framework.events.category . Параметр event предоставляет дополнительную информацию о событии.

Например, если вы хотите узнать, когда транслируется изменение mediaStatus , вы можете использовать следующую логику для обработки события:

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

Перехват сообщений

Web Receiver SDK позволяет вашему приложению Web Receiver перехватывать сообщения и выполнять пользовательский код для этих сообщений. Перехватчик сообщений принимает параметр cast.framework.messages.MessageType , который указывает, какой тип сообщения должен быть перехвачен.

Перехватчик должен вернуть измененный запрос или Promise, который разрешается с измененным значением запроса. Возврат null предотвратит вызов обработчика сообщений по умолчанию. Подробнее см. Загрузка медиа .

Например, если вы хотите изменить данные запроса на загрузку, вы можете использовать следующую логику для их перехвата и изменения:

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

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

Обработка ошибок

При возникновении ошибок в перехватчике сообщений ваше приложение Web Receiver должно возвращать соответствующие cast.framework.messages.ErrorType и cast.framework.messages.ErrorReason .

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

Перехват сообщений против прослушивателя событий

Некоторые ключевые различия между перехватом сообщений и прослушиванием событий заключаются в следующем:

  • Прослушиватель событий не позволяет изменять данные запроса.
  • Прослушиватель событий лучше всего использовать для запуска аналитики или пользовательской функции.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • Перехват сообщений позволяет прослушивать сообщение, перехватывать его и изменять сами данные запроса.
  • Перехват сообщений лучше всего использовать для обработки пользовательской логики в отношении запрашиваемых данных.

Загрузка медиа

MediaInformation предоставляет множество свойств для загрузки мультимедиа в сообщении cast.framework.messages.MessageType.LOAD , включая entity , contentUrl и contentId .

  • entity — это предлагаемое свойство для использования в вашей реализации для приложений отправителя и получателя. Свойство — это URL-адрес глубокой ссылки, который может быть либо списком воспроизведения, либо медиа-контентом. Ваше приложение должно проанализировать этот URL-адрес и заполнить по крайней мере одно из двух других полей.
  • contentUrl соответствует воспроизводимому URL, который игрок будет использовать для загрузки контента. Например, этот URL может указывать на манифест DASH.
  • contentId может быть либо URL-адресом воспроизводимого контента (аналогичным свойству contentUrl ), либо уникальным идентификатором загружаемого контента или плейлиста. При использовании этого свойства в качестве идентификатора ваше приложение должно заполнить URL-адрес воспроизводимого контента в contentUrl .

Предлагается использовать entity для хранения реального ID или ключевых параметров и contentUrl для URL медиа. Пример этого показан в следующем фрагменте, где entity присутствует в запросе LOAD и извлекается воспроизводимый contentUrl :

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

Возможности устройства

Метод getDeviceCapabilities предоставляет информацию об устройстве на подключенном устройстве Cast и видео- или аудиоустройстве, подключенном к нему. Метод getDeviceCapabilities предоставляет информацию о поддержке для Google Assistant, Bluetooth и подключенных дисплеев и аудиоустройств.

Этот метод возвращает объект, который можно запросить, передав один из указанных перечислений, чтобы получить возможности устройства для этого перечисления. Перечисления определены в cast.framework.system.DeviceCapabilities .

В этом примере проверяется, может ли устройство Web Receiver воспроизводить HDR и DolbyVision (DV) с ключами IS_HDR_SUPPORTED и IS_DV_SUPPORTED соответственно.

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

Обработка взаимодействия с пользователем

Пользователь может взаимодействовать с вашим приложением Web Receiver через приложения-отправители (веб, Android и iOS), голосовые команды на устройствах с поддержкой Assistant, сенсорное управление на интеллектуальных дисплеях и пульты дистанционного управления на устройствах Android TV. Cast SDK предоставляет различные API, позволяющие приложению Web Receiver обрабатывать эти взаимодействия, обновлять пользовательский интерфейс приложения через состояния действий пользователя и, при необходимости, отправлять изменения для обновления любых внутренних служб.

Поддерживаемые медиа-команды

Состояния элементов управления пользовательского интерфейса управляются MediaStatus.supportedMediaCommands для расширенных контроллеров отправителя iOS и Android, приложений приемника и пульта дистанционного управления, работающих на сенсорных устройствах, и приложений приемника на устройствах Android TV. Когда в свойстве включена определенная битовая Command , включаются кнопки, связанные с этим действием. Если значение не задано, кнопка отключена. Эти значения можно изменить в веб-приемнике следующим образом:

  1. Использование PlayerManager.setSupportedMediaCommands для установки определенных Commands
  2. Добавление новой команды с помощью addSupportedMediaCommands
  3. Удаление существующей команды с помощью removeSupportedMediaCommands .
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

Когда получатель подготовит обновленный MediaStatus , он включит изменения в свойство supportedMediaCommands . Когда статус будет передан, подключенные приложения отправителя обновят кнопки в своем пользовательском интерфейсе соответствующим образом.

Дополнительную информацию о поддерживаемых командах мультимедиа и сенсорных устройствах см. в руководстве « Accessing UI controls .

Управление состояниями действий пользователя

Когда пользователи взаимодействуют с пользовательским интерфейсом или отправляют голосовые команды, они могут управлять воспроизведением контента и свойствами, связанными с воспроизводимым элементом. Запросы, которые управляют воспроизведением, обрабатываются автоматически SDK. Запросы, которые изменяют свойства текущего воспроизводимого элемента, такие как команда LIKE , требуют, чтобы приложение-получатель обрабатывало их. SDK предоставляет ряд API для обработки этих типов запросов. Для поддержки этих запросов необходимо выполнить следующее:

  • При загрузке элемента мультимедиа задайте MediaInformation userActionStates в соответствии с предпочтениями пользователя.
  • Перехватывать сообщения USER_ACTION и определять запрошенное действие.
  • Обновите MediaInformation UserActionState , чтобы обновить пользовательский интерфейс.

Следующий фрагмент перехватывает запрос LOAD и заполняет MediaInformation LoadRequestData . В этом случае пользователю нравится загружаемый контент.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      const userActionLike = new cast.framework.messages.UserActionState(
          cast.framework.messages.UserAction.LIKE);
      loadRequestData.media.userActionStates = [userActionLike];

      return loadRequestData;
    });

Следующий фрагмент перехватывает сообщение USER_ACTION и обрабатывает вызов бэкэнда с запрошенным изменением. Затем он делает вызов для обновления UserActionState на приемнике.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

Следующий фрагмент имитирует вызов бэкэнд-службы. Функция проверяет UserActionRequestData , чтобы увидеть тип изменения, запрошенного пользователем, и делает сетевой вызов только в том случае, если действие поддерживается бэкэндом.

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

Следующий фрагмент берет UserActionRequestData и добавляет или удаляет UserActionState из MediaInformation . Обновление UserActionState MediaInformation изменяет состояние кнопки, связанной с запрошенным действием. Это изменение отражается в пользовательском интерфейсе управления интеллектуальным дисплеем, приложении дистанционного управления и пользовательском интерфейсе Android TV. Оно также транслируется через исходящие сообщения MediaStatus для обновления пользовательского интерфейса расширенного контроллера для отправителей iOS и Android.

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

Голосовые команды

Следующие команды мультимедиа в настоящее время поддерживаются в Web Receiver SDK для устройств с поддержкой Assistant. Реализации этих команд по умолчанию находятся в cast.framework.PlayerManager .

Команда Описание
Играть Воспроизвести или возобновить воспроизведение с приостановленного состояния.
Пауза Приостановить воспроизводимый контент.
Предыдущий Перейти к предыдущему элементу мультимедиа в очереди мультимедиа.
Следующий Перейти к следующему медиа-элементу в очереди медиа-данных.
Останавливаться Остановите воспроизводимое в данный момент медиа.
Повторить нет Отключить повторение элементов мультимедиа в очереди после завершения воспроизведения последнего элемента в очереди.
Повторить сингл Повторять текущий воспроизводимый медиафайл бесконечно.
Повторить все Повторить все элементы в очереди после воспроизведения последнего элемента в очереди.
Повторить все и перемешать После завершения воспроизведения последнего элемента в очереди перемешайте очередь и повторите воспроизведение всех элементов в очереди.
Перемешать Перемешивайте элементы мультимедиа в очереди мультимедиа.
Субтитры ВКЛ/ВЫКЛ Включить/выключить скрытые субтитры для ваших медиа. Включить/выключить также можно по языку.
Стремитесь к абсолютному времени Переход к указанному абсолютному времени.
Перейти ко времени относительно текущего времени Переход вперед или назад на указанный период времени относительно текущего времени воспроизведения.
Играть снова Перезапустите текущий воспроизводимый медиафайл или воспроизведите последний воспроизведенный медиафайл, если в данный момент ничего не воспроизводится.
Установить скорость воспроизведения Изменить скорость воспроизведения медиа. Это должно обрабатываться по умолчанию. Вы можете использовать перехватчик сообщений SET_PLAYBACK_RATE для переопределения входящих запросов скорости.

Поддерживаемые голосовые команды мультимедиа

Чтобы голосовая команда не запускала медиа-команду на устройстве с поддержкой Assistant, сначала необходимо задать поддерживаемые медиа-команды , которые вы планируете поддерживать. Затем необходимо принудительно применить эти команды, включив свойство CastReceiverOptions.enforceSupportedCommands . Пользовательский интерфейс на отправителях Cast SDK и сенсорных устройствах изменится, чтобы отразить эти конфигурации. Если флаг не включен, входящие голосовые команды будут выполняться.

Например, если вы разрешаете PAUSE из приложений отправителя и сенсорных устройств, вы также должны настроить приемник, чтобы отразить эти настройки. После настройки любые входящие голосовые команды будут сброшены, если они не включены в список поддерживаемых команд.

В примере ниже мы предоставляем CastReceiverOptions при запуске CastReceiverContext . Мы добавили поддержку команды PAUSE и заставили проигрыватель поддерживать только эту команду. Теперь, если голосовая команда запрашивает другую операцию, например SEEK , она будет отклонена. Пользователь будет уведомлен о том, что команда пока не поддерживается.

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

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

Вы можете применить отдельную логику для каждой команды, которую вы хотите ограничить. Снимите флаг enforceSupportedCommands , и для каждой команды, которую вы хотите ограничить, вы можете перехватывать входящее сообщение. Здесь мы перехватываем запрос, предоставленный SDK, чтобы команды SEEK , отправленные на устройства с поддержкой Assistant, не запускали поиск в вашем приложении Web Receiver.

Для медиа-команд, которые ваше приложение не поддерживает, возвращайте соответствующую причину ошибки, например NOT_SUPPORTED .

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

Фоновая информация от голосовой активности

Если платформа Cast воспроизводит звук вашего приложения в фоновом режиме из-за активности помощника, например, прослушивания речи пользователя или ответа, сообщение FocusState NOT_IN_FOCUS отправляется приложению Web Receiver при запуске активности. Другое сообщение с IN_FOCUS отправляется при завершении активности. В зависимости от вашего приложения и воспроизводимого мультимедиа вы можете захотеть приостановить мультимедиа, когда FocusState становится NOT_IN_FOCUS , перехватив тип сообщения FOCUS_STATE .

Например, пользователю удобно приостанавливать воспроизведение аудиокниги, если Помощник отвечает на запрос пользователя.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

Язык субтитров, определяемый голосом

Когда пользователь явно не указывает язык субтитров, то для субтитров используется тот же язык, на котором была произнесена команда. В таких сценариях параметр isSuggestedLanguage входящего сообщения указывает, был ли связанный язык предложен или явно запрошен пользователем.

Например, isSuggestedLanguage устанавливается в true для команды «OK Google, включи субтитры», поскольку язык был определен на основе языка, на котором была произнесена команда. Если язык запрошен явно, например, в «OK Google, включи английские субтитры», isSuggestedLanguage устанавливается в false .

Метаданные и озвучивание

Хотя голосовые команды обрабатываются Web Receiver по умолчанию, вам следует убедиться, что метаданные для вашего контента полны и точны. Это гарантирует, что голосовые команды будут правильно обработаны Assistant и что метаданные будут правильно отображаться в новых типах интерфейсов, таких как приложение Google Home и интеллектуальные дисплеи, такие как Google Home Hub.

Потоковая передача

Сохранение состояния сеанса является основой потоковой передачи, где пользователи могут перемещать существующие аудио- и видеопотоки между устройствами с помощью голосовых команд, приложения Google Home или интеллектуальных дисплеев. Медиа останавливается на одном устройстве (источнике) и продолжается на другом (адресате). Любое устройство Cast с последней версией прошивки может служить источником или адресатом потоковой передачи.

Поток событий для потоковой передачи следующий:

  1. На исходном устройстве:
    1. Медиафайлы останавливаются.
    2. Приложение Web Receiver получает команду на сохранение текущего состояния мультимедиа.
    3. Приложение Web Receiver закрыто.
  2. На целевом устройстве:
    1. Приложение Web Receiver загружено.
    2. Приложение Web Receiver получает команду на восстановление сохраненного состояния мультимедиа.
    3. Медиа возобновляет воспроизведение.

Элементы медиагосударства включают в себя:

  • Конкретная позиция или временная метка песни, видео или медиафайла.
  • Его место в более широкой очереди (например, в плейлисте или радиопередаче исполнителя).
  • Аутентифицированный пользователь.
  • Состояние воспроизведения (например, воспроизведение или пауза).

Включение потоковой передачи

Чтобы реализовать потоковую передачу для вашего веб-приемника:

  1. Обновите supportedMediaCommands с помощью команды STREAM_TRANSFER :
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. При желании переопределите перехватчики сообщений SESSION_STATE и RESUME_SESSION , как описано в разделе Сохранение состояния сеанса . Переопределяйте их только в том случае, если пользовательские данные необходимо сохранить как часть моментального снимка сеанса. В противном случае реализация по умолчанию для сохранения состояний сеанса будет поддерживать потоковую передачу.

Сохранение состояния сеанса

Web Receiver SDK предоставляет реализацию по умолчанию для приложений Web Receiver, позволяющую сохранять состояния сеанса путем создания снимка текущего состояния мультимедиа, преобразования состояния в запрос на загрузку и возобновления сеанса с запросом на загрузку.

Запрос на загрузку, сгенерированный Web Receiver, может быть переопределен в перехватчике сообщений SESSION_STATE если это необходимо. Если вы хотите добавить пользовательские данные в запрос на загрузку, мы предлагаем поместить их в loadRequestData.customData .

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

Пользовательские данные можно получить из loadRequestData.customData в перехватчике сообщений RESUME_SESSION .

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

Предварительная загрузка контента

Веб-приемник поддерживает предварительную загрузку элементов мультимедиа после текущего элемента воспроизведения в очереди.

Операция предварительной загрузки предварительно загружает несколько сегментов предстоящих элементов. Спецификация выполняется по значению preloadTime в объекте QueueItem (по умолчанию 20 секунд, если не указано). Время выражается в секундах относительно окончания текущего воспроизводимого элемента. Допустимы только положительные значения. Например, если значение равно 10 секундам, этот элемент будет предварительно загружен за 10 секунд до завершения предыдущего элемента. Если время предварительной загрузки больше, чем время, оставшееся на currentItem, предварительная загрузка произойдет как можно скорее. Таким образом, если указать очень большое значение preload на queueItem, можно добиться эффекта, когда всякий раз, когда мы воспроизводим текущий элемент, мы уже предварительно загружаем следующий элемент. Однако мы оставляем настройку и выбор этого разработчику, поскольку это значение может повлиять на пропускную способность и производительность потоковой передачи текущего воспроизводимого элемента.

Предварительная загрузка по умолчанию будет работать для потокового контента HLS, DASH и Smooth.

Обычные видео- и аудиофайлы MP4, такие как MP3, не будут предварительно загружены, поскольку устройства Cast поддерживают только один медиаэлемент и не могут использоваться для предварительной загрузки во время воспроизведения существующего элемента контента.

Пользовательские сообщения

Обмен сообщениями является ключевым методом взаимодействия для приложений Web Receiver.

Отправитель отправляет сообщения веб-приемнику, используя API отправителя для платформы, на которой работает отправитель (Android, iOS, Web). Объект события (являющийся проявлением сообщения), который передается прослушивателям событий, имеет элемент данных ( event.data ), где данные принимают свойства определенного типа события.

Приложение Web Receiver может выбрать прослушивание сообщений в указанном пространстве имен. В силу этого приложение Web Receiver поддерживает протокол этого пространства имен. Затем все подключенные отправители, желающие общаться в этом пространстве имен, должны использовать соответствующий протокол.

Все пространства имен определяются строкой и должны начинаться с " urn:x-cast: ", за которой следует любая строка. Например, " urn:x-cast: com.example.cast.mynamespace ".

Ниже приведен фрагмент кода для веб-приемника, который прослушивает пользовательские сообщения от подключенных отправителей:

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

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

Аналогично, приложения Web Receiver могут информировать отправителей о состоянии Web Receiver, отправляя сообщения подключенным отправителям. Приложение Web Receiver может отправлять сообщения, используя sendCustomMessage(namespace, senderId, message) в CastReceiverContext . Web Receiver может отправлять сообщения отдельному отправителю, либо в ответ на полученное сообщение, либо из-за изменения состояния приложения. Помимо обмена сообщениями точка-точка (с ограничением в 64 Кб), Web Receiver может также транслировать сообщения всем подключенным отправителям.

Трансляция для аудиоустройств

Подробную информацию о воспроизведении только звука см. в руководстве Google Cast для аудиоустройств .

Android-ТВ

В этом разделе обсуждается, как Google Web Receiver использует ваши входные данные для воспроизведения, а также совместимость с Android TV.

Интеграция вашего приложения с пультом дистанционного управления

Google Web Receiver, работающий на устройстве Android TV, преобразует входные данные с управляющих входов устройства (например, с пульта дистанционного управления) в сообщения воспроизведения мультимедиа, определенные для пространства имен urn:x-cast:com.google.cast.media , как описано в разделе Сообщения воспроизведения мультимедиа . Ваше приложение должно поддерживать эти сообщения для управления воспроизведением мультимедиа приложения, чтобы обеспечить базовое управление воспроизведением с управляющих входов Android TV.

Рекомендации по совместимости с Android TV

Вот несколько рекомендаций и распространенных ошибок, которых следует избегать, чтобы обеспечить совместимость вашего приложения с Android TV:

  • Имейте в виду, что строка user-agent содержит как "Android", так и "CrKey"; некоторые сайты могут перенаправлять на сайт, предназначенный только для мобильных устройств, поскольку они обнаруживают метку "Android". Не думайте, что "Android" в строке user-agent всегда указывает на мобильного пользователя.
  • Стек медиа Android может использовать прозрачный GZIP для извлечения данных. Убедитесь, что ваши медиаданные могут реагировать на Accept-Encoding: gzip .
  • События мультимедиа HTML5 на Android TV могут запускаться в разное время, чем на Chromecast. Это может выявить проблемы, скрытые на Chromecast.
  • При обновлении медиа используйте события, связанные с медиа, которые запускаются элементами <audio>/<video> , например timeupdate , pause и waiting . Избегайте использования событий, связанных с сетью, например progress , suspend и stalled , поскольку они, как правило, зависят от платформы. Подробнее об обработке событий медиа в приемнике см. в разделе События медиа .
  • При настройке сертификатов HTTPS вашего принимающего сайта обязательно включите промежуточные сертификаты CA. См. страницу проверки SSL Qualsys, чтобы проверить: если доверенный путь сертификации для вашего сайта включает сертификат CA с меткой «extra download», то он может не загружаться на платформах на базе Android.
  • В то время как Chromecast отображает страницу приемника на графической плоскости 720p, другие платформы Cast, включая Android TV, могут отображать страницу до 1080p. Убедитесь, что страница приемника масштабируется изящно при разных разрешениях.