Aggiungi funzionalità principali al tuo ricevitore web personalizzato

Questa pagina contiene snippet di codice e descrizioni delle funzionalità disponibili per un'app Custom Web Receiver.

  1. Un elemento cast-media-player che rappresenta la UI del player integrato fornita con Web Receiver.
  2. Stile personalizzato simile a CSS per l'elemento cast-media-player per applicare stili a vari elementi dell'interfaccia utente come background-image, splash-image e font-family.
  3. Un elemento script per caricare il framework Web Receiver.
  4. Codice JavaScript per intercettare i messaggi e gestire gli eventi.
  5. Coda per la riproduzione automatica.
  6. Opzioni per configurare la riproduzione.
  7. Opzioni per impostare il contesto del ricevitore web.
  8. Opzioni per impostare i comandi supportati dall'app Web Receiver.
  9. Una chiamata JavaScript per avviare l'applicazione Web Receiver.

Configurazione e opzioni dell'applicazione

Configura l'applicazione

CastReceiverContext è la classe più esterna esposta allo sviluppatore e gestisce il caricamento delle librerie sottostanti e l'inizializzazione dell'SDK Web Receiver. L'SDK fornisce API che consentono agli sviluppatori di applicazioni di configurare l'SDK tramite CastReceiverOptions. Queste configurazioni vengono valutate una volta per ogni avvio dell'applicazione e vengono trasmesse all'SDK quando viene impostato il parametro facoltativo nella chiamata a start.

L'esempio seguente mostra come eseguire l'override del comportamento predefinito per rilevare se una connessione del mittente è ancora attiva. Quando il ricevitore web non è riuscito a comunicare con un mittente per maxInactivity secondi, viene inviato un evento SENDER_DISCONNECTED. La configurazione riportata di seguito esegue l'override di questo timeout. Può essere utile per il debug dei problemi, in quanto impedisce all'app Web Receiver di chiudere la sessione di Chrome Remote Debugger quando non sono presenti mittenti connessi in uno stato IDLE.

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

Configurare il player

Durante il caricamento dei contenuti, l'SDK Web Receiver offre un modo per configurare le variabili di riproduzione, ad esempio le informazioni DRM, le configurazioni dei tentativi e i gestori delle richieste utilizzando cast.framework.PlaybackConfig. Queste informazioni vengono gestite da PlayerManager e vengono valutate al momento della creazione dei giocatori. I giocatori vengono creati ogni volta che viene passato un nuovo caricamento all'SDK Web Receiver. Le modifiche apportate a PlaybackConfig dopo la creazione del player vengono valutate al successivo caricamento dei contenuti. L'SDK fornisce i seguenti metodi per modificare PlaybackConfig.

  • CastReceiverOptions.playbackConfig per ignorare le opzioni di configurazione predefinite durante l'inizializzazione di CastReceiverContext.
  • PlayerManager.getPlaybackConfig() per ottenere la configurazione attuale.
  • PlayerManager.setPlaybackConfig() per eseguire l'override della configurazione attuale. Questa impostazione viene applicata a tutti i carichi successivi o finché non viene sostituita di nuovo.
  • PlayerManager.setMediaPlaybackInfoHandler() per applicare configurazioni aggiuntive solo all'elemento multimediale caricato in aggiunta alle configurazioni correnti. Il gestore viene chiamato appena prima della creazione del player. Le modifiche apportate qui non sono permanenti e non sono incluse nelle query a getPlaybackConfig(). Quando viene caricato l'elemento multimediale successivo, questo gestore viene chiamato di nuovo.

L'esempio seguente mostra come impostare PlaybackConfig durante l'inizializzazione di CastReceiverContext. La configurazione esegue l'override delle richieste in uscita per ottenere i manifest. Il gestore specifica che le richieste CORS Access-Control devono essere effettuate utilizzando credenziali come cookie o intestazioni di autorizzazione.

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

L'esempio seguente mostra come eseguire l'override di PlaybackConfig utilizzando i metodi getter e setter forniti in PlayerManager. L'impostazione configura il player in modo che riprenda la riproduzione dei contenuti dopo il caricamento di un segmento.

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

L'esempio seguente mostra come sostituire PlaybackConfig per una specifica richiesta di caricamento utilizzando il gestore delle informazioni sulla riproduzione dei contenuti multimediali. Il gestore chiama un metodo getLicenseUrlForMedia implementato dall'applicazione per ottenere licenseUrl dall'contentId dell'elemento corrente.

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

  return playbackConfig;
});

