Aggiungi funzionalità principali al tuo ricevitore web personalizzato

Questa pagina contiene snippet di codice e descrizioni delle funzionalità disponibili per un'app Ricevitore web personalizzato.

  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 lo stile a vari elementi UI, come background-image, splash-image e font-family.
  3. Un elemento script per caricare il framework del ricevitore web.
  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 lancio dell'applicazione e vengono passate all'SDK quando si imposta 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 seguente esegue l'override di questo timeout. Questo può essere utile durante il debug dei problemi, in quanto impedisce all'app Web Receiver di chiudere la sessione di Chrome Remote Debugger quando non ci sono sender connessi in stato IDLE.

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

Configura il player

Durante il caricamento dei contenuti, l'SDK Web Receiver consente di configurare le variabili di riproduzione, come le informazioni DRM, le configurazioni dei nuovi tentativi e i gestori delle richieste utilizzando cast.framework.PlaybackConfig. Queste informazioni vengono gestite da PlayerManager e vengono valutate al momento della creazione dei player. I player vengono creati ogni volta che un nuovo caricamento viene passato all'SDK Web Receiver. Le modifiche 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 eseguire l'override delle 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 caricamenti successivi o finché non viene eseguito un altro override.
  • PlayerManager.setMediaPlaybackInfoHandler() per applicare configurazioni aggiuntive solo all'elemento multimediale caricato oltre 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 Access-Control CORS 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 il getter e il 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 eseguire l'override di PlaybackConfig per una richiesta di caricamento specifica utilizzando il gestore delle informazioni di riproduzione dei contenuti multimediali. Il gestore chiama un metodo implementato dall'applicazione getLicenseUrlForMedia per ottenere licenseUrl da 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 alla tua 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. Gli 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 modifica di mediaStatus, 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 alla tua 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'intercettatore deve restituire la richiesta modificata o una Promise che si risolve con il valore della richiesta modificata. La restituzione di null impedirà la chiamata del gestore dei messaggi predefinito. Per maggiori dettagli, consulta Caricamento dei 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 un 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 consente di modificare i dati della richiesta.
  • Un listener di eventi è ideale per attivare l'analisi 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 stessa.
  • L'intercettazione dei messaggi è ideale per gestire la logica personalizzata relativa ai dati delle richieste.

Caricamento di contenuti multimediali in corso…

MediaInformation fornisce numerose proprietà per caricare i 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 deep link che può essere una playlist o un contenuto multimediale. L'applicazione deve analizzare questo URL e compilare almeno uno degli altri due campi.
  • contentUrl corrisponde all'URL riproducibile che il player utilizzerà per caricare i contenuti. Ad esempio, questo URL potrebbe puntare a un manifest DASH.
  • contentId può essere un URL di contenuti riproducibili (simile a quello della proprietà contentUrl) o un identificatore univoco dei contenuti o della playlist in fase di caricamento. 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 di utilizzare contentUrl per l'URL dei contenuti multimediali. Un esempio è mostrato nel seguente snippet, in cui entity è presente nella richiesta LOAD e viene recuperato il 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à per il dispositivo

Il metodo getDeviceCapabilities fornisce informazioni sul dispositivo Cast 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 ricevitore web è 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 la tua applicazione ricevitore web 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 l'interfaccia utente 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 UI sono gestiti da MediaStatus.supportedMediaCommands per i controller espansi dei mittenti iOS e Android, le app di ricezione e telecomando in esecuzione su dispositivi touch e le app di ricezione su dispositivi Android TV. Quando nella proprietà viene attivato un determinato Command bit per bit, vengono attivati i pulsanti correlati a quell'azione. Se il valore non è impostato, il pulsante è disattivato. Questi valori possono essere modificati sul ricevitore web:

  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 il MediaStatus aggiornato, includerà le modifiche nella proprietà supportedMediaCommands. Quando lo stato viene trasmesso, le app mittente collegate aggiornano i pulsanti nella loro 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 attualmente in riproduzione, 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:

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

Il seguente snippet intercetta la richiesta LOAD e compila il campo MediaInformation di LoadRequestData. In questo caso, l'utente apprezza i contenuti che vengono caricati.

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

