Request times, playback limits, shuffling and the limitations of a server-client architecture #1023
heyhippari
started this conversation in
UI & UX
Replies: 1 comment 2 replies
-
I think the server already tracks queues on a basic level, but it sounds like what you want already exists in a different form. Rather than track individual queue history on the server (which would impose its own problems) we should add a new sort method called "FakeRandom" or something that takes the user's play history as input. This actually sounds like the better option, because it will account for playback on different devices and thus provide even better non-random randomness. |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I want to make an open and archived design discussion for this, as I think it's important enough that a simple Matrix chat doesn't cut it.
PR #1008 has generated some amount of discussion both publicly and in private, in particular with regards to the imposed limit of 300 items on a request. As such, I wanted to explain the reasoning a bit more, how it also applies to the rest of the client, why it's done and why we can't really do it any other way.
Essentially, "true shuffling" is pretty much impossible in current Jellyfin and may be impossible (or very hard to do) in future Jellyfin.
The main reason why Spotify and other apps that rely on a client-server model do not do "true shuffling" is fairly simple: due to the architecture, you are limited to a set amount of data for transfers to be done quickly. This is the entire reason why websites and web apps paginate data.
Here is an example of two requests for the same data (A music library of around 4046 tracks). The first request doesn't have a limit, second one has a limit of 300 items:
Do not focus too much on the request time here, as network latency and such can very quite a bit. Instead, I would like to focus on the size of the data:
5.75MB vs 0.43MB
This might not seem like a lot, but do remember: we also run on metered and mobile connections. These usually tend to be a lot slower, and every kilobyte of data matters. And for every track you add to your library, this number grows.
This, combined with the server-side time to query items (Jellyfin, as of writing, has a rather slow database) makes one thing obvious: there has to be limits set, for pretty much every query. Otherwise, the client becomes sluggish and annoying to use (Waiting more than around half a second for playback to start is not an acceptable user experience).
Then there is the issue of "true shuffling", which was brought up during discussions about the new playback limit. Here is a thorough answer on Quora from former Spotify engineer Mattias Petter about whether Spotify's shuffle is truly random or not, and why.
Some interesting takeaways from this:
There is also this answer by Spotify engineer Lukáš Poláček which goes more into the probabilities:
(I believe this may have changed a bit since 2015, but more on that later.)
They also link a very good article from the Spotify R&D blog, written by Lukáš Poláček: https://engineering.atspotify.com/2014/02/28/how-to-shuffle-songs/
tl;dr: Spotify used the Fischer-Yates algorithm to shuffle tracks. This is pretty much what Lodash uses (So what the current
master
branch of Jellyfin Vue uses, as of 2021-04-17) and, I suspect (but without proof) what the server might use).Through user feedback, they noticed that true randomness isn't what people actually want (even though they think it is).
They eventually moved on to an algorithm based on dithering algorithms like Floyd-Steinberg. This provides an even distribution of artists and albums throughout the queue, removing the feeling of "non-random randomness" that users felt.
One caveat they mention is that restarting the app essentially re-shuffles the queue, leading to further feeling of non-randomness. I mentioned before that I had a hunch that something changed between the previously cited posts and now, and I believe it relates to that.
My guess is that Spotify stores queues on the server-side, unless the user is playing locally.
When you request playback, it opens a session with Spotify (Much like we do with Jellyfin when starting playback), but the queue is handled on Spotify's side, for the most part.
They shuffle server-side, they send you back a few items to start, and more as you go along or navigate to the queue page.
This solution would fix all our issues, since we could get the speed afforded by paginating items, while also offering longer (potentially limitless) queues, with proper shuffling.
So, here is how I see it:
With this in mind, here is the game plan that I propose (which would involve the server team, and would likely not be ready until Jellyfin 11):
This makes the client actually usable, by keeping the "time to start" for playback low
I'm thinking mainly of the library views. One downside is that this kills @ferferga dream of blazing through library pages at lightning speed. That's essentially impossible due to technical constraints (Even now, it's difficult. The only real way to achieve this is to pre-render everything into DOM, which just isn't viable).
When reaching the last track of the queue (or scrolling down to the end of the queue), we would fetch the next 300 items in the queue.
The server is the one who would handle shuffling, paginating the queue, etc. We would just request a session, with an initiator item (An album, playlist, series, collection, library, etc). The server would store the queue on that playback session and we would request pages (This also fixes getting access to queues for remote devices, as well as generally unifies the way clients start playback)
Remove the use of true randomness from any shuffle operation. Queues would be shuffled as explained above (though in a way that is adapted to various media types).
This effectively fixes a bunch of issues, both with Vue and the server in general, making us pretty fast, allowing for nicer shuffling of items, unlimited queue lengths, and allowing clients to easily see what the queues for the others are, which is perfect for remote control.
Beta Was this translation helpful? Give feedback.
All reactions