Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom MediaSources, resolving MediaItems from remote API, and metadata updates #11031

Closed
sampengilly opened this issue Mar 2, 2023 · 4 comments
Assignees
Labels

Comments

@sampengilly
Copy link

I've searched around extensively on this repository, on the androidx/media repository, on stack overflow, and I've been browsing through the source to determine the best course of action for my use case but I haven't really found much, and I've run into issues or gaps in the explanation on the information I have found.

The use case I have seems like it calls for custom media sources, for the most part it isn't complex, it's a case of loading the media based upon an internal URI system. But there are some additional complexities when it comes to the type of media to load.

Key details:

  • I'm using ExoPlayer via Media3
  • I am aiming to treat Media3 (and the underlying ExoPlayer) as my single source of truth for playback, i.e. all information shown in the player UI and media notification should come from Media3/ExoPlayer. (With the notification being automatic in media3).
  • The content I am loading comes from a remote datastore API, I am aiming to encapsulate this within the Media3/ExoPlayer part of my app. In other words, As far as my app UI is concerned, it just needs to add a MediaItem that uses request metadata to point to one of my internal URIs (something like mydatastorescheme://podcast/{id}) and the rest is handled opaquely inside the Media code.
  • I have many different types of content to load, all audio, but things like podcasts, audio books, live radio, etc.

In Media3 there is the MediaSession callback with the required onAddMediaItems function. This function works fine for loading the correct audio URLs and metadata for a particular bit of content referenced by one of my internal URIs. e.g. I can take the request metadata, lookup in my system what mydatastorescheme://podcast/1234 is, get its title, description, presenter name, audio stream URL, etc and I can fill out a MediaItem with that information.

However this approach seems somewhat naive and could balloon out a bit when it comes to supporting a wide variety of content types as simple as it is initially. I encountered a roadblock here when it comes to live radio streams, as the MediaItem is immutable and I have a need to hit another part of my API at scheduled times in order to update certain parts about the metadata (i.e. what radio program is currently airing, who is presenting, etc). This lead me down the path of looking more at the integration with ExoPlayer and creating custom media sources.

I've been attempting to set this up for the last few days with limited success and with some uncertainty over whether I'm using things in the right way.

The first problem I'm tackling is loading simple, on demand content with unchanging metadata (like the podcast example above). I've looked at both MediaSource factories and DataSource factories for achieving this (particularly the ResolvingDataSource). There's a few different roadblocks I've run into with trying each of these approaches:

  • Using the DefaultMediaSourceFactory with a ResolvingDataSource doesn't work to resolve my content before creating a media source as the media sources are created before the data source is used, the DefaultMediaSourceFactory also aborts if the local configuration of the MediaItem is null, which it is for me at this stage since the RequestMetadata still needs to be resolved.
  • It would be wrong to simply put my internal URL from the RequestMetadata into the local configuration, as the type of the media is still unknown at this point, so the DefaultMediaSourceFactory wouldn't be able to correctly select the right MediaSource and would just fall through to the default ProgressiveMediaSource.
  • Using a CompositeMediaSource I am able to set up a loader to resolve my internal URI to an actual MediaItem with local configuration and metadata, I can then pass this to DefaultMediaSourceFactory to get a MediaSource which I can prepare as a child of my CompositeMediaSource. However, I'm not certain if this is an ideal approach (using a media source factory inside another media source), I've seen a question asked about this without really getting an answer on it specifically (here: MediaSourceFactory for different content types combined with the dynamic stream links androidx/media#17)
  • Using the CompositeMediaSource approach I can get the audio content playing but the metadata doesn't seem to update. From tracing through the code execution it seems like the block that builds new metadata from incoming playback info (in ExoPlayer::updatePlaybackInfo) isn't getting run due to either mediaItemTransitioned being false or the staticMetadata being the same across the previous and new playback info objects. My setup is very similar to that seen in the above linked question. In onChildSourceInfoRefreshed I'm simply calling refreshSourceInfo with the new timeline as seen in some built-in composite media sources like WrappingMediaSource. I'm unsure why this doesn't carry through and update the metadata in the player.

If I can get that working then the next step would be working out what's required (likely in another custom MediaSource) to load a stream for playback, then call an API at specific times to fetch the metadata for the next airing program (API has the current and next available with timestamps for the start and end times of each). This feels like it's a job for periods on a timeline? But the mechanism through which to make those schedules API calls and surface the metadata is still unclear to me.

The documentation doesn't really have much info in it for worked examples on customized Media Sources, and resolving media lazily from an internal API seems to be a common-ish question just with different nuances. I read through another example of this here: #5883 though it still leaves some questions unanswered (such as my questions above on the use of a factory inside a media source, or the issue with metadata now flowing through from the added child source to the player.

If I could get some guidance on these questions or if this is completely the wrong direction some guidance of what the right direction is, then that would be much appreciated.

@sampengilly
Copy link
Author

Regarding the topic of metadata during playback. The docs mention a mechanism for receiving this metadata by "adding a MetadataOutput to the player" but provides no further information on how to do that. https://exoplayer.dev/retrieving-metadata.html#during-playback, if there is a mechanism through which other customizations can write to such a MetadataOutput would that be an appropriate solution to support the live radio case?

@icbaker icbaker self-assigned this Mar 2, 2023
@icbaker
Copy link
Collaborator

icbaker commented Mar 2, 2023

Since you're using media3 can you please re-post this on the media3 issue tracker (this tracker should only be used for apps using the com.google.android.exoplayer2 package): https://github.com/androidx/media/issues

@sampengilly
Copy link
Author

Apologies, I was under the impression that since this was more specifically about the ExoPlayer parts of media3 that it should be posted here (doesn't help that the media3 repo has a note in their question issue template about coming here for exoplayer related questions).

@icbaker
Copy link
Collaborator

icbaker commented Mar 2, 2023

You're right, that wording isn't super clear. sorry about that - it's meant to be saying 'search for existing issues on the exoplayer tracker'. I've sent a change to clarify that, and also more clearly call out in the templates of this tracker that it should only be used by apps using the com.google.android.exoplayer2 package. Thanks for explaining your reasoning for ending up here :)

(generally it doesn't really matter which tracker we use for exoplayer-only issues, but because you're also discussing media3-only bits like onAddMediaItems it seems best to get the whole thread into the media3 project before replying)

rohitjoins pushed a commit to androidx/media that referenced this issue Mar 7, 2023
rohitjoins pushed a commit that referenced this issue Mar 7, 2023
tonihei pushed a commit to androidx/media that referenced this issue Mar 14, 2023
Issue: google/ExoPlayer#11031

#minor-release

PiperOrigin-RevId: 514366016
(cherry picked from commit 9c82923)
tonihei pushed a commit that referenced this issue Mar 14, 2023
Issue: #11031

#minor-release

PiperOrigin-RevId: 514366016
(cherry picked from commit 0674177)
@google google locked and limited conversation to collaborators May 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants