-
Notifications
You must be signed in to change notification settings - Fork 408
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
Make audio processors MediaItem aware #418
Comments
Could you point out how exactly you apply the replay gain once you have the metadata? Is this a simple call to The reason for these questions is that waiting for |
Yes I get the RG values from the Format.metadata. (But I could also get them before if necessary). And I use most of the time an AudioProcessor for that but there's no calls to configure or anything on media change if they are the same codec and everything. (And it's also an issue for example to enable / disable audio processor on demand, currently we can only bypass by doing a simple copy). The other way I use sometimes is to apply an Android DynamicsProcessing at higher level when I also apply some EQ stuff) but this is even less precise. If there was a way with AudioProcessor then I would always use it but this is not the case currently. For the first song or when pressing next (so a new prepare) this works perfectly the metadata is extracted before the codec is initialized and applied correctly before first audio sample or at least the flush works soon enough to ensure no wrong sample is played. But with gapless we are not talking about 1 audio sample but could be up to 2 seconds that is already passed through the processor and the flush is wayy too late to recover. With flac or high res media this is a lot less but with mid quality MP3 this is 2 seconds. Anyway if there's no way to disable the current gapless behavior, an audio processor solution would be nice. |
Bump ? Currently applying the RG via ffmpeg as a secondary solution but this is not efficient at all. A future native solution would be better. |
It sounds to me like the problem is around the fact that @tonihei - You're more familiar with ExoPlayer components. Is there functionality in audio renderers to force the sink to be configured when the media item changes? I can't determine what the trigger is for MediaCodecAudioRenderer/DecoderAudioRenderer to configure the underlying sink is - It all seems based on codec reuse. Once/if @tonihei confirms this, my recommendation would be for @Tolriq to pass in a custom |
This means @Samrobbo's suggestion of wrapping |
Can try that after holidays but not sure about the flush on configure. Currently this does not happen when the format is the same, that's why we can't just disable the custom audio processor when not needed. But if the sink configure is called on same format I guess I can force it anyway. Same question about Gapless, should I take special steps when the RG is constant and gapless wanted to avoid wrong flush and audible glitches? |
Ok so @tonihei @Samrobbo I did a quick test.
But the format passed to that function have no metadata at all, no id, nothing I can use to try to extract or get access to already extracted RG data. |
Actually got my answer: And The metadata is not passed down. Adding:
To
To Seems to fix all the cases including when using external libraries like ffmpeg. Not sure about the potential impacts / side effects before submitting a PR. |
@tonihei Can you advise? |
So I'm late with my luggage but configuring the AP at that moment works perfectly including Gapless. Would be really nice if there was a proper way to ensure that the metadata is passed down to the |
Bump. At least to have confirmation that by doing so in my fork I won't have side effects I did not see yet. |
Ah, sorry, I didn't see the problem you highlighted when reading your post above. Adding more identifying fields to this |
Ok perfect thanks. Should I make a PR as it might be helpful globally for others no? |
Yes, please file a PR and we'll merge it in. |
BTW unrelated but there's a tons of nullability issues in 1.2 (Never really checked that part of the code before). |
We run Checker Framework's nullability checks internally to ensure there aren't any issues. However, there are some files that are currently still excluded from the check because we never got around to ensure proper annotations everywhere. |
Seems ExoPlayer does not extract metadata from WAV (probably normal since there's no official ways), but even if I do have the RG values I can't find a way to pass them down to the AudioSink. Is there anything I'm missing to be able to pass down at least an ID or something to gather the proper data from the proper related media? |
@Samrobbo @christosts I believe there are some efforts to make the audio processing pipeline "MediaItem-aware" in order change effects based on the current item. We already pass down the current item to the audio renderer, but I'm not sure how/if this ends up in the actual audio processors. Could you comment on what's already planned (or what could be done?) |
No concrete plans yet, the work is TBD. I think our first approach would be to use awareness of MediaItem in the audio renderer and then have custom logic that sits on top of the audio processors inside a custom audio sink implementation. So, unless we hit a dead-end, I'd say we will not change the AudioProcessors, at least not yet |
@christosts @tonihei you both seem to say audio renderer is MediaItem aware but I can't see anything mediaItem related or a way to access it from If there's a way to access the MediaItem there I can use it to augment the metadata passed down to the sink and that works for me to have a fork for that as a constrained change. |
Apologies, this is just added in Media3 v1.2.0. I'm copying the answer from another comment I posted recently: As of version 1.2.0, there are two changes in
With a Timeline and a MediaPeriodId, you can get the
|
@christosts Trying to figure out the proper place to handle things for both renderers to pass to the sink without a flush is possible. |
That said, when |
Yes with #594 the metadata is now available at the configure call in the processor. I just need a way to augment the metadata from the media item for the case ExoPlayer does not extract what I need or I get it from the server. Maybe there's another place where I can call again the sink configure without triggering sample loss. The whole attempt is to avoid wrong volume sample that can be hard on ears with large replay gain values. |
So finally started to investigate on this and it seems to work (needs to use I can access the proper media item before the sink.configure call and augment the metadata. But since this is quite intrusive in a fork, do you think there's a way to negotiate an official solution @christosts ? Like simply adding a mediaId to the format and passing it down, this looks like the less intrusive way to pass the data without an API change. I can imagine custom audioprocessors having access to the media item can solve a few issues like this one (replay gain), but could also allow per media items settings, like convert to mono or specific balance, .... |
I'll reassign it to @Samrobbo who may have the most insights in the audio processing plans. The general request sounds reasonable and I think there already were other plans to make the audio processors MediaItem-aware. |
My app support gapless and everything works fine.
But my app also support Replay Gain that it applies from extracted metadata. The gain is applied from
onTracksChanged
and this works nicely for the first song (And also when applying for albums since the replay gain is constant).The problem arise when users want to play random songs with random replay gain values. In that case due to pre buffering for gapless,
onTracksChanged
is called too late and the replay gain is applied late (For medium quality mp3 up to 2 seconds). This obviously is not nice.Since they play random tracks there's no need for gapless, and they prefer a small delay for the next song than a wrong volume for a few seconds.
The question is how can I achieve that (disable gapless, so that I can apply the replaygain at the proper moment) in normal usage of exoplayer and media sources and everything.
I'd like to avoid rewrite a complete different path to not use ExoPlayer playlists and handle everything manually.
The text was updated successfully, but these errors were encountered: