Live streaming

ExoPlayer riproduce la maggior parte dei live streaming adattabili senza alcuna configurazione speciale. Per maggiori dettagli, consulta la pagina Formati supportati.

I live streaming adattivi offrono una finestra di contenuti multimediali disponibili che viene aggiornata a intervalli regolari per adattarsi all'evoluzione in tempo reale. Ciò significa che la posizione di riproduzione sarà sempre in questa finestra, nella maggior parte dei casi vicino al tempo reale corrente in cui viene prodotto lo stream. La differenza tra il tempo in tempo reale corrente e la posizione di riproduzione è chiamata offset dal live.

Rilevamento e monitoraggio delle riproduzioni in tempo reale

Ogni volta che una finestra in tempo reale viene aggiornata, le istanze Player.Listener registrate riceveranno un evento onTimelineChanged. Puoi recuperare i dettagli sulla riproduzione in diretta corrente eseguendo query su vari metodi Player e Timeline.Window, come elencato di seguito e mostrato nella figura seguente.

Finestra in tempo reale

  • Player.isCurrentWindowLive indica se l'elemento media attualmente in riproduzione è un live streaming. Questo valore rimane valido anche se il live streaming è terminato.
  • Player.isCurrentWindowDynamic indica se l'elemento multimediale attualmente in riproduzione è ancora in fase di aggiornamento. Questo è in genere il caso dei live streaming che non sono ancora terminati. Tieni presente che in alcuni casi questo flag è valido anche per i live streaming non in diretta.
  • Player.getCurrentLiveOffset restituisce l'offset tra il tempo reale corrente e la posizione di riproduzione (se disponibile).
  • Player.getDuration restituisce la lunghezza della finestra live corrente.
  • Player.getCurrentPosition restituisce la posizione di riproduzione rispetto all'inizio della finestra live.
  • Player.getCurrentMediaItem restituisce l'elemento multimediale corrente, dove MediaItem.liveConfiguration contiene le sostituzioni fornite dall'app per i parametri di offset in diretta e di aggiustamento dell'offset in diretta target.
  • Player.getCurrentTimeline restituisce la struttura multimediale corrente in un Timeline. L'Timeline.Window corrente può essere recuperato dal Timeline utilizzando Player.getCurrentMediaItemIndex e Timeline.getWindow. All'interno di Window:
    • Window.liveConfiguration contiene i parametri di aggiustamento dell'offset live target e dell'offset live. Questi valori si basano sulle informazioni nei contenuti multimediali e sugli eventuali override forniti dall'app impostati in MediaItem.liveConfiguration.
    • Window.windowStartTimeMs è il tempo dall'epoca Unix in cui inizia la finestra in diretta.
    • Window.getCurrentUnixTimeMs è il tempo trascorso dall'epoca Unix del tempo reale attuale. Questo valore può essere corretto da una differenza di orologio nota tra il server e il client.
    • Window.getDefaultPositionMs è la posizione nella finestra del live streaming in cui il player avvia la riproduzione per impostazione predefinita.

Avanzamento nei live streaming

Puoi andare a qualsiasi punto all'interno della finestra in diretta utilizzando Player.seekTo. La posizione di ricerca passata è relativa all'inizio dell'intervallo live. Ad esempio, seekTo(0) cercherà fino all'inizio della finestra pubblicata. Dopo una ricerca, il player cercherà di mantenere lo stesso offset in tempo reale della posizione di ricerca.

La finestra live ha anche una posizione predefinita in cui dovrebbe iniziare la riproduzione. Questa posizione si trova in genere vicino al bordo attivo. Puoi andare alla posizione predefinita chiamando Player.seekToDefaultPosition.

Interfaccia utente della riproduzione in diretta

I componenti dell'interfaccia utente predefiniti di ExoPlayer mostrano la durata della finestra live e la posizione di riproduzione corrente al suo interno. Ciò significa che la posizione sembrerà fare un salto all'indietro ogni volta che la finestra in tempo reale viene aggiornata. Se hai bisogno di un comportamento diverso, ad esempio per mostrare il tempo Unix o l'offset in tempo reale corrente, puoi creare un fork di PlayerControlView e modificarlo in base alle tue esigenze.

Configurare i parametri di riproduzione dal vivo

ExoPlayer utilizza alcuni parametri per controllare l'offset della posizione di riproduzione dall'edge live e l'intervallo di velocità di riproduzione che possono essere utilizzati per regolare questo offset.

ExoPlayer recupera i valori per questi parametri da tre posizioni, in ordine di priorità decrescente (viene utilizzato il primo valore trovato):

  • Per i valori MediaItem passati a MediaItem.Builder.setLiveConfiguration.
  • Valori predefiniti globali impostati su DefaultMediaSourceFactory.
  • Valori letti direttamente dai contenuti multimediali.

Kotlin

// Global settings.
val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
    .build()

// Per MediaItem settings.
val mediaItem =
  MediaItem.Builder()
    .setUri(mediaUri)
    .setLiveConfiguration(
      MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build()
    )
    .build()
player.setMediaItem(mediaItem)

Java

// Global settings.
ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context).setLiveTargetOffsetMs(5000))
        .build();

// Per MediaItem settings.
MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(mediaUri)
        .setLiveConfiguration(
            new MediaItem.LiveConfiguration.Builder().setMaxPlaybackSpeed(1.02f).build())
        .build();
player.setMediaItem(mediaItem);