Listener di eventi

L'SDK Web Receiver consente all'app Web Receiver di gestire gli eventi del player. Il listener di eventi accetta un parametro cast.framework.events.EventType (o un array di questi parametri) che specifica gli eventi che devono attivare il listener. Array preconfigurati di cast.framework.events.EventType utili per il debug sono disponibili in cast.framework.events.category. Il parametro evento fornisce ulteriori informazioni sull'evento.

Ad esempio, se vuoi sapere quando viene trasmessa una mediaStatus modifica, puoi utilizzare la seguente logica per gestire l'evento:

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
});

Intercettazione dei messaggi

L'SDK Web Receiver consente all'app Web Receiver di intercettare i messaggi ed eseguire codice personalizzato su questi messaggi. L'intercettatore di messaggi accetta un parametro cast.framework.messages.MessageType che specifica il tipo di messaggio da intercettare.

L'intercettore deve restituire la richiesta modificata o una promessa che si risolve con il valore della richiesta modificata. La restituzione di null impedirà la chiamata al gestore di messaggi predefinito. Per ulteriori dettagli, consulta Caricamento di contenuti multimediali.

Ad esempio, se vuoi modificare i dati della richiesta di caricamento, puoi utilizzare la seguente logica per intercettarli e modificarli:

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();

Gestione degli errori

Quando si verificano errori nell'intercettatore di messaggi, l'app Web Receiver deve restituire un cast.framework.messages.ErrorType e cast.framework.messages.ErrorReason appropriati.

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;
        });
    });

Intercettazione dei messaggi e listener di eventi

Di seguito sono riportate alcune differenze fondamentali tra l'intercettazione dei messaggi e il listener di eventi:

  • Un listener di eventi non ti consente di modificare i dati della richiesta.
  • Un listener di eventi è ideale per attivare Analytics o una funzione personalizzata.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • L'intercettazione dei messaggi ti consente di ascoltare un messaggio, intercettarlo e modificare i dati della richiesta.
  • L'intercettazione dei messaggi è ideale per gestire la logica personalizzata in relazione ai dati delle richieste.

Caricamento dei contenuti multimediali in corso…

MediaInformation fornisce numerose proprietà per caricare contenuti multimediali nel messaggio cast.framework.messages.MessageType.LOAD, tra cui entity, contentUrl e contentId.

  • entity è la proprietà suggerita da utilizzare nell'implementazione sia per le app mittente che per quelle ricevitore. La proprietà è un URL di link diretto che può essere una playlist o contenuti multimediali. La tua applicazione deve analizzare questo URL e compilare almeno uno degli altri due campi.
  • L'contentUrl corrisponde all'URL riproducibile che il player utilizzerà per caricare i contenuti. Ad esempio, questo URL potrebbe rimandare a un manifest DASH.
  • contentId può essere un URL di contenuti riproducibili (simile a quello della proprietà contentUrl) o un identificatore univoco per i contenuti o la playlist da caricare. Se utilizzi questa proprietà come identificatore, la tua applicazione deve compilare un URL riproducibile in contentUrl.

Il suggerimento è di utilizzare entity per memorizzare l'ID reale o i parametri chiave e contentUrl per l'URL del media. Un esempio è mostrato nello snippet seguente, in cui entity è presente nella richiesta LOAD e viene recuperato contentUrl riproducibile:

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;
        });
    });

Funzionalità del dispositivo

Il metodo getDeviceCapabilities fornisce informazioni sul dispositivo di trasmissione connesso e sul dispositivo video o audio collegato. Il metodo getDeviceCapabilities fornisce informazioni di assistenza per l'Assistente Google, il Bluetooth e i dispositivi audio e di visualizzazione connessi.

Questo metodo restituisce un oggetto su cui puoi eseguire query passando uno degli enum specificati per ottenere la funzionalità del dispositivo per quell'enum. Gli enum sono definiti in cast.framework.system.DeviceCapabilities.

Questo esempio verifica se il dispositivo Web Receiver è in grado di riprodurre HDR e DolbyVision (DV) con i tasti IS_HDR_SUPPORTED e IS_DV_SUPPORTED rispettivamente.

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();

Gestione dell'interazione utente

Un utente può interagire con l'applicazione Web Receiver tramite applicazioni mittente (web, Android e iOS), comandi vocali su dispositivi con l'Assistente integrato, controlli touch su smart display e telecomandi su dispositivi Android TV. L'SDK Cast fornisce varie API per consentire all'app Web Receiver di gestire queste interazioni, aggiornare la UI dell'applicazione tramite gli stati delle azioni utente e, facoltativamente, inviare le modifiche per aggiornare i servizi di backend.

