mirror of
https://github.com/librespot-org/librespot.git
synced 2026-04-27 08:15:50 +03:00
[GH-ISSUE #1213] Gapless play and next button #558
Labels
No labels
A-Alsa
SpotifyAPI
Tokio 1.0
audio
bug
can't reproduce
compilation
dependencies
duplicate
enhancement
good first issue
help wanted
high priority
imported
imported
invalid
new api
pull-request
question
reverse engineering
wiki
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/librespot#558
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @jrfaller on GitHub (Oct 25, 2023).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/1213
Hi! First thanks a lot for this amazing project! I use it daily and I really love it!
I have a USB DAC that emits a small pop when an audio sink is released or created. Fortunately, librespot uses gapless playback and therefore when I listen to a song till the end and the next song is played, I do not get this pop.
However, I have remarked that when I click on the next button on my Spotify client, there is a pop that is emitted, meaning that in this case, there is no gapless play? I was not able to find out where to look in the code to be sure.
Would it be possible to enable gapless play also when clicking the next button? I imagine that the problem is that there is no preloaded data for the next song in this case, but would it be possible to keep the sink open?
Cheers!
@kingosticks commented on GitHub (Oct 25, 2023):
I think https://github.com/librespot-org/librespot/blob/dev/playback/src/player.rs#L941 is the culprit but I don't know/remember why that
means we also need to stop the sink (and cause your pop).
It might be possible to trigger
TimeToPreloadNextTrackevent (or similar) before we do the actual load but it probably needs something blocking. Maybe something likepreload_data_before_playback()e.g.preload_data_before_next(). These both feel like sticking plasters.@jrfaller commented on GitHub (Oct 25, 2023):
Thanks for the pointer!
Fun fact, if I wait to be near the end of the song (a little after the total time of the song minus
PRELOAD_NEXT_TRACK_BEFORE_END_DURATION_MS) and I click next, then there is no pop, meaning there is probably enough data to make a gapless play. Therefore, it makes me wonder two things:Maybe it would be a good idea regardless of my pop problem to have a "gapless" next for instance if one-day crossfading gets implemented.
Cheers!
@roderickvd commented on GitHub (Oct 25, 2023):
As part of the shift to the HTTP CDN in
dev, I also rewrote large parts of the preloading logic. Unfortunately I got little to no feedback at that time, so not sure if this is a regression or not.For purpose of diagnostics, would you please try the latest 0.4 release and see what happens there?
I also think that's wrong. This already deals with this correctly:
github.com/librespot-org/librespot@054074c920/playback/src/player.rs (L1773)So I think this would be safe to remove:github.com/librespot-org/librespot@054074c920/playback/src/player.rs (L1915)This preloading implementation, like the previous one, estimates when it should start downloading depending on network throughput and time left. So it's optimised to save bandwidth. I never gave it much thought, but I think you are right. In this age there is little reason not start the preload immediately. Though I'm no longer an active developer, from what I remember this should be easy to do.
Of course, it's also entirely possible that a user selects a "next" song which is not next in queue. That could still trigger your pop. It never did for me, so I guess it depends on the output device. So an alternative to preloading immediately, covering this case as well, is to a quick mute-unmute cycle when manually changing songs. Somewhere in the area of 20 ms ramp time should work fine. This will take a little more effort to put in.
@jrfaller commented on GitHub (Oct 25, 2023):
Thanks for the detailed answer!
I ran into the issue with the following release on moodeaudio:
[2023-10-25T18:31:33Z INFO librespot] librespot 0.4.2 22f8aed (Built on 2022-08-18, Build ID: LQ4hikXT, Profile: release)would you like me to try with other releases?I believe that it would be nice to have a more eager strategy for preloading since users with bad bandwidth can disable gapless playing
The pop is clearly a design mistake from my DAC manufacturer, I totally can live with a pop if my playlist has ended, and I do not have autoplay 😆
@roderickvd commented on GitHub (Oct 25, 2023):
Yeah in that case please try compiling from
dev?@kingosticks commented on GitHub (Oct 26, 2023):
That's a nice idea.
@jrfaller commented on GitHub (Oct 26, 2023):
Oooh maybe I did not understand the proposal, it means that when clicking the next button librespot would mute / load the next song / unmute instead of recreating a sink?
Ok tried that, surprisingly easy on the raspberry. Got
[2023-10-26T18:36:41Z INFO librespot] librespot 0.5.0-dev 054074c (Built on 2023-10-26, Build ID: GBF8F7wi, Profile: debug)running. Unfortunately, ran over someERROR librespot_core::mercury] error 403 for uri hm://keymaster/token/authenticated?scope=playlist-read&client_id=errors that I do not understand because connexion and authentication seemed to work fine (and got no sound to test the pop).@jrfaller commented on GitHub (Oct 27, 2023):
Status update: got librespot working fine using @kingosticks fix for #1179:
librespot] librespot 0.5.0-dev 1896611 (Built on 2023-10-27, Build ID: Rjfa9F0L, Profile: debug).On this version, the behavior is the same as
0.4.2.I tried removing
self.ensure_sink_stopped(play);as suggested by @roderickvd and 🥁 there is no longer a pop when clicking next, which fixes my problem 👍🏻@jrfaller commented on GitHub (Oct 29, 2023):
Another testing update: not only does the removal of
self.ensure_sink_stopped(play);fix the sink closing when clicking on the next button but it also avoids closing the sink when directly changing to another song when a song is playing. As far as I can tell, no regression was detected!@roderickvd commented on GitHub (Nov 14, 2023):
Could you put in a PR to fix it for everyone?
@jrfaller commented on GitHub (Nov 15, 2023):
Of course! Here it is at #1223