Retrieving metadata

During playback

The metadata of the media can be retrieved during playback in multiple ways. The most straightforward is to listen for the Player.Listener#onMediaMetadataChanged event; this will provide a MediaMetadata object for use, which has fields such as title and albumArtist. Alternatively, calling Player#getMediaMetadata returns the same object.

Kotlin

override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
  mediaMetadata.title?.let(::handleTitle)
}

Java

@Override
public void onMediaMetadataChanged(MediaMetadata mediaMetadata) {
  if (mediaMetadata.title != null) {
    handleTitle(mediaMetadata.title);
  }
}

If your app needs access to specific Metadata.Entry objects, then it should listen to Player.Listener#onMetadata (for dynamic metadata delivered during playback). Alternatively, if there is a need to look at static metadata, this can be accessed through the TrackSelections#getFormat. Player#getMediaMetadata is populated from both of these sources.

Without playback

If playback is not needed, it is more efficient to use the MetadataRetriever to extract the metadata because it avoids having to create and prepare a player.

Kotlin

val trackGroupsFuture = MetadataRetriever.retrieveMetadata(context, mediaItem)
Futures.addCallback(
  trackGroupsFuture,
  object : FutureCallback<TrackGroupArray?> {
    override fun onSuccess(trackGroups: TrackGroupArray?) {
      if (trackGroups != null) handleMetadata(trackGroups)
    }

    override fun onFailure(t: Throwable) {
      handleFailure(t)
    }
  },
  executor
)

Java

ListenableFuture<TrackGroupArray> trackGroupsFuture =
    MetadataRetriever.retrieveMetadata(context, mediaItem);
Futures.addCallback(
    trackGroupsFuture,
    new FutureCallback<TrackGroupArray>() {
      @Override
      public void onSuccess(TrackGroupArray trackGroups) {
        handleMetadata(trackGroups);
      }

      @Override
      public void onFailure(Throwable t) {
        handleFailure(t);
      }
    },
    executor);

Motion photos

It is also possible to extract motion photo metadata, including the offsets and lengths of the image and video parts of the file. The following motion photo container formats are supported:

  • JPEG motion photos recorded by some Android camera apps. The video part of these files is playable by ExoPlayer. The associated metadata is also exposed by the player and can be retrieved using MetadataRetriever.
  • HEIC motion photos recorded by some Android camera apps. The video part of these files is not playable by ExoPlayer, but the associated metadata can be retrieved using MetadataRetriever.

For motion photos, the TrackGroupArray obtained with the MetadataRetriever contains a TrackGroup with a single Format enclosing a MotionPhotoMetadata metadata entry.

Kotlin

0.until(trackGroups.length)
  .asSequence()
  .mapNotNull { trackGroups[it].getFormat(0).metadata }
  .filter { metadata -> metadata.length() == 1 }
  .map { metadata -> metadata[0] }
  .filterIsInstance<MotionPhotoMetadata>()
  .forEach(::handleMotionPhotoMetadata)

Java

for (int i = 0; i < trackGroups.length; i++) {
  TrackGroup trackGroup = trackGroups.get(i);
  Metadata metadata = trackGroup.getFormat(0).metadata;
  if (metadata != null && metadata.length() == 1) {
    Metadata.Entry metadataEntry = metadata.get(0);
    if (metadataEntry instanceof MotionPhotoMetadata) {
      MotionPhotoMetadata motionPhotoMetadata = (MotionPhotoMetadata) metadataEntry;
      handleMotionPhotoMetadata(motionPhotoMetadata);
    }
  }
}