Comandi multimediali supportati

Gli stati dei controlli dell'UI sono determinati da MediaStatus.supportedMediaCommands per i controller espansi del mittente per iOS e Android, le app ricevitore e telecomando in esecuzione su dispositivi touch e le app ricevitore sui dispositivi Android TV. Quando un determinato Command bitwise è abilitato nella proprietà, i pulsanti correlati a questa azione vengono abilitati. Se il valore non è impostato, il pulsante è disattivato. Questi valori possono essere modificati su Web Receiver:

  1. Utilizzo di PlayerManager.setSupportedMediaCommands per impostare il valore Commands specifico
  2. Aggiunta di un nuovo comando utilizzando addSupportedMediaCommands
  3. Rimozione di un comando esistente utilizzando removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

Quando il destinatario prepara l'MediaStatus aggiornato, questo includerà le modifiche nella proprietà supportedMediaCommands. Quando lo stato viene trasmesso, le app mittente connesse aggiorneranno i pulsanti nella propria UI di conseguenza.

Per ulteriori informazioni sui comandi multimediali e sui dispositivi touch supportati, consulta la guida Accessing UI controls.

Gestione degli stati delle azioni utente

Quando gli utenti interagiscono con l'interfaccia utente o inviano comandi vocali, possono controllare la riproduzione dei contenuti e le proprietà relative all'elemento in riproduzione. Le richieste che controllano la riproduzione vengono gestite automaticamente dall'SDK. Le richieste che modificano le proprietà dell'elemento in riproduzione corrente, ad esempio un comando LIKE, richiedono che l'applicazione ricevitore le gestisca. L'SDK fornisce una serie di API per gestire questi tipi di richieste. Per supportare queste richieste, è necessario effettuare le seguenti operazioni:

  • Imposta MediaInformation userActionStates con le preferenze di un utente durante il caricamento di un elemento multimediale.
  • Intercetta i messaggi USER_ACTION e determina l'azione richiesta.
  • Aggiorna MediaInformation UserActionState per aggiornare la UI.

Il seguente snippet intercetta la richiesta LOAD e compila MediaInformation di LoadRequestData. In questo caso, all'utente piace il contenuto in fase di caricamento.

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;
    });

Il seguente snippet intercetta il messaggio USER_ACTION e gestisce la chiamata al backend con la modifica richiesta. Quindi, effettua una chiamata per aggiornare UserActionState sul ricevitore.

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;
    });
});

Il seguente snippet simula una chiamata a un servizio di backend. La funzione controlla UserActionRequestData per vedere il tipo di modifica richiesta dall'utente e fa una chiamata di rete solo se l'azione è supportata dal backend.

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));
    }
  });
}

Lo snippet seguente prende UserActionRequestData e aggiunge o rimuove UserActionState da MediaInformation. L'aggiornamento di UserActionState di MediaInformation modifica lo stato del pulsante associato all'azione richiesta. Questa modifica si riflette nell'interfaccia utente dei controlli dello smart display, nell'app telecomando e nell'interfaccia utente di Android TV. Viene inoltre trasmesso tramite messaggi MediaStatus in uscita per aggiornare l'interfaccia utente del controller espanso per i mittenti iOS e 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;
}

Comandi vocali

I seguenti comandi multimediali sono attualmente supportati nell'SDK Web Receiver per i dispositivi con l'assistente integrato. Le implementazioni predefinite di questi comandi si trovano in cast.framework.PlayerManager.

