ExoPlayer lit la plupart des flux en direct adaptatifs prêts à l'emploi, sans configuration particulière. Pour en savoir plus, consultez la page Formats acceptés.
Les diffusions en direct adaptatives offrent une fenêtre de contenus multimédias disponibles qui est mise à jour à intervalles réguliers pour refléter les changements en temps réel. Cela signifie que la position de lecture se trouvera toujours quelque part dans cette fenêtre, dans la plupart des cas, à proximité du temps réel actuel de production du flux. La différence entre le temps réel et la position de lecture actuelle est appelée décalage en direct.
Détecter et surveiller les lectures en direct
Chaque fois qu'une fenêtre en direct est mise à jour, les instances Player.Listener
enregistrées reçoivent un événement onTimelineChanged
. Vous pouvez obtenir des informations sur la lecture en direct en cours en interrogeant diverses méthodes Player
et Timeline.Window
, comme indiqué ci-dessous et illustré dans la figure suivante.
Player.isCurrentWindowLive
indique si l'élément multimédia en cours de lecture est un flux en direct. Cette valeur reste vraie même si la diffusion en direct est terminée.Player.isCurrentWindowDynamic
indique si l'élément multimédia en cours de lecture est toujours en cours de mise à jour. C'est généralement le cas pour les diffusions en direct qui ne sont pas encore terminées. Notez que, dans certains cas, cet indicateur s'applique également aux diffusions qui ne sont pas en direct.Player.getCurrentLiveOffset
renvoie le décalage entre le temps réel actuel et la position de lecture (si disponible).Player.getDuration
renvoie la durée de la fenêtre en direct actuelle.Player.getCurrentPosition
renvoie la position de lecture par rapport au début de la fenêtre en direct.Player.getCurrentMediaItem
renvoie l'élément multimédia actuel, oùMediaItem.liveConfiguration
contient des remplacements fournis par l'application pour les paramètres de décalage en direct cible et d'ajustement de décalage en direct.Player.getCurrentTimeline
renvoie la structure multimédia actuelle dans unTimeline
. LeTimeline.Window
actuel peut être récupéré à partir deTimeline
à l'aide dePlayer.getCurrentWindowIndex
et deTimeline.getWindow
. DansWindow
:Window.liveConfiguration
contient les paramètres de décalage en direct cible et d'ajustement du décalage en direct. Ces valeurs sont basées sur les informations du contenu multimédia et sur les forçages fournis par l'application définis dansMediaItem.liveConfiguration
.Window.windowStartTimeMs
est l'heure à laquelle la fenêtre en direct commence depuis l'epoch Unix.Window.getCurrentUnixTimeMs
est le temps écoulé depuis l'epoch Unix de la période actuelle. Cette valeur peut être corrigée par une différence d'horloge connue entre le serveur et le client.Window.getDefaultPositionMs
correspond à la position par défaut du lecteur dans la fenêtre en direct.
Rechercher dans les diffusions en direct
Vous pouvez rechercher n'importe où dans la fenêtre en direct avec Player.seekTo
. La position de recherche transmise dépend du début de la fenêtre en direct. Par exemple, seekTo(0)
recherche le début de la fenêtre en direct. Le joueur tente de conserver le même décalage en direct que la position recherchée après une recherche.
La fenêtre en direct possède également une position par défaut à laquelle la lecture est censée commencer. Cette position se trouve généralement quelque part près du bord direct. Vous pouvez rechercher la position par défaut en appelant Player.seekToDefaultPosition
.
UI de lecture en direct
Les composants d'interface utilisateur par défaut d'ExoPlayer affichent la durée de la fenêtre en direct et la position de lecture actuelle dans celle-ci. Cela signifie que la position semble reculer chaque fois que la fenêtre en direct est mise à jour. Si vous avez besoin d'un comportement différent, par exemple pour afficher l'heure Unix ou le décalage en direct actuel, vous pouvez dupliquer PlayerControlView
et le modifier en fonction de vos besoins.
Configurer les paramètres de lecture en direct
ExoPlayer utilise certains paramètres pour contrôler le décalage de la position de lecture par rapport au bord direct, ainsi que la plage de vitesses de lecture pouvant être utilisée pour ajuster ce décalage.
ExoPlayer obtient les valeurs de ces paramètres à partir de trois emplacements, par ordre de priorité décroissante (la première valeur trouvée est utilisée):
- Valeurs pour
MediaItem
transmises àMediaItem.Builder.setLiveConfiguration
. - Valeurs globales par défaut définies sur
DefaultMediaSourceFactory
. - Valeurs lues directement depuis le contenu multimédia.
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);
Les valeurs de configuration disponibles sont les suivantes:
targetOffsetMs
: décalage en direct cible. Si possible, le lecteur tente de se rapprocher de ce décalage en direct lors de la lecture.minOffsetMs
: décalage en direct minimal autorisé. Même lorsque vous ajustez le décalage en fonction des conditions actuelles du réseau, le lecteur ne tente pas de passer en dessous de ce décalage pendant la lecture.maxOffsetMs
: décalage en direct maximal autorisé. Même lorsque vous ajustez le décalage en fonction des conditions actuelles du réseau, le lecteur ne tente pas de dépasser ce décalage pendant la lecture.minPlaybackSpeed
: vitesse de lecture minimale que le lecteur peut utiliser pour revenir en arrière lorsqu'il tente d'atteindre le décalage en direct cible.maxPlaybackSpeed
: vitesse de lecture maximale que le lecteur peut rattraper lorsqu'il tente d'atteindre le décalage en direct cible.
Ajustement de la vitesse de lecture
Lors de la lecture d'une diffusion en direct à faible latence, ExoPlayer ajuste le décalage en direct en modifiant légèrement la vitesse de lecture. Le lecteur tente de correspondre au décalage en direct cible fourni par le contenu multimédia ou l'application, mais tente également de réagir à l'évolution des conditions du réseau. Par exemple, en cas de remise en mémoire tampon pendant la lecture, le lecteur ralentit légèrement la lecture pour s'éloigner du bord en direct. Si le réseau redevient suffisamment stable pour permettre la lecture plus près du bord en direct, le lecteur accélère la lecture pour revenir vers le décalage cible en direct.
Si vous ne souhaitez pas ajuster automatiquement la vitesse de lecture, vous pouvez le désactiver en définissant les propriétés minPlaybackSpeed
et maxPlaybackSpeed
sur 1.0f
.
De même, vous pouvez l'activer pour les diffusions en direct à faible latence en les définissant explicitement sur des valeurs autres que 1.0f
. Consultez la section de configuration ci-dessus pour en savoir plus sur la manière de définir ces propriétés.
Personnaliser l'algorithme de réglage de la vitesse de lecture
Si l'ajustement de la vitesse est activé, LivePlaybackSpeedControl
définit les ajustements qui sont effectués. Il est possible d'implémenter un LivePlaybackSpeedControl
personnalisé ou de personnaliser l'implémentation par défaut, à savoir DefaultLivePlaybackSpeedControl
. Dans les deux cas, une instance peut être définie lors de la création du lecteur:
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();
Les paramètres de personnalisation pertinents de DefaultLivePlaybackSpeedControl
sont les suivants:
fallbackMinPlaybackSpeed
etfallbackMaxPlaybackSpeed
: vitesses de lecture minimale et maximale pouvant être utilisées pour l'ajustement si aucun contenu multimédia niMediaItem
fourni par l'application ne définissent de limites.proportionalControlFactor
: contrôle la fluidité de l'ajustement de la vitesse. Une valeur élevée rend les ajustements plus soudains et réactifs, mais également plus susceptibles d'être audibles. Une valeur inférieure permet une transition plus fluide entre les vitesses, mais au prix d'un ralentissement.targetLiveOffsetIncrementOnRebufferMs
: cette valeur est ajoutée au décalage en temps réel cible chaque fois qu'une remise en mémoire tampon se produit, afin d'être plus prudente. Cette fonctionnalité peut être désactivée en définissant la valeur sur 0.minPossibleLiveOffsetSmoothingFactor
: facteur de lissage exponentiel utilisé pour suivre le décalage en direct minimal possible en fonction du média actuellement mis en mémoire tampon. Une valeur très proche de 1 signifie que l'estimation est plus prudente et peut prendre plus de temps pour s'adapter à l'amélioration des conditions du réseau, tandis qu'une valeur inférieure indique que l'estimation s'ajuste plus rapidement, ce qui augmente le risque de remise en mémoire tampon.
BehindLiveWindowException et ERROR_CODE_DR_LIVE_WINDOW
La position de lecture peut être en retard par rapport à la fenêtre en direct, par exemple si le lecteur est mis en pause ou met en mémoire tampon pendant une période suffisamment longue. Dans ce cas, la lecture échouera et une exception avec le code d'erreur ERROR_CODE_BEHIND_LIVE_WINDOW
sera signalée via Player.Listener.onPlayerError
. Le code de l'application peut souhaiter gérer ces erreurs en reprenant la lecture à la position par défaut. La propriété PlayerActivity de l'application de démonstration illustre cette approche.
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 } }