I valori di configurazione disponibili sono:

  • targetOffsetMs: l'offset dal live target. Se possibile, il player cercherà di avvicinarsi a questo offset in tempo reale durante la riproduzione.
  • minOffsetMs: la differenza minima consentita in tempo reale. Anche se l'offset viene modificato in base alle condizioni di rete attuali, il player non tenterà di scendere al di sotto di questo offset durante la riproduzione.
  • maxOffsetMs: la differenza massima consentita in tempo reale. Anche se regoli l'offset in base alle condizioni di rete attuali, il player non tenterà di superare questo offset durante la riproduzione.
  • minPlaybackSpeed: la velocità di riproduzione minima che il player può utilizzare come opzione di riserva quando tenta di raggiungere lo spostamento in tempo reale target.
  • maxPlaybackSpeed: la velocità di riproduzione massima che il player può utilizzare per mettersi al passo quando tenta di raggiungere lo spostamento dal live target.

Regolazione della velocità di riproduzione

Quando riproduci un live streaming a bassa latenza, ExoPlayer regola l'offset in tempo reale modificando leggermente la velocità di riproduzione. Il player cercherà di corrispondere all'offset in tempo reale del target fornito dai contenuti multimediali o dall'app, ma cercherà anche di reagire alle condizioni mutevoli della rete. Ad esempio, se si verificano nuovi buffering durante la riproduzione, il player rallenta leggermente la riproduzione per allontanarsi dal live streaming. Se la rete diventa sufficientemente stabile da supportare di nuovo la riproduzione più vicino al live streaming, il player accelera la riproduzione per tornare all'offset dal live streaming target.

Se non vuoi che la velocità di riproduzione venga regolata automaticamente, puoi disattivarla impostando le proprietà minPlaybackSpeed e maxPlaybackSpeed su 1.0f. Analogamente, può essere attivato per i live streaming con latenza non bassa impostandoli esplicitamente su valori diversi da 1.0f. Per maggiori dettagli su come impostare queste proprietà, consulta la sezione sulla configurazione sopra.

Personalizzazione dell'algoritmo di regolazione della velocità di riproduzione

Se la regolazione della velocità è attivata, un LivePlaybackSpeedControl definisce gli aggiustamenti da apportare. È possibile implementare un valore personalizzatoLivePlaybackSpeedControl o personalizzare l'implementazione predefinita, ovveroDefaultLivePlaybackSpeedControl. In entrambi i casi, è possibile impostare un'istanza durante la compilazione del player:

Kotlin

val player =
  ExoPlayer.Builder(context)
    .setLivePlaybackSpeedControl(
      DefaultLivePlaybackSpeedControl.Builder().setFallbackMaxPlaybackSpeed(1.04f).build()
    )
    .build()

Java

ExoPlayer player =
    new ExoPlayer.Builder(context)
        .setLivePlaybackSpeedControl(
            new DefaultLivePlaybackSpeedControl.Builder()
                .setFallbackMaxPlaybackSpeed(1.04f)
                .build())
        .build();

I parametri di personalizzazione pertinenti di DefaultLivePlaybackSpeedControl sono:

  • fallbackMinPlaybackSpeed e fallbackMaxPlaybackSpeed: le velocità di riproduzione minime e massime che possono essere utilizzate per la regolazione se né i contenuti multimediali né il MediaItem fornito dall'app definiscono i limiti.
  • proportionalControlFactor: controlla la fluidità della regolazione della velocità. Un valore elevato rende gli aggiustamenti più improvvisi e reattivi, ma anche più probabili di essere udibili. Un valore inferiore consente una transizione più fluida tra le velocità, ma al costo di essere più lenta.
  • targetLiveOffsetIncrementOnRebufferMs: questo valore viene aggiunto all'offset dal vivo target ogni volta che si verifica un nuovo buffering, per procedere con maggiore cautela. Questa funzionalità può essere disattivata impostando il valore su 0.
  • minPossibleLiveOffsetSmoothingFactor: un fattore di smorzamento esponenziale utilizzato per monitorare l'offset in tempo reale minimo possibile in base ai contenuti multimediali attualmente memorizzati nella cache. Un valore molto vicino a 1 indica che la stima è più prudente e potrebbe richiedere più tempo per adattarsi al miglioramento delle condizioni di rete, mentre un valore più basso significa che la stima si adegua più rapidamente, con un rischio maggiore di immettere rebuffer.

dietroLiveWindowException e ERROR_CODE_ {8/}_LIVE_WINDOW

La posizione di riproduzione potrebbe rimanere indietro rispetto alla finestra del live streaming, ad esempio se il player è in pausa o è in buffering per un periodo di tempo sufficientemente lungo. In questo caso, la riproduzione non andrà a buon fine e verrà segnalata un'eccezione con il codice di errore ERROR_CODE_BEHIND_LIVE_WINDOW tramite Player.Listener.onPlayerError. Il codice dell'applicazione potrebbe gestire questi errori riprendendo la riproduzione dalla posizione predefinita. PlayerActivity dell'app dimostrativa è un esempio di questo approccio.

Kotlin

override fun onPlayerError(error: PlaybackException) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition()
    player.prepare()
  } else {
    // Handle other errors
  }
}

Java

@Override
public void onPlayerError(PlaybackException error) {
  if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the live edge.
    player.seekToDefaultPosition();
    player.prepare();
  } else {
    // Handle other errors
  }
}