Comando Descrizione
Riproduci Riprodurre o riprendere la riproduzione dallo stato di pausa.
Metti in pausa Mettere in pausa i contenuti in riproduzione.
Indietro Passa all'elemento multimediale precedente nella coda multimediale.
Avanti Passa all'elemento multimediale successivo nella coda multimediale.
Interrompi Interrompi la riproduzione dei contenuti multimediali in corso.
Non ripetere nulla Disattiva la ripetizione degli elementi multimediali nella coda una volta terminata la riproduzione dell'ultimo elemento della coda.
Ripeti singolo Ripete all'infinito i contenuti multimediali attualmente in riproduzione.
Ripeti tutto Ripete tutti gli elementi della coda una volta riprodotto l'ultimo elemento.
Ripeti tutto e Riproduzione casuale Una volta riprodotto l'ultimo elemento della coda, riproduci in modalità casuale la coda e ripeti tutti gli elementi della coda.
Shuffle Riproduci in ordine casuale gli elementi multimediali nella coda multimediale.
Sottotitoli codificati ON / OFF Attiva / disattiva i sottotitoli codificati per i tuoi contenuti multimediali. L'attivazione / disattivazione è disponibile anche per lingua.
Vai al tempo assoluto Salta al momento assoluto specificato.
Vai all'ora relativa all'ora attuale Salta in avanti o indietro del periodo di tempo specificato rispetto al tempo di riproduzione corrente.
Gioca di nuovo Riavvia i contenuti multimediali in riproduzione o riproduce l'ultimo elemento riprodotto se al momento non è in riproduzione nulla.
Impostare la velocità di riproduzione Variare la velocità di riproduzione dei contenuti multimediali. Questo dovrebbe essere gestito per impostazione predefinita. Puoi utilizzare l'intercettatore di messaggi SET_PLAYBACK_RATE per ignorare le richieste di tariffa in entrata.

Comandi multimediali supportati con la voce

Per impedire che un comando vocale attivi un comando multimediale su un dispositivo con l'assistente integrato, devi prima impostare i comandi multimediali supportati che intendi supportare. Quindi devi applicare questi comandi attivando la proprietà CastReceiverOptions.enforceSupportedCommands. L'interfaccia utente sui mittenti dell'SDK Cast e sui dispositivi touch cambierà per riflettere queste configurazioni. Se il flag non è attivato, i comandi vocali in arrivo verranno eseguiti.

Ad esempio, se consenti PAUSE dalle applicazioni di invio e dai dispositivi touch, devi anche configurare il ricevitore in modo che rifletta queste impostazioni. Se configurati, tutti i comandi vocali in entrata verranno eliminati se non inclusi nell'elenco dei comandi supportati.

Nell'esempio seguente forniamo CastReceiverOptions all'avvio di CastReceiverContext. Abbiamo aggiunto il supporto per il comando PAUSE e imposto il player in modo che supporti solo questo comando. Ora, se un comando vocale richiede un'altra operazione, ad esempio SEEK, verrà rifiutato. L'utente riceverà una notifica che lo informa che il comando non è ancora supportato.

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

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

Puoi applicare una logica separata per ogni comando che vuoi limitare. Rimuovi il flag enforceSupportedCommands e per ogni comando che vuoi limitare puoi intercettare il messaggio in arrivo. Qui intercettiamo la richiesta fornita dall'SDK in modo che i comandi SEEKemessi ai dispositivi con l'assistente non attivino una ricerca nell'applicazione Web Receiver.

Per i comandi multimediali non supportati dalla tua applicazione, restituisci un motivo di errore appropriato, ad esempio 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;
  });

Backgrounding dall'attività vocale

Se la piattaforma Cast mette in secondo piano l'audio della tua applicazione a causa dell'attività dell'assistente, ad esempio l'ascolto del discorso dell'utente o la risposta, viene inviato un messaggio FocusState di NOT_IN_FOCUS all'applicazione Web Receiver quando inizia l'attività. Al termine dell'attività, viene inviato un altro messaggio con IN_FOCUS. A seconda dell'applicazione e dei contenuti multimediali riprodotti, potresti voler mettere in pausa i contenuti multimediali quando l'FocusState è NOT_IN_FOCUS intercettando il tipo di messaggio FOCUS_STATE.

Ad esempio, è una buona esperienza utente mettere in pausa la riproduzione dell'audiobook se l'assistente sta rispondendo a una query dell'utente.

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;
  });

Lingua dei sottotitoli codificati specificata con la voce

Quando un utente non specifica esplicitamente la lingua dei sottotitoli codificati, la lingua utilizzata per i sottotitoli codificati è la stessa in cui è stato pronunciato il comando. In questi scenari, il parametro isSuggestedLanguage del messaggio in arrivo indica se la lingua associata è stata suggerita o richiesta esplicitamente dall'utente.

Ad esempio, isSuggestedLanguage è impostato su true per il comando "Ok Google, attiva i sottotitoli codificati", perché la lingua è stata dedotta dalla lingua in cui è stato pronunciato il comando. Se la lingua viene richiesta esplicitamente, ad esempio "Ok Google, attiva i sottotitoli codificati in inglese", isSuggestedLanguage è impostato su false.

Metadati e doppiaggio

