mpv-player / mpv

🎥 Command line video player
https://mpv.io
Other
28.78k stars 2.93k forks source link

Buffer next videos in the playlist #6437

Open sebast889 opened 5 years ago

sebast889 commented 5 years ago

I would like to load a Youtube playlist and buffer them before they start playing. For example if I load a playlist with 5 videos and I'm still on the first video which has fully buffered I would then like it for mpv to start buffering video 2 then video 3 etc. so I don't have to wait for it to download only once start to play video 2. Is it currently possible to do this? If not, is it possible to add a way to do this?

haasn commented 5 years ago

It's almost possible, but needs a bit of massaging. mpv can already pre-buffer videos from a playlist, even ones from a remote source, since e277fadd603.

The problem is that youtube videos are not real URLs until they're processed by the ytdl_hook.lua, which runs only once the URL is actually being played back.

With a bit of refactoring, this could be made to where ytdl_hook.lua is instead called (at arbitrary times, not necessarily just when attempting playback) by mpv to resolve youtube URLs. Then --prefetch-playlist could be made to work with them.

sebast889 commented 5 years ago

Oh, nice. It would be great if it could be made to work with youtube/ytdl URLs!

bitingsock commented 5 years ago

I have a working prototype if anyone would like to try: https://gist.github.com/bitingsock/f9a87ea158035d4a36899b559d611228 It only gets the url and title for now. On line 6 ("< 10") you can set how much time ytdl gets called before the demuxer reaches the end of the cache. By default, it will call at 10 seconds from the end of the cache. You still need --prefetch-playlist for it to start buffering, assuming it actually is working. It does not support DASH playback as it just uses the "-f best" format.

bitingsock commented 5 years ago

So it looks like when the demuxer reaches eof it checks for prefetch and the url has to be resolved at that time. Can the prefetch code be recalled after this point to try again?

sebast889 commented 5 years ago

@bitingsock I've tried to get it to work by fiddling with line 6 value but can't get it doesn't buffer before the next video. Don't know if I'm doing anything wrong. Maybe I will try on another machine (though the script seems to be windows only..can it be made to work on nix?)

bitingsock commented 5 years ago

I think if you remove ".exe" from line 2 it should work on *nix. Keep in mind, the active cache shown in mpv does not include the the prefetch buffer. I had to monitor network traffic in order to verify.

bitingsock commented 5 years ago

I've discovered that a lot of usefulness of my script doesn't actually work :( It appears --prefetch-playlist doesn't actually fill the cache with subsequent data and merely opens the url and keeps it active, downloading what appears to be header and metadata and mpv just waits for that file to actually be playing before downloading any more.

ge9 commented 1 year ago

At least for youtube, we can get internal audio urls by -O url option of youtube-dl (yt-dlp) and pass them to mpv for gapless playback. if we use -O title together and translate the input to .m3u format, we can display its title. Note that this does not support video data (because internal urls are audio- or video-only), and urls will expire in 6 hours (according to the expire= parameter in urls).

ge9 commented 1 year ago

This is my yt-mpv.sh (works as yt-mpv.sh [youtube URL with playlist id] [number of musics to play] [other mpv options])

#!/bin/sh
cd /path/to/mpv_dir
ARR=(`echo $1 | sed -r "s/^.*(www|music)\.youtube\.com\/watch\?v=[^&]+&list=([^&]+)&index=([^&]+)$/\1 \2 \3/"`)
if [ ${ARR[0]} = "www" ]; then
  NA_OPTION="--compat-options no-youtube-unavailable-videos"
fi
INDEX=${ARR[2]}
if [ "$2" != "0" ]; then
  END_INDEX=`expr $INDEX + $2 - 1`
fi
shift 2
yt-dlp $NA_OPTION -f 251 --extractor-args "youtube:lang=ja" -O title -O url -I $INDEX:$END_INDEX ${ARR[1]} | sed '1~2 s/^/#EXTINF:-1,/' | sed '1i#EXTM3U' | ./mpv.exe --player-operation-mode=pseudo-gui --prefetch-playlist=yes --playlist=- $@