ExoPlayer riproduce la maggior parte dei live streaming adattivi 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 seguire l'andamento in tempo reale. Ciò significa che la posizione di riproduzione sarà sempre all'interno di questa finestra, nella maggior parte dei casi vicino al tempo reale attuale in cui viene prodotto lo stream. La differenza tra la posizione di riproduzione e la posizione in tempo reale attuale è chiamata offset live.
Rilevare e monitorare le riproduzioni live
Ogni volta che una finestra live viene aggiornata, le istanze Player.Listener registrate
riceveranno un evento onTimelineChanged. Puoi recuperare i dettagli sulla
riproduzione live corrente eseguendo query su vari metodi Player e Timeline.Window, come elencato di seguito e mostrato nella figura seguente.

Player.isCurrentWindowLiveindica se l'elemento multimediale attualmente in riproduzione è un live streaming. Questo valore è ancora valido anche se il live streaming è terminato.Player.isCurrentWindowDynamicindica se l'elemento multimediale attualmente in riproduzione è ancora in fase di aggiornamento. Questo vale in genere per i live streaming che non sono ancora terminati. Tieni presente che questo flag è vero anche per i contenuti non in live streaming in alcuni casi.Player.getCurrentLiveOffsetrestituisce l'offset tra l'ora in tempo reale corrente e la posizione di riproduzione (se disponibile).Player.getDurationrestituisce la durata della finestra live corrente.Player.getCurrentPositionrestituisce la posizione di riproduzione relativa all'inizio della finestra live.Player.getCurrentMediaItemrestituisce l'elemento multimediale corrente, doveMediaItem.liveConfigurationcontiene gli override forniti dall'app per i parametri di offset live e di aggiustamento dell'offset live di destinazione.Player.getCurrentTimelinerestituisce la struttura dei media corrente in unTimeline. L'Timeline.Windowcorrente può essere recuperato daTimelineutilizzandoPlayer.getCurrentMediaItemIndexeTimeline.getWindow. All'interno diWindow:Window.liveConfigurationcontiene i parametri di offset live di destinazione e di aggiustamento dell'offset live. Questi valori si basano sulle informazioni nei contenuti multimediali e su eventuali override forniti dall'app impostati inMediaItem.liveConfiguration.Window.windowStartTimeMsè il tempo trascorso dall'epoca Unix in cui inizia la finestra live.Window.getCurrentUnixTimeMsè il tempo trascorso dall'epoca Unix dell'ora in tempo reale corrente. Questo valore può essere corretto in base a una differenza di orologio nota tra il server e il client.Window.getDefaultPositionMsè la posizione nella finestra live in cui il player avvierà la riproduzione per impostazione predefinita.
Ricerca nei live streaming
Puoi spostarti in qualsiasi punto della finestra live utilizzando Player.seekTo. La posizione
di ricerca passata è relativa all'inizio della finestra live. Ad esempio,
seekTo(0) andrà all'inizio della finestra live. Il player tenterà di
mantenere lo stesso offset live della posizione raggiunta dopo una ricerca.
La finestra live ha anche una posizione predefinita in cui la riproduzione dovrebbe
iniziare. Questa posizione si trova di solito vicino al bordo vivo. Puoi tornare
alla posizione predefinita chiamando il numero Player.seekToDefaultPosition.
UI di riproduzione live
I componenti UI predefiniti di ExoPlayer mostrano la durata della finestra live e
la posizione di riproduzione corrente al suo interno. Ciò significa che la posizione sembrerà
saltare indietro ogni volta che la finestra live viene aggiornata. Se hai bisogno di un comportamento diverso, ad esempio mostrare l'ora Unix o l'offset live corrente, puoi creare un fork di PlayerControlView e modificarlo in base alle tue esigenze.
Configurazione dei parametri di riproduzione live
ExoPlayer utilizza alcuni parametri per controllare l'offset della posizione di riproduzione dal bordo live e l'intervallo di velocità di riproduzione che possono essere utilizzati per regolare questo offset.
ExoPlayer ottiene i valori di questi parametri da tre posizioni, in ordine di priorità decrescente (viene utilizzato il primo valore trovato):
- Per
MediaItemvalori passati aMediaItem.Builder.setLiveConfiguration. - Valori predefiniti globali impostati il giorno
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 live di destinazione. Il player tenterà di avvicinarsi a questo offset live durante la riproduzione, se possibile.minOffsetMs: l'offset live minimo consentito. Anche quando si regola l'offset in base alle condizioni di rete attuali, il player non tenterà di scendere al di sotto di questo offset durante la riproduzione.maxOffsetMs: l'offset live massimo consentito. Anche quando si regola 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 fallback quando tenta di raggiungere l'offset live di destinazione.maxPlaybackSpeed: la velocità di riproduzione massima che il player può utilizzare per recuperare quando tenta di raggiungere l'offset live target.
Regolazione della velocità di riproduzione
Quando riproduce un live streaming a bassa latenza, ExoPlayer regola l'offset live modificando leggermente la velocità di riproduzione. Il player tenterà di abbinare l'offset live di destinazione fornito dai contenuti multimediali o dall'app, ma cercherà anche di reagire alle condizioni di rete variabili. Ad esempio, se si verificano ribuffer durante la riproduzione, il player rallenterà leggermente la riproduzione per allontanarsi ulteriormente dal bordo live. Se la rete diventa di nuovo sufficientemente stabile per supportare la riproduzione più vicina al bordo live, il player velocizzerà la riproduzione per tornare verso l'offset live di destinazione.
Se non vuoi la regolazione automatica della velocità di riproduzione, puoi disattivarla
impostando le proprietà minPlaybackSpeed e maxPlaybackSpeed su 1.0f.
Analogamente, può essere abilitato per i live streaming non a bassa latenza impostando questi valori
in modo esplicito su valori diversi da 1.0f. Per
maggiori dettagli su come impostare queste proprietà, consulta
la sezione di configurazione precedente.
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 LivePlaybackSpeedControl personalizzato o personalizzare l'implementazione predefinita, ovvero DefaultLivePlaybackSpeedControl. In entrambi i casi, è possibile impostare un'istanza durante la creazione del giocatore:
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:
fallbackMinPlaybackSpeedefallbackMaxPlaybackSpeed: la velocità di riproduzione minima e massima che può essere utilizzata per la regolazione se né i contenuti multimediali né l'app fornitaMediaItemdefiniscono limiti.proportionalControlFactor: controlla la fluidità della regolazione della velocità. Un valore elevato rende le regolazioni più improvvise e reattive, ma anche più probabile che siano udibili. Un valore più basso comporta una transizione più fluida tra le velocità, a discapito della velocità.targetLiveOffsetIncrementOnRebufferMs: questo valore viene aggiunto all'offset live di destinazione 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 utilizzato per monitorare l'offset live minimo possibile in base ai contenuti multimediali attualmente memorizzati nel buffer. Un valore molto vicino a 1 indica che la stima è più cauta e potrebbe richiedere più tempo per adattarsi alle migliori condizioni di rete, mentre un valore più basso indica che la stima si adatterà più rapidamente con un rischio maggiore di incorrere in ribuffer.
BehindLiveWindowException e ERROR_CODE_BEHIND_LIVE_WINDOW
La posizione di riproduzione potrebbe rimanere indietro rispetto alla finestra live, 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 voler gestire questi
errori riprendendo la riproduzione dalla posizione predefinita. L'attività del giocatore dell'app demo esemplifica 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 } }