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

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

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

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

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

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

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

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

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

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

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

В примере ниже показано, как установить PlaybackConfig при инициализации CastReceiverContext . Конфигурация переопределяет исходящие запросы на получение манифестов. Обработчик указывает, что запросы контроля доступа CORS должны выполняться с использованием учетных данных, таких как файлы 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;
});

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

SDK веб-приемника позволяет вашему приложению веб-приемника обрабатывать события игрока. Прослушиватель событий принимает параметр 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
});

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

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

Перехватчик должен вернуть измененный запрос или обещание, которое разрешается с измененным значением запроса. Возврат 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();

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

При возникновении ошибок в перехватчике сообщений ваше приложение веб-приемника должно возвращать соответствующие значения 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 для хранения реального идентификатора или ключевых параметров и использовать 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 .

В этом примере проверяется, способно ли устройство веб-приемника воспроизводить 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();

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

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

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

Состояния элементов управления пользовательского интерфейса управляются 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;
}

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

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

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

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

Чтобы голосовая команда не запускала мультимедийную команду на устройстве с поддержкой Ассистента, необходимо сначала настроить поддерживаемые мультимедийные команды , которые вы планируете поддерживать. Затем вы должны обеспечить соблюдение этих команд, включив свойство 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, не запускали поиск в вашем приложении веб-приемника.

Для мультимедийных команд, которые ваше приложение не поддерживает, верните соответствующую причину ошибки, например 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 отправляется приложению веб-приемника при запуске действия. Другое сообщение с 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 для команды «ОК, Google, включи субтитры», поскольку язык был определен по языку, на котором была произнесена команда. Если язык запрошен явно, например, в команде «ОК, Google, включите Английские субтитры», для параметра isSuggestedLanguage установлено значение false .

Метаданные и голосовой кастинг

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

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

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

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

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

К элементам медиагосударства относятся:

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

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

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

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

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

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

Запрос на загрузку, сгенерированный веб-приемником, при необходимости можно переопределить в перехватчике сообщений 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, предварительная загрузка произойдет как можно скорее. Таким образом, если для объекта QueueItem указано очень большое значение предварительной загрузки, можно добиться эффекта, при котором всякий раз, когда мы воспроизводим текущий элемент, мы уже предварительно загружаем следующий элемент. Однако мы оставляем настройку и выбор этого параметра на усмотрение разработчика, поскольку это значение может повлиять на пропускную способность и производительность потоковой передачи текущего воспроизводимого элемента.

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

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

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

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

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

Приложение веб-приемника может прослушивать сообщения в указанном пространстве имен. В результате считается, что приложение 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();

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

Cast для аудиоустройств

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

Андроид ТВ

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

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

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

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

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

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