Streaming en direct

ExoPlayer lit la plupart des diffusions en direct adaptatives prêtes à l'emploi, sans aucune configuration spéciale. 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 suivre l'actualité en temps réel. Cela signifie que la position de lecture sera toujours quelque part dans cette fenêtre, dans la plupart des cas proche du temps réel actuel à partir duquel le flux est produit. La différence entre le temps réel actuel et la position de lecture 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 récupérer 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.

Fenêtre en direct

  • Player.isCurrentWindowLive indique si l'élément multimédia en cours de lecture est une diffusion en direct. Cette valeur est toujours 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 est également vrai pour les flux non en direct.
  • Player.getCurrentLiveOffset renvoie le décalage entre le temps réel actuel et la position de lecture (le cas échéant).
  • Player.getDuration renvoie la longueur de la fenêtre en direct actuelle.
  • Player.getCurrentPosition renvoie la position de lecture par rapport au début de la fenêtre de diffusion en direct.
  • Player.getCurrentMediaItem renvoie l'élément multimédia actuel, où MediaItem.liveConfiguration contient des forçages fournis par l'application pour les paramètres de décalage en direct cible et d'ajustement du décalage en direct.
  • Player.getCurrentTimeline renvoie la structure multimédia actuelle dans un Timeline. Le Timeline.Window actuel peut être récupéré à partir du Timeline à l'aide de Player.getCurrentMediaItemIndex et Timeline.getWindow. Dans Window :
    • 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 des contenus multimédias et sur les forçages fournis par l'application définis dans MediaItem.liveConfiguration.
    • Window.windowStartTimeMs est le temps écoulé depuis l'époque Unix à laquelle la fenêtre en direct commence.
    • Window.getCurrentUnixTimeMs est le temps écoulé depuis l'époque Unix du temps réel actuel. Cette valeur peut être corrigée par une différence de horloge connue entre le serveur et le client.
    • Window.getDefaultPositionMs correspond à la position dans la fenêtre de diffusion en direct à partir de laquelle le lecteur commencera la lecture par défaut.

Rechercher dans les diffusions en direct

Vous pouvez rechercher n'importe quel point dans la fenêtre en direct à l'aide de Player.seekTo. La position de recherche transmise est relative au début de la fenêtre en direct. Par exemple, seekTo(0) permet d'accéder au début de la période de diffusion en direct. Le lecteur tentera de conserver le même décalage en direct que la position de recherche après une recherche.

La fenêtre de diffusion en direct comporte également une position par défaut à partir de laquelle la lecture doit commencer. Cette position se situe généralement près du bord actif. Vous pouvez rechercher la position par défaut en appelant Player.seekToDefaultPosition.

UI de la 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 du direct est mise à jour. Si vous avez besoin d'un comportement différent, par exemple pour afficher l'heure Unix ou le décalage actuel en temps réel, 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 en direct et la plage de vitesses de lecture pouvant être utilisées 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 MediaItem transmises à MediaItem.Builder.setLiveConfiguration.
  • Valeurs globales par défaut définies sur DefaultMediaSourceFactory.
  • Valeurs lues directement à partir du 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 temporel en direct cible. Si possible, le lecteur tente de se rapprocher de ce décalage en direct pendant la lecture.
  • minOffsetMs: décalage en direct minimal autorisé. Même en ajustant le décalage en fonction des conditions réseau actuelles, le lecteur ne tentera pas de descendre en dessous de ce décalage pendant la lecture.
  • maxOffsetMs: décalage en direct maximal autorisé. Même en ajustant le décalage en fonction des conditions réseau actuelles, le lecteur ne tentera 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 utiliser pour rattraper son retard 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 tentera de correspondre au décalage en direct cible fourni par le contenu multimédia ou l'application, mais tentera également de réagir aux conditions réseau changeantes. Par exemple, si des rebuffers se produisent pendant la lecture, le lecteur ralentit légèrement la lecture pour s'éloigner davantage de la limite en direct. Si le réseau devient suffisamment stable pour permettre de lire à nouveau plus près du seuil, le lecteur accélère la lecture pour revenir vers le décalage en direct cible.

Si vous ne souhaitez pas que la vitesse de lecture soit automatiquement ajustée, vous pouvez la désactiver en définissant les propriétés minPlaybackSpeed et maxPlaybackSpeed sur 1.0f. De même, vous pouvez l'activer pour les flux en direct à faible latence en les définissant explicitement sur des valeurs autres que 1.0f. Pour en savoir plus sur la configuration de ces propriétés, consultez la section de configuration ci-dessus.

Personnaliser l'algorithme d'ajustement de la vitesse de lecture

Si l'ajustement de la vitesse est activé, un LivePlaybackSpeedControl définit les ajustements 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 et fallbackMaxPlaybackSpeed: vitesses de lecture minimale et maximale pouvant être utilisées pour l'ajustement si ni le contenu multimédia ni le MediaItem 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 plus réactifs, mais aussi plus susceptibles d'être audibles. Une valeur plus faible permet une transition plus fluide entre les vitesses, mais au détriment de la vitesse.
  • targetLiveOffsetIncrementOnRebufferMs: cette valeur est ajoutée au décalage en direct cible chaque fois qu'un rebuffering se produit, afin de procéder plus prudemment. Cette fonctionnalité peut être désactivée en définissant la valeur sur 0.
  • minPossibleLiveOffsetSmoothingFactor: facteur d'atténuation exponentielle utilisé pour suivre le décalage en direct minimal possible en fonction du contenu multimé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 faible signifie que l'estimation s'ajustera plus rapidement, avec un risque plus élevé de disposer de nouvelles mémoires tampons.

BehindLiveWindowException et ERROR_CODE_BEHIND_LIVE_WINDOW

La position de lecture peut être en retard par rapport à la fenêtre de diffusion en direct, par exemple si le lecteur est mis en pause ou en mémoire tampon pendant une période suffisamment longue. Dans ce cas, la lecture échoue et une exception avec le code d'erreur ERROR_CODE_BEHIND_LIVE_WINDOW est signalée via Player.Listener.onPlayerError. Le code de l'application peut 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
  }
}