spezifisch / stmps

Subsonic Terminal Music Player S
GNU General Public License v3.0
20 stars 6 forks source link

support gapless playback / crossfade #34

Open ptrcnull opened 3 months ago

ptrcnull commented 3 months ago

this is a feature missing from surprisingly a lot of subsonic clients and i'd love to see it implemented here

spezifisch commented 3 months ago

That should be pretty straight-forward to implement. We only need to queue the following track a few seconds before the current one ends and mpv handles the rest for us.

xxxserxxx commented 1 month ago

@spezifisch I had a look at this, spent a couple of hours on it, and have given up for the moment.

Setting the gapless-audio option on libmpv is fairly straightforward, but by itself has no noticeable effect -- 0 (NO), 1 (YES), and -1 (WEAK) all sound the same. It's not clear (to me) from the documentation or the mpv client itself how clients should implement this. From the osc.lua example in the mpv project, it looks as if clients are supposed to load multiple songs and handle calculating the offset and playing the songs in overlap themselves, but I didn't find any example of fading overlapping songs in and out.

I shelved my changes; either this is easy but I'm unable to find code examples, or it's not easy; I suspect it might require changes to go-mpv to achieve.

Unless you have an idea how this could be done, I'd like to suggest bumping this out of milestone 1.0.0 -- I have a feeling this may be more work than expected.

spezifisch commented 1 month ago

@xxxserxxx Actually, I'm pretty sure I had a state (before forking) that had gapless playback.

AFAIR there are two ways to implement a queue with libmpv:

  1. Let mpv handle the queue. You add tracks, move or delete them, but the queue is under mpv's management. I believe that you must have multiple tracks in this queue for gapless-audio to do something. And then it works automatically like magic. I think that's still how Supersonic implements their queue.
  2. We use mpv as a "dumb" media player, i.e. there will be only ever 0-2 tracks in mpv's queue. Gapless playback could maybe (or did) work here by "preloading" the next song into mpv, let's say 10 seconds before the previous one ends. This way mpv has it in memory to make a seamless transition between tracks possible.

Disclaimer: It's been a while since I looked at that libmpv wrapper code.

Edit:

Unless you have an idea how this could be done, I'd like to suggest bumping this out of milestone 1.0.0

Also agreed.

xxxserxxx commented 1 month ago
1. Let mpv handle the queue. 

Ah. Yes, that would make sense. The complexity I encountered was all around logic required to fade in and out tracks, and start playing next songs before previous songs ended. If libmpv were handling all this, it'd need to be managing the queue; of course. My puny attempt to implement gapless by setting the gapless-audio option to YES and LAZY resulted in literally no change to the playback, at which point I gave up since I couldn't figure out through the docs how to tell libmpv to do cross-fading.

2. We use mpv as a "dumb" media player, i.e. there will be only ever 0-2 tracks in mpv's queue.

That's... elegant.

In either case, if you've done this before, I'll leave this one to you. I'm mainly trying to work through the milestone 1.0.0 items, rather than piling in new features that aren't flagged.