-
Notifications
You must be signed in to change notification settings - Fork 130
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
Rework player progress reporting #477
Conversation
9dc737f
to
3d72f67
Compare
Hi @Maxr1998, you might also wanna check out my changes for the upcoming redesign at https://github.com/Chaphasilor/finamp/tree/better-queue! I completely rewrote the queuing system to be more flexible, and have a separate service for playback history that also handles playback reporting. I hope you didn't spent too long on the rewrite 😅 Hopefully we can integrate some of your improvements there, if necessary? |
FYI, the new |
Hi @Chaphasilor! Unfortunately I didn't see your changes before making my own. I looked through some of your recent commits, the history service seems really useful. Very excited for that already, I thought about a feature like this myself in the past. Regarding the new queue system and playback reporting, I believe it still has the same problems as the current main branch, specifically those outlined in #87 and handled by my workaround in #200. The root cause is a race condition where using the current player state in the player event handler may return mismatched data if the event or generated PlaybackProgressInfo are too old, i.e. were recorded before the track was changed and the player started a new track. I think we could work to integrate my changes to the new system as well. |
This looks very nice! We could still get it into main, since the redesign changes won't be in a full release for a while. |
Sounds good to me! Any idea about the volume reporting? Should we just default isMuted to false if we don't have the info. |
Yeah, we could just leave that out if just_audio doesn't let us get to it. |
Alright, I'll do the changes later then! |
Looking at your PR description from #200:
I believe this shouldn't be happening with the new system because the Edit: nevermind, seems like I was lazy and used the old implementation for now. This will be changed later on to reflect my comment above 😅 |
The playbackEventStream unfortunately isn't frequent enough, causing the previous event to sometimes be older than the specified maximum age. This causes stop events to be dropped sometimes. Thus, we revert this, but also ensure that the position, that is automatically extrapolated based on the current time, doesn't exceed the duration of the track.
Had to make some more testing because the player doesn't update the playback state as often as I'd like (sometimes lagging behind over two minutes if the app is in the background...). Thus, I reverted that extra workaround for now. The current behavior should work pretty well and is ready for review. |
Found a better workaround, now it's fine 👍 |
I've been actively using this for a while now and can confirm it's nearly perfect. There are still some conditions where duplicate playback events are sent, but those are quite rare, thankfully, and otherwise the events are sent very reliably (as long as the network connection also is). |
That's awesome to hear! I think this could be merged in then, it won't be worse than the old system ^^ Also, do you know if it's possible to send playback events after-the-fact, i.e. caching them in offline mode and then retro-actively pushing them to the server? That would be super neat! |
Unfortunately, the Jellyfin API doesn't really support this at the moment. You can technically do this through the The best solution would be a stop timestamp on the playback stopped event or an additional activity submission endpoint in Jellyfin that playback reporting plugins could use then, but that's a breaking API change which I doubt would arrive anytime soon. |
Hmm, that's a bummer. I think proper playback statistics are very important and educational, and help with curating personalized suggestions. But I'm biased (created Jellyfin Rewind :D) One thing that I would really like to see at some point is the ability to submit a parent ID of a playback item, for example an album or a playlist. I created an issue for it in the Playback Reporting repo, but never received a reply. Maybe you have some more influence there? |
Merging :) As for the idea of caching for offline mode, I think just throwing events at Jellyfin will suffice. We could add an option to attempt to send in offline mode, so that people who only ever use offline mode can still regularly update their playback (and cached events won't be too inaccurate) |
I'm not sure what exactly you mean by "just throwing events at Jellyfin". Once Jellyfin supports that? Because submitting the event after-the-fact would cause problems... |
Would it? We could just "replay" the events, i.e., send a start event and an end event (or wherever the song was stopped). Ideally we'd be able to say when the event happened, but we can't right now. |
yeah that's the problem. we could track that it was played at all, yes, but the playback duration would be screwed up Edit: or can we specify the position for the stop event? |
@Maxr1998 I'm currently porting this over into #484 and just have two questions:
|
Unfortunately not. I wish the used audio player library would expose a few more events.. on ExoPlayer (which is wrapped by this), a looped track should be much easier to detect. I agree that if we send a queue, position changes (of any track in the queue) should report the new queue to the server. |
Thanks for your input. My first shot at this is at ce5eee2 if you would like to take a look. |
Still need to test this thoroughly and fix one added TODO before this is ready for a full review. Wanted to get this out early nonetheless.
On to the basic ideas behind this change: currently, the player reports playback stop events after the track index changes, with no easy way to know the previous state.
For that, it subscribes to
_player.currentIndexStream
, which simply maps the (distinct) index from_player.playbackEventStream
. So, my idea was to drop this index stream completely, and instead handle the changes in the_player.playbackEventStream
manually by comparing the new and previous index. This comes with the advantage that of knowing the complete previous state as well in that handler.I also heavily rewrote
generatePlaybackProgressInfo
and split it into three functions.The original function still handles the reporting, but now receives all attributes as parameters. No default handling, no reading information from the player anymore.
The two new functions handle the following cases: