Aggiungi funzionalità principali al tuo ricevitore web personalizzato

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

  1. Un elemento cast-media-player che rappresenta l'interfaccia utente del player integrato fornita con Web receiver.
  2. Stili personalizzati di tipo CSS per l'elemento cast-media-player per applicare uno stile a vari elementi UI, come background-image, splash-image e font-family.
  3. Un elemento di script per caricare il framework Web receiver.
  4. codice JavaScript per l'intercettazione dei messaggi e la gestione degli 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. Gestisce il caricamento delle librerie sottostanti e gestisce 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 seguente sostituisce questo timeout. Questo può essere utile durante il debug dei problemi, in quanto impedisce all'app Web receiver di chiudere la sessione Chrome Remote Debugger quando non sono presenti mittenti connessi in 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 WebRicevir fornisce un modo per configurare variabili di riproduzione come le informazioni DRM, ritentare le configurazioni e i gestori di 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 viene passato un nuovo carico all'SDK Web receiver. Le modifiche all'PlaybackConfig dopo la creazione del player vengono valutate nel caricamento di contenuti successivo. 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 fino a quando non viene eseguito nuovamente l'override.
  • PlayerManager.setMediaPlaybackInfoHandler() per applicare configurazioni aggiuntive solo all'elemento multimediale caricato sopra le configurazioni attuali. Il gestore viene chiamato appena prima della creazione del player. Le modifiche apportate qui non sono permanenti e non sono incluse nelle query su getPlaybackConfig(). Quando viene caricato l'elemento multimediale successivo, questo gestore viene richiamato.

L'esempio seguente mostra come impostare PlaybackConfig durante l'inizializzazione di CastReceiverContext. La configurazione sostituisce le richieste in uscita per l'ottenimento dei 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 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 1 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 sulla riproduzione dei contenuti multimediali. Il gestore chiama un metodo implementato dall'applicazione getLicenseUrlForMedia per ottenere il valore licenseUrl dall'elemento 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 richiede 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 informazioni aggiuntive 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 ricevitore consente alla tua app Web receiver di intercettare i messaggi ed eseguire codice personalizzato su questi messaggi. L'intercettatore di messaggi prende un parametro cast.framework.messages.MessageType che specifica il tipo di messaggio da intercettare.

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

Ad esempio, se vuoi modificare i dati della richiesta di carico, 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 WebRicevitore dovrebbe restituire 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;
        });
    });

Confronto tra intercettazione dei messaggi e listener di eventi

Ecco 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 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, intercettare un messaggio e modificare i dati della richiesta stessi.
  • L'intercettazione dei messaggi è la soluzione ideale per gestire la logica personalizzata per quanto riguarda la richiesta di dati.

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 l'app mittente sia per l'app ricevente. La proprietà è un URL di link diretto che può essere una playlist o contenuti multimediali. L'applicazione deve analizzare questo URL e compilare almeno uno degli altri due campi.
  • Il parametro contentUrl corrisponde all'URL riproducibile che verrà utilizzato dal player per caricare i contenuti. Ad esempio, questo URL potrebbe indirizzare 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 che vengono caricati. Se utilizzi questa proprietà come identificatore, l'applicazione deve completare un URL demo nella sezione contentUrl.

Il suggerimento è utilizzare entity per archiviare l'ID reale o i parametri chiave e utilizzare contentUrl per l'URL dell'elemento multimediale. Un esempio è mostrato nello snippet seguente, 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à 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 supporto per l'Assistente Google, il Bluetooth e i dispositivi audio e display collegati.

Questo metodo restituisce un oggetto su cui puoi eseguire una query passando una delle enumerazioni specificate per ottenere la funzionalità del dispositivo per quell'enumerazione. Le enum sono definite in cast.framework.system.DeviceCapabilities.

Questo esempio verifica se il dispositivo ricevitore web è in grado di riprodurre rispettivamente i formati HDR e DolbyVision (DV) con i tasti IS_HDR_SUPPORTED e 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();

Gestione delle interazioni degli utenti

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

Comandi multimediali supportati

Gli stati dei controlli dell'interfaccia utente si basano su MediaStatus.supportedMediaCommands per controller espansi, app ricevitore e di controllo remoto in esecuzione su dispositivi touch e app ricevitore su dispositivi Android TV. Quando nella proprietà viene attivato un determinato Command a bit a bit, i pulsanti relativi a tale azione vengono attivati. Se il valore non è impostato, il pulsante è disattivato. Questi valori possono essere modificati sul ricevitore web:

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

Quando il destinatario prepara l'oggetto MediaStatus aggiornato, includerà le modifiche nella proprietà supportedMediaCommands. Quando lo stato viene trasmesso, le app di mittenti connesse aggiornano di conseguenza i pulsanti nella loro UI.

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

Gestione degli stati delle azioni degli utenti

Quando gli utenti interagiscono con l'interfaccia utente o inviano comandi vocali, possono controllare la riproduzione dei contenuti e delle proprietà relativi 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 ricevente le gestisca. L'SDK fornisce una serie di API per gestire questi tipi di richieste. A supporto di queste richieste, è necessario fare quanto segue:

  • Imposta MediaInformation userActionStates con le preferenze di un utente quando carica un elemento multimediale.
  • Intercetta USER_ACTION messaggi e determina l'azione richiesta.
  • Aggiorna MediaInformation UserActionState per aggiornare l'UI.

Il seguente snippet intercetta la richiesta LOAD e compila il MediaInformation di LoadRequestData. In questo caso, all'utente piacciono 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 destinatario.

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 richiesta 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 cambia lo stato del pulsante associato all'azione richiesta. Questa modifica si riflette nell'UI dei controlli degli smart display, nell'app Remote Control e nella UI di Android TV. Inoltre, viene trasmesso tramite messaggi MediaStatus in uscita per aggiornare l'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 WebRicevir 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 Vai all'elemento multimediale precedente nella coda multimediale.
Avanti Passare all'elemento multimediale successivo nella coda multimediale.
Interrompi Interrompi i contenuti multimediali attualmente in riproduzione.
Nessuna ripetizione Disattiva la ripetizione degli elementi multimediali in coda una volta terminata la riproduzione dell'ultimo elemento in coda.
Ripeti singolo Ripeti all'infinito i contenuti multimediali attualmente in riproduzione.
Ripeti tutto Ripeti tutti gli elementi in coda dopo aver riprodotto l'ultimo elemento in coda.
Ripeti tutti e Riproduzione casuale Una volta terminata la riproduzione dell'ultimo elemento in coda, riproduci la coda in ordine casuale e ripeti tutti gli elementi in coda.
Riproduzione casuale Riprodurre in ordine casuale gli elementi multimediali nella coda multimediale.
ATTIVA / DISATTIVA Sottotitoli codificati Attiva / disattiva i sottotitoli codificati per i tuoi contenuti multimediali. L'opzione Attiva / Disattiva è disponibile anche in base alla lingua.
Vai al tempo assoluto Passa al momento assoluto specificato.
Vai all'ora in relazione all'ora attuale Vai avanti o indietro del periodo di tempo specificato rispetto al tempo di riproduzione attuale.
Gioca di nuovo Riavvia i contenuti multimediali attualmente in riproduzione o riproduci l'ultimo elemento multimediale riprodotto se al momento non è in riproduzione nulla.
Impostare la velocità di riproduzione Varia la velocità di riproduzione dei contenuti multimediali. Questa opzione deve essere gestita per impostazione predefinita. Puoi utilizzare l'intercettatore di messaggi SET_PLAYBACK_RATE per eseguire l'override delle richieste di tariffe in entrata.

Comandi multimediali supportati tramite comandi vocali

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. Devi quindi applicare questi comandi abilitando la proprietà CastReceiverOptions.enforceSupportedCommands. L'UI sui mittenti dell'SDK Cast e sui dispositivi abilitati per il tocco cambierà per riflettere queste configurazioni. Se il flag non è abilitato, verranno eseguiti i comandi vocali in arrivo.