Lo snippet seguente 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;
    });
});

Lo snippet seguente simula una chiamata a un servizio di backend. La funzione controlla UserActionRequestData per vedere il tipo di modifica richiesto dall'utente ed effettua 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 del telecomando e nell'interfaccia utente di Android TV. Viene anche trasmesso tramite messaggi MediaStatus in uscita per aggiornare la UI 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 Riproduci o riprendi la riproduzione dallo stato di pausa.
Metti in pausa Metti in pausa i contenuti attualmente in riproduzione.
Indietro Passa all'elemento multimediale precedente nella coda di contenuti multimediali.
Avanti Passa all'elemento multimediale successivo nella coda di contenuti multimediali.
Interrompi Interrompere i contenuti multimediali in riproduzione.
Nessuna ripetizione Disattiva la ripetizione degli elementi multimediali nella coda una volta terminata la riproduzione dell'ultimo elemento.
Ripeti singolo Ripeti i contenuti multimediali attualmente in riproduzione a tempo indeterminato.
Ripeti tutti Ripeti tutti gli elementi della coda una volta riprodotto l'ultimo elemento.
Ripeti tutto e Riproduzione casuale Una volta terminata la riproduzione dell'ultimo elemento della coda, riproduci in ordine casuale e ripeti tutti gli elementi della coda.
Riproduzione casuale 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 a un momento assoluto Passa all'ora assoluta specificata.
Spostati a un orario relativo all'ora corrente Salta avanti o indietro del periodo di tempo specificato rispetto al tempo di riproduzione corrente.
Gioca ancora Riavvia i contenuti multimediali in riproduzione o riproduce l'ultimo elemento multimediale riprodotto se non è in riproduzione alcun contenuto.
Imposta la velocità di riproduzione Modificare la velocità di riproduzione dei contenuti multimediali. Questo dovrebbe essere gestito per impostazione predefinita. Puoi utilizzare l'intercettatore di messaggi SET_PLAYBACK_RATE per eseguire l'override delle richieste di tariffa in entrata.

Comandi vocali supportati per i contenuti multimediali

Per evitare che un comando vocale attivi un comando multimediale su un dispositivo con l'assistente integrato, devi prima impostare i comandi multimediali supportati che prevedi di supportare. Poi devi applicare questi comandi attivando la proprietà CastReceiverOptions.enforceSupportedCommands. La UI sui mittenti Cast SDK e sui dispositivi touch cambierà per riflettere queste configurazioni. Se il flag non è attivo, i comandi vocali in arrivo verranno eseguiti.

Ad esempio, se consenti PAUSE dalle tue applicazioni mittente e dai dispositivi touch, devi anche configurare il ricevitore in modo che rifletta queste impostazioni. Se configurata, tutti i comandi vocali in arrivo verranno ignorati se non sono 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 al player di supportare solo questo comando. Ora, se un comando vocale richiede un'altra operazione, ad esempio SEEK, questa verrà negata. 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 SEEK inviati ai dispositivi con l'assistente integrato 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 background l'audio della tua applicazione a causa dell'attività dell'assistente, ad esempio l'ascolto della voce dell'utente o la risposta, un messaggio FocusState di NOT_IN_FOCUS viene inviato all'applicazione Web Receiver all'inizio dell'attività. Un altro messaggio con IN_FOCUS viene inviato al termine dell'attività. A seconda dell'applicazione e dei contenuti multimediali in riproduzione, potresti voler mettere in pausa i contenuti multimediali quando FocusState è NOT_IN_FOCUS intercettando il tipo di messaggio FOCUS_STATE.

Ad esempio, è una buona esperienza utente mettere in pausa la riproduzione dell'audiolibro 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 dalla voce

Quando un utente non indica esplicitamente la lingua dei sottotitoli, la lingua utilizzata per i sottotitoli è 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 "Hey Google, attiva i sottotitoli", perché la lingua è stata dedotta dalla lingua in cui è stato pronunciato il comando. Se la lingua viene richiesta esplicitamente, ad esempio "Hey Google, attiva i sottotitoli codificati in inglese", isSuggestedLanguage viene impostato su false.