Sebbene i comandi vocali vengano gestiti per impostazione predefinita dal Web Receiver, devi assicurarti che i metadati dei tuoi contenuti siano completi e accurati. In questo modo, i comandi vocali vengono gestiti correttamente dall'assistente e i metadati vengono visualizzati correttamente nei nuovi tipi di interfacce, come l'app Google Home e gli smart display come Google Nest Hub.

Trasferimento dello streaming

Il mantenimento dello stato della sessione è la base del trasferimento dello stream, in cui gli utenti possono spostare gli stream audio e video esistenti tra i dispositivi utilizzando i comandi vocali, l'app Google Home o gli smart display. La riproduzione dei contenuti multimediali si interrompe su un dispositivo (l'origine) e continua su un altro (la destinazione). Qualsiasi dispositivo di trasmissione con il firmware più recente può fungere da origine o destinazione in un trasferimento di stream.

Il flusso di eventi per il trasferimento dello stream è:

  1. Sul dispositivo di origine:
    1. La riproduzione dei contenuti multimediali si interrompe.
    2. L'applicazione Web Receiver riceve un comando per salvare lo stato attuale dei contenuti multimediali.
    3. L'applicazione Web Receiver viene chiusa.
  2. Sul dispositivo di destinazione:
    1. L'applicazione Web Receiver è caricata.
    2. L'applicazione Web Receiver riceve un comando per ripristinare lo stato dei contenuti multimediali salvati.
    3. La riproduzione dei contenuti multimediali riprende.

Gli elementi dello stato dei contenuti multimediali includono:

  • Posizione o timestamp specifici del brano, del video o dell'elemento multimediale.
  • La sua posizione in una coda più ampia (ad esempio una playlist o la radio dell'artista).
  • L'utente autenticato.
  • Stato di riproduzione (ad esempio, riproduzione o pausa).

Abilitazione del trasferimento dello streaming

Per implementare il trasferimento dello stream per il tuo Web Receiver:

  1. Aggiorna supportedMediaCommands con il comando STREAM_TRANSFER:
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. (Facoltativo) Esegui l'override degli intercettori di messaggi SESSION_STATE e RESUME_SESSION come descritto in Conservare lo stato della sessione. Esegui l'override solo se i dati personalizzati devono essere archiviati come parte dello snapshot della sessione. In caso contrario, l'implementazione predefinita per la conservazione degli stati della sessione supporterà il trasferimento dello stream.

Conservare lo stato della sessione

L'SDK Web Receiver fornisce un'implementazione predefinita per le app Web Receiver per conservare gli stati della sessione acquisendo uno snapshot dello stato attuale dei contenuti multimediali, convertendo lo stato in una richiesta di caricamento e riprendendo la sessione con la richiesta di caricamento.

La richiesta di caricamento generata dal ricevitore web può essere sostituita nell'intercettore di messaggi SESSION_STATE, se necessario. Se vuoi aggiungere dati personalizzati alla richiesta di caricamento, ti consigliamo di inserirli in 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;
    });

I dati personalizzati possono essere recuperati da loadRequestData.customData nell'intercettatore di messaggi 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;
    });

Precaricamento dei contenuti

Web Receiver supporta il precaricamento degli elementi multimediali dopo l'elemento di riproduzione corrente nella coda.

L'operazione di precaricamento pre-scarica diversi segmenti degli elementi in arrivo. La specifica viene eseguita sul valore preloadTime nell'oggetto QueueItem (il valore predefinito è 20 secondi se non viene fornito). Il tempo è espresso in secondi, rispetto alla fine dell'elemento attualmente in riproduzione . Sono validi solo i valori positivi. Ad esempio, se il valore è 10 secondi, questo elemento verrà precaricato 10 secondi prima che l'elemento precedente sia terminato. Se il tempo di precaricamento è superiore al tempo rimanente dell'elemento corrente, il precaricamento avverrà il prima possibile. Pertanto, se viene specificato un valore di precaricamento molto elevato per queueItem, si potrebbe ottenere l'effetto di precaricare l'elemento successivo durante la riproduzione dell'elemento corrente. Tuttavia, lasciamo l'impostazione e la scelta di questo valore allo sviluppatore, in quanto può influire sulla larghezza di banda e sulle prestazioni di streaming dell'elemento in riproduzione.

Il precaricamento funziona per impostazione predefinita per i contenuti HLS, DASH e Smooth Streaming.

I normali file audio e video MP4, come MP3, non verranno precaricati perché i dispositivi Cast supportano un solo elemento multimediale e non possono essere utilizzati per il precaricamento mentre è in riproduzione un elemento di contenuti esistente.