Ad esempio, se consenti PAUSE dalle applicazioni mittente e dai dispositivi abilitati per il tocco, devi anche configurare il destinatario in modo che riflettano queste impostazioni. Una volta configurati, i comandi vocali in arrivo verranno eliminati se non sono inclusi nell'elenco dei comandi supportati.

Nell'esempio riportato di seguito, viene fornito il CastReceiverOptions all'avvio di CastReceiverContext. Abbiamo aggiunto il supporto per il comando PAUSE e forzato il supporto del player solo per questo comando. Se un comando vocale richiede un'altra operazione, come SEEK, verrà rifiutata. All'utente verrà informato 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 a 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 nella tua applicazione ricevitore web.

Per i comandi multimediali non supportati dall'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;
  });

Background dell'attività vocale

Se la piattaforma di trasmissione esegue in background l'audio della tua applicazione a causa di attività dell'assistente quali l'ascolto dei comandi vocali o la conversazione, all'avvio dell'applicazione viene inviato un FocusState messaggio di NOT_IN_FOCUS. Al termine dell'attività viene inviato un altro messaggio con l'indirizzo IN_FOCUS. A seconda dell'applicazione e dei contenuti multimediali riprodotti, potresti voler mettere in pausa i contenuti multimediali quando FocusState è NOT_IN_FOCUS intercettando il tipo di messaggio FOCUS_STATE.

Ad esempio, mettere in pausa la riproduzione dell'audiolibro sarebbe una buona esperienza utente se l'assistente risponde 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 specificata dalla voce

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

Metadati e trasmissione vocale

Anche se i comandi vocali vengono gestiti per impostazione predefinita dal ricevitore web, devi assicurarti che i metadati dei tuoi contenuti siano completi e accurati. Ciò garantisce che i comandi vocali vengano gestiti correttamente dall'assistente e che i metadati vengano visualizzati correttamente nei nuovi tipi di interfacce, come l'app Google Home e gli smart display come Google Home Hub.

Trasferimento dello streaming