Metadati e casting vocale

Sebbene i comandi vocali siano gestiti dal ricevitore web per impostazione predefinita, 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 Home Hub.

Trasferimento dello streaming

La conservazione dello stato della sessione è alla base del trasferimento dello streaming, che consente agli utenti di 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 (la sorgente) 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 dello streaming.

Il flusso di eventi per il trasferimento dello streaming è il seguente:

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

Gli elementi dello stato dei contenuti multimediali includono:

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

Attivazione del trasferimento dello streaming

Per implementare il trasferimento dello streaming per il tuo ricevitore web:

  1. Aggiorna supportedMediaCommands con il comando STREAM_TRANSFER:
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. Facoltativamente, esegui l'override degli intercettatori di messaggi SESSION_STATE e RESUME_SESSION come descritto in Conservazione dello stato della sessione. Esegui l'override di questi valori solo se i dati dei clienti 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 streaming.

Conservazione dello stato della sessione

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

Se necessario, la richiesta di caricamento generata dal ricevitore web può essere sostituita nell'intercettatore di messaggi SESSION_STATE. 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

Il ricevitore web supporta il precaricamento degli elementi multimediali dopo l'elemento di riproduzione corrente nella coda.

L'operazione di precaricamento scarica in anticipo diversi segmenti degli elementi imminenti. 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 del termine dell'elemento precedente. Se il tempo di precaricamento è superiore al tempo rimanente su currentItem, il precaricamento avverrà il prima possibile. Quindi, se per queueItem viene specificato un valore di precaricamento molto elevato, si potrebbe ottenere l'effetto che, ogni volta che riproduciamo l'elemento corrente, precarichiamo già l'elemento successivo. 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 attualmente in riproduzione.

Il precaricamento funzionerà per impostazione predefinita per i contenuti in streaming HLS, DASH e Smooth.

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

Messaggi personalizzati

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

Un mittente invia messaggi a un ricevitore web utilizzando le API del 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 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, l'applicazione Web Receiver supporta il protocollo dello spazio dei nomi. Spetta poi ai mittenti connessi che vogliono comunicare in quello 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 il ricevitore web per ascoltare i messaggi personalizzati dei 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();

Analogamente, le applicazioni ricevitore web possono tenere informati i mittenti sullo stato del ricevitore web inviando messaggi ai mittenti connessi. Un'applicazione Web Receiver può inviare messaggi utilizzando sendCustomMessage(namespace, senderId, message) su CastReceiverContext. Un ricevitore web 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 annunci a tutti i mittenti connessi.

Trasmetti 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 il ricevitore web Google utilizza i tuoi input come riproduzione e la compatibilità con Android TV.

Integrazione dell'applicazione con il telecomando

Il Web Receiver Google in esecuzione sul dispositivo Android TV traduce l'input proveniente dai controlli del dispositivo (ad es. il telecomando portatile) in 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 di contenuti multimediali dell'applicazione, in modo da consentire i controlli di riproduzione di base dagli input di controllo di Android TV.

Linee guida per la compatibilità con Android TV

Ecco alcuni consigli e problemi comuni da evitare per garantire che la tua applicazione sia compatibile con Android TV:

  • Tieni presente che la stringa dello 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 dello user agent indichi sempre un utente mobile.
  • Lo stack multimediale di Android potrebbe utilizzare GZIP trasparente per il recupero dei 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 che erano 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 alla rete come progress, suspend e stalled, in quanto tendono a dipendere dalla piattaforma. Per saperne di più sulla gestione degli eventi multimediali nel ricevitore, consulta Eventi multimediali.
  • Quando configuri i certificati HTTPS del sito del 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 con l'etichetta "download aggiuntivo", potrebbe non essere caricato sulle piattaforme basate su Android.
  • Mentre Chromecast visualizza la pagina del ricevitore su un piano grafico a 720p, altre piattaforme Cast, tra cui Android TV, possono visualizzare la pagina fino a 1080p. Assicurati che la pagina del ricevitore si adatti correttamente alle diverse risoluzioni.