Messaggi personalizzati

Lo scambio di messaggi è il metodo di interazione chiave per le applicazioni Web Receiver.

Un mittente invia messaggi a un ricevitore web utilizzando le API mittente per la piattaforma su cui è in esecuzione (Android, iOS, web). L'oggetto evento (che è la manifestazione di un messaggio) passato ai listener di eventi ha un elemento di dati (event.data) in cui i dati assumono le proprietà del tipo di evento specifico.

Un'applicazione Web Receiver può scegliere di ascoltare i messaggi in uno spazio dei nomi specificato. In questo modo, si dice che l'applicazione Web Receiver supporta il protocollo dello spazio dei nomi. Spetta quindi a tutti i mittenti connessi che desiderano comunicare nello spazio dei nomi utilizzare il protocollo appropriato.

Tutti gli spazi dei nomi sono definiti da una stringa e devono iniziare con "urn:x-cast:" seguito da una stringa qualsiasi. Ad esempio, "urn:x-cast:com.example.cast.mynamespace".

Ecco uno snippet di codice per Web Receiver per ascoltare i messaggi personalizzati provenienti da mittenti connessi:

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();

Allo stesso modo, le applicazioni Web Receiver possono tenere informati i mittenti sullo stato di Web Receiver inviando messaggi ai mittenti connessi. Un'applicazione Web Receiver può inviare messaggi utilizzando sendCustomMessage(namespace, senderId, message) su CastReceiverContext. Un Web Receiver può inviare messaggi a un singolo mittente, in risposta a un messaggio ricevuto o a causa di una modifica dello stato dell'applicazione. Oltre alla messaggistica point-to-point (con un limite di 64 KB), un ricevitore web può anche trasmettere messaggi a tutti i mittenti connessi.

Trasmettere per dispositivi audio

Consulta la guida di Google Cast per i dispositivi audio per assistenza sulla riproduzione solo audio.

Android TV

Questa sezione illustra come Google Web Receiver utilizza gli input per la riproduzione e la compatibilità con Android TV.

Integrazione dell'applicazione con il telecomando

Google Web Receiver in esecuzione sul dispositivo Android TV traduce l'input dai controlli di input del dispositivo (ad es. telecomando portatile) come messaggi di riproduzione multimediale definiti per lo spazio dei nomi urn:x-cast:com.google.cast.media, come descritto in Messaggi di riproduzione multimediale. La tua applicazione deve supportare questi messaggi per controllare la riproduzione dei contenuti multimediali dell'applicazione al fine di consentire il controllo di riproduzione di base dagli input di controllo di Android TV.

Linee guida per la compatibilità con Android TV

Ecco alcuni suggerimenti e problemi comuni da evitare per garantire la compatibilità della tua applicazione con Android TV:

  • Tieni presente che la stringa user-agent contiene sia "Android" sia "CrKey"; alcuni siti potrebbero reindirizzare a un sito solo per dispositivi mobili perché rilevano l'etichetta "Android". Non dare per scontato che "Android" nella stringa user agent indichi sempre un utente mobile.
  • Lo stack multimediale di Android potrebbe utilizzare GZIP trasparente per recuperare i dati. Assicurati che i tuoi dati multimediali possano rispondere a Accept-Encoding: gzip.
  • Gli eventi multimediali HTML5 di Android TV potrebbero essere attivati in tempi diversi rispetto a Chromecast, il che potrebbe rivelare problemi nascosti su Chromecast.
  • Quando aggiorni i contenuti multimediali, utilizza gli eventi correlati ai contenuti multimediali attivati dagli elementi <audio>/<video>, come timeupdate, pause e waiting. Evita di utilizzare eventi correlati al networking come progress, suspend e stalled, in quanto tendono a dipendere dalla piattaforma. Per saperne di più sulla gestione degli eventi multimediali nel ricevitore, consulta la sezione Eventi multimediali.
  • Quando configuri i certificati HTTPS del sito ricevitore, assicurati di includere i certificati CA intermedi. Consulta la pagina di test SSL di Qualsys per verificare: se il percorso di certificazione attendibile per il tuo sito include un certificato CA etichettato come "download aggiuntivo", potrebbe non essere caricato su piattaforme basate su Android.
  • Mentre Chromecast visualizza la pagina del ricevitore su un piano grafico a 720p, altre piattaforme di trasmissione, tra cui Android TV, potrebbero visualizzare la pagina fino a 1080p. Assicurati che la pagina del destinatario venga scalata correttamente a risoluzioni diverse.