Live streaming

ExoPlayer riproduce subito la maggior parte dei live streaming adattivi senza bisogno di nessuna configurazione speciale. Per ulteriori dettagli, consulta la pagina Formati supportati.

I live streaming adattivi offrono una finestra dei contenuti multimediali disponibili che vengono aggiornati a intervalli regolari per essere aggiornati in base all'attuale versione in tempo reale. Ciò significa che la posizione di riproduzione sarà sempre in qualsiasi punto di questa finestra, nella maggior parte dei casi vicino all'attuale tempo reale in cui lo stream è prodotto. La differenza tra l'attuale tempo in tempo reale e la posizione di riproduzione viene chiamata offset dal vivo.

Rilevamento e monitoraggio delle riproduzioni dal vivo

Ogni volta che viene aggiornata una finestra dal vivo, le istanze Player.Listener registrate riceveranno un evento onTimelineChanged. Puoi recuperare informazioni dettagliate sulla riproduzione dal vivo corrente eseguendo una query su vari metodi Player e Timeline.Window come elencato di seguito e mostrato nella figura che segue.

Finestra in diretta

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

Ricerca nei live streaming

Puoi spostarti ovunque all'interno della finestra dal vivo utilizzando Player.seekTo. La posizione di ricerca passata è relativa all'inizio della finestra di pubblicazione. Ad esempio, seekTo(0) cercherà all'inizio della finestra Dal vivo. Il player cercherà di mantenere lo stesso offset live della posizione desiderata dopo una ricerca.

La finestra Dal vivo ha anche una posizione predefinita da cui dovrebbe iniziare la riproduzione. Questa posizione di solito si trova vicino al bordo attivo. Puoi cercare la posizione predefinita chiamando Player.seekToDefaultPosition.

UI Riproduzione dal vivo

I componenti predefiniti dell'interfaccia utente di ExoPlayer mostrano la durata della finestra dal vivo e la posizione di riproduzione corrente al suo interno. Ciò significa che la posizione verrà saltata indietro ogni volta che la finestra dal vivo viene aggiornata. Se hai bisogno di un comportamento diverso, ad esempio mostrare l'ora Unix o l'offset attuale, puoi creare un fork di PlayerControlView e modificarlo in base alle tue esigenze.

Configurare i parametri per la riproduzione dal vivo

ExoPlayer utilizza alcuni parametri per controllare l'offset della posizione di riproduzione dal bordo dal vivo e l'intervallo di velocità di riproduzione che possono essere utilizzate per regolare questo offset.

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

  • Valori per MediaItem trasmessi 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 di pubblicazione target. Il player cercherà di avvicinarsi a questo offset live durante la riproduzione, se possibile.
  • minOffsetMs: l'offset live streaming minimo consentito. Anche quando regoli l'offset alle condizioni di rete attuali, il player non tenterà di scendere al di sotto di questo offset durante la riproduzione.
  • maxOffsetMs: l'offset live streaming massimo consentito. Anche quando regoli l'offset alle condizioni attuali della rete, il player non tenterà di superare questo offset durante la riproduzione.
  • minPlaybackSpeed: la velocità di riproduzione minima che il player può utilizzare per tornare indietro quando cerca di raggiungere l'offset dal vivo target.
  • maxPlaybackSpeed: la velocità di riproduzione massima che il player può utilizzare per recuperare quando cerca di raggiungere l'offset di live streaming target.

Regolazione della velocità di riproduzione

Durante la riproduzione di un live streaming a bassa latenza, ExoPlayer regola l'offset dal vivo modificando leggermente la velocità di riproduzione. Il player cercherà di raggiungere l'offset del live streaming target fornito dal contenuto multimediale o dall'app, ma tenterà anche di reagire alle variazioni delle condizioni della rete. Ad esempio, se si verificano rebuffer durante la riproduzione, il player rallenterà leggermente la riproduzione per allontanarsi dal bordo della riproduzione. Se la rete diventa abbastanza stabile da supportare nuovamente la riproduzione più vicino al limite live, il player velocizza la riproduzione per tornare all'offset di live streaming target.

Se non vuoi la regolazione automatica della velocità di riproduzione, puoi disattivarla impostando le proprietà minPlaybackSpeed e maxPlaybackSpeed su 1.0f. Analogamente, può essere abilitata per i live streaming a non bassa latenza impostandoli esplicitamente su valori diversi da 1.0f. Consulta la sezione sulla configurazione sopra per ulteriori dettagli su come impostare queste proprietà.

Personalizzare l'algoritmo di regolazione della velocità di riproduzione

Se la regolazione della velocità è attivata, un LivePlaybackSpeedControl definisce quali regolazioni vengono apportate. È possibile implementare un elemento LivePlaybackSpeedControl personalizzato o personalizzare l'implementazione predefinita, ovvero DefaultLivePlaybackSpeedControl. In entrambi i casi, è possibile impostare un'istanza durante la creazione 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é gli MediaItem forniti dall'app definiscono dei limiti.
  • proportionalControlFactor: controlla il livello di fluidità della regolazione della velocità. Un valore elevato rende le regolazioni più improvvise e reattive, ma anche più udibili. Un valore inferiore determina una transizione più fluida tra le velocità, a costo di una minore velocità.
  • targetLiveOffsetIncrementOnRebufferMs: questo valore viene aggiunto all'offset in tempo reale target ogni volta che si verifica un rebuffer, per procedere con maggiore cautela. Questa funzionalità può essere disattivata impostando il valore su 0.
  • minPossibleLiveOffsetSmoothingFactor: un fattore di livellamento esponenziale che viene utilizzato per tenere traccia dell'offset di live streaming minimo possibile in base ai contenuti multimediali attualmente inseriti nel buffer. Un valore molto vicino a 1 indica che la stima è più cauta e potrebbe richiedere più tempo per adattarsi alle condizioni di rete migliorate, mentre un valore più basso significa che la stima si adatterà più velocemente con un rischio maggiore di eseguire rebuffer.

BehindLiveWindowException e ERROR_CODE_Behind_LIVE_WINDOW

La posizione di riproduzione potrebbe rimanere indietro rispetto alla finestra di live streaming, ad esempio se il player è in pausa o se esegue il 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 voler gestire questi errori ripristinando la riproduzione nella posizione predefinita. La proprietà PlayerActivity dell'app demo è 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
  }
}