mihaiolteanu / vuiet

The music player and explorer for Emacs
https://mihaiolteanu.me/vuiet
GNU General Public License v3.0
278 stars 15 forks source link

Pre-buffer upcoming tracks #14

Closed hughwilliams94 closed 4 years ago

hughwilliams94 commented 4 years ago

Thanks for the package, a really cool implementation. I don't know if this would require a significant re-write, but it would be nice if the upcoming track could be queued to avoid the current silence between tracks.

[Edit] I have just realised that this may actually be the intended behaviour but that my setup is broken, after running vuiet-play-artist, the track plays and then I get the following error:

[error] request--callback: peculiar error: 400
[error] request-default-error-callback: http://ws.audioscrobbler.com/2.0/ error
Error running timer ‘vuiet--scrobble-track’: (error "Invalid method signature supplied")

Is this related?

mihaiolteanu commented 4 years ago

the upcoming track could be queued

That's a good point. I'll look over it, but I can' promise a quick solution available "today". I've scribbled it on my todo list. Thanks for your suggestion.

Is this related?

No, it is not. It is related to scrobbling your track, which is, adding your currently playing track to the list of listened tracks that is visible when you visit your last.fm account. You probably don't have the Session Key (SK) in your .lastfmrc file. You can check that by visiting the said file, at this location: (concat (xdg-config-home) lastfm--config-file-name). Calling (lastfm-generate-session-key) should generate and save the SK in your .lastfmrc file. See the lastfm.el package for the details.

If you don't want scrobbling, you can disable it by setting the vuiet-scrobble-enabled custom variable to nil.

If any of the above is not as clear as it should be, please let me know so that I can update the README.

hughwilliams94 commented 4 years ago

Thanks for the tip on the scrobbling error. No rush on the buffering, thanks for getting back to me.

aluaces commented 4 years ago

Some tips:

hughwilliams94 commented 4 years ago

I have used mpv for streaming video before, and I seem to remember that it buffers a bit before beginning playback. Perhaps that is the delay. Pre-downloading a couple of tracks at a time would be great, but might not be perfect when internet connection are patchy (although the same is true for streaming). Maybe it could be a configurable option?

mihaiolteanu commented 4 years ago

I'm not sure about whether the slow part is waiting for the link or waiting for the streaming to begin

I've timed both streaming the youtube link directly and with ytsearch, as is now implemented in vuiet . There is no difference between the two.

I have used mpv for streaming video before, and I seem to remember that it buffers a bit before beginning playback. Perhaps that is the delay.

Yes, indeed. It does a bit of buffering before starting to play the video. There is an option for mpv to change the amount of buffering done before it actually starts playing the video. That also makes no significant difference regarding the start-up time.

According to this issue from mpv, it seems like,

the extra pass needed to request the metadata, plus the wasted time due to a double-connect, is a big part of the overhead for watching youtube videos

So having the youtube link beforehand or just doing a search seems to make no significant difference. Same for buffering.

Another idea would be prestart the next track in a different mpv instance and pause it right after it starts. But that is not doable at the moment since controlling the mpv process makes use of a socket and the way the mpv.el package is now implemented only allows one mpv instance to run.

Another one would be to have an mpv playlist, and to prefetch the next youtube song on that playlist when the current one starts. That also seems to be not doable, according to the issue linked above.

On my machine, starting up the next youtube song with mpv takes about 5 seconds, and the fetching of what song to play, which includes at least a call to last.fm, takes about 1 second. Given what I know and seen, I guess the only part where some start-up time can be saved, is fetching the info from last.fm beforehand.

downloading the file beforehand

That could be the only option at the moment, but some users might not like it and, again, I don't think the current mpv.el implementation supports it. That is, calling another mpv instance while one is already running.

Maybe it could be a configurable option?

That could be a way.

mihaiolteanu commented 4 years ago

Here is the official mpv documentation saying that prefeching of youtube urls doesn't and it probably won't work in the near future [1],

--prefetch-playlist=<yes|no> Prefetch next playlist entry while playback of the current entry is ending (default: no). This merely opens the URL of the next playlist entry as soon as the current URL is fully read.

This does not work with URLs resolved by the youtube-dl wrapper, and it won't.

This does not affect HLS (.m3u8 URLs) - HLS prefetching depends on the demuxer cache settings and is on by default.

This can give subtly wrong results if per-file options are used, or if options are changed in the time window between prefetching start and next file played.

This can occasionally make wrong prefetching decisions. For example, it can't predict whether you go backwards in the playlist, and assumes you won't edit the playlist.

Highly experimental.

So that is not an option at the moment.

It seems that first downloading the whole video and only then playing it with mpv is sometimes faster (depending on the size, of course) than streaming it. So I'll try to have a system where the first song is streamed, since you will have to have a startup time somewhere, and the second song is downloaded while the first one is still streaming. When the second song starts playing, a third one will start to download, and so on and so forth.

I'll play with this and see what will come out of it.

[1] https://mpv.io/manual/stable/#options-prefetch-playlist

mihaiolteanu commented 4 years ago

I've updated vuiet to not close the mpv player between tracks or between changing playlists. This saves a bit of time.

I've also updated vuiet to prefetch the next track from lastfm together with its youtube url. This also saves a bit of load time.

As said above, the greatest latency is when starting to actually play a youtube url. This is because the way mpv does things. There's nothing I can change about that.

With the above changes, playing the next track in a playlist takes about 30-40% less time than before (rough calculation based on my feeling).

Try it out and let me know if you have any issues. I will close this issue otherwise.

Thanks!

mihaiolteanu commented 4 years ago

Well, no complaints means everybody is happy :)

aluaces commented 4 years ago

Works wonderfully. Sometimes I cannot even tell what I'm hearing is a different song already. Thanks!