Conservare lo stato della sessione è la base del trasferimento dello streaming, 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 viene interrotta su un dispositivo (l'origine) e continua su un altro (la destinazione). Qualsiasi dispositivo di trasmissione con il firmware più recente può fungere da sorgente o destinazione in un trasferimento dello streaming.

Il flusso di eventi per il trasferimento dello streaming è:

  1. Sul dispositivo di origine:
    1. La riproduzione dei contenuti multimediali viene interrotta.
    2. L'applicazione WebRicevitore riceve un comando per salvare lo stato dei contenuti multimediali corrente.
    3. L'applicazione WebRicevitore è stata arrestata.
  2. Sul dispositivo di destinazione:
    1. L'applicazione WebRicevitore è stata caricata.
    2. L'applicazione WebRicevitore 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 specifica o timestamp del brano, del video o dell'elemento multimediale.
  • Deve essere inserito in una coda più ampia (ad esempio una playlist o una radio di un artista).
  • L'utente autenticato.
  • Stato di riproduzione (ad esempio riproduzione o pausa).

Abilitazione del trasferimento dello streaming in corso...

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 intercetti dei messaggi SESSION_STATE e RESUME_SESSION come descritto in Conservazione dello stato della sessione. Sostituiscile solo se devi archiviare dati personalizzati 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 ricevitore fornisce un'implementazione predefinita per le app Web receiver al fine di preservare gli stati della sessione mediante l'acquisizione di un'istantanea dello stato dei contenuti multimediali corrente, la conversione dello stato in una richiesta di caricamento e il ripristino della sessione con la richiesta di caricamento.

La richiesta di caricamento generata dal ricevitore web può essere sottoposta a override nell'intercettatore di messaggi SESSION_STATE, se necessario. Se vuoi aggiungere dati personalizzati alla richiesta di caricamento, ti suggeriamo 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 dei 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 attuale in coda.

L'operazione di precaricamento pre-scarica diversi segmenti degli elementi successivi. La specifica viene eseguita sul valore preloadTime nell'oggetto QueueItem (il valore predefinito è 20 secondi se non viene fornito). Il tempo è espresso in secondi, relativo 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 viene eseguito il prima possibile. Quindi, se viene specificato un valore molto elevato di precaricamento in codeItem, si potrebbe ottenere l'effetto di quando riproduciamo l'elemento corrente, stiamo già precaricando l'elemento successivo. Tuttavia, lasciamo lo sviluppatore all'impostazione e alla scelta di questa opzione in quanto questo valore può influire sulla larghezza di banda e sulle prestazioni di streaming dell'elemento in riproduzione corrente.

Per impostazione predefinita, il precaricamento funziona per i contenuti HLS, DASH e in streaming fluido.

I normali file video e audio MP4, ad esempio gli MP3, non verranno precaricati in quanto i dispositivi di trasmissione supportano un solo elemento multimediale e non possono essere utilizzati per precaricare mentre è ancora in corso la riproduzione di un contenuto esistente.

Messaggi personalizzati

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

Un mittente invia i messaggi a un destinatario web utilizzando le API del mittente per la piattaforma in esecuzione (Android, iOS, Web). L'oggetto evento (ovvero 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 ricevitore può scegliere di ascoltare i messaggi in uno spazio dei nomi specificato. In questo modo, si dice che l'applicazione Web Ricevitore supporti quel protocollo dello spazio dei nomi. Spetta quindi a tutti i mittenti connessi che vogliono comunicare nello spazio dei nomi usare il protocollo appropriato.

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

Ecco uno snippet di codice per consentire al ricevitore web di ascoltare i messaggi personalizzati provenienti dai 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 Web ricevitore possono mantenere i mittenti informati sullo stato del ricevitore web inviando messaggi ai mittenti connessi. Un'applicazione WebRicevitore 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 messaggi a tutti i mittenti connessi.

Trasmetti per i dispositivi audio

Consulta la guida di Google Cast per i dispositivi audio per supportare la riproduzione in modalità solo audio.

Android TV

In questa sezione viene spiegato in che modo il ricevitore web Google utilizza i tuoi input per la riproduzione e in che modo è compatibile con Android TV.

Integrazione dell'applicazione con il telecomando

Il ricevitore web Google in esecuzione sul dispositivo Android TV traduce l'input proveniente dagli ingressi di controllo del dispositivo (ovvero il telecomando portatile) come messaggi relativi alla riproduzione di contenuti multimediali definiti per lo spazio dei nomi urn:x-cast:com.google.cast.media, come descritto nella sezione Messaggi di riproduzione di contenuti multimediali. L'applicazione deve supportare questi messaggi per controllare la riproduzione dei contenuti multimediali dell'applicazione e consentire il controllo di riproduzione di base dagli ingressi di controllo di Android TV.

Linee guida per la compatibilità con Android TV

Di seguito sono riportati alcuni consigli e insidie comuni da evitare per assicurarti che la tua applicazione sia compatibile con Android TV:

  • Tieni presente che la stringa dello user agent contiene sia "Android" che "Ckubectl". 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 di dispositivi mobili.
  • 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 a tempi diversi rispetto a Chromecast, il che potrebbe rivelare problemi che sono stati nascosti su Chromecast.
  • Quando aggiorni i contenuti multimediali, usa eventi correlati ai contenuti multimediali attivati da elementi <audio>/<video>, come timeupdate, pause e waiting. Evita di utilizzare eventi di networking come progress, suspend e stalled, poiché tendono a dipendere dalla piattaforma. Consulta Eventi multimediali per ulteriori informazioni sulla gestione degli eventi multimediali nel ricevitore.
  • Quando configuri i certificati HTTPS del sito destinatario, assicurati di includere i certificati CA intermedi. Consulta la pagina di test SSL Qualsys per verificare: se il percorso di certificazione attendibile per il tuo sito include un certificato CA con l'etichetta "Download aggiuntivo", questo potrebbe non caricarsi sulle piattaforme Android.
  • Mentre Chromecast mostra la pagina del ricevitore su un piano grafico da 720p, altre piattaforme Cast, tra cui Android TV, potrebbero visualizzare la pagina fino a 1080p. Assicurati che la pagina del ricevitore venga scalata agevolmente a diverse risoluzioni.