From 664e8fe66ae8532471c2528e86812122af6a04dd Mon Sep 17 00:00:00 2001 From: Ricardo Constantino Date: Mon, 15 Jan 2018 21:16:36 +0000 Subject: ytdl_hook: parse youtube playlist urls to set start index Still needs `--ytdl-raw-option=yes-playlist=` because this only works for youtube. This was requested in a few issues: https://github.com/mpv-player/mpv/issues/1400 https://github.com/mpv-player/mpv/issues/2592 https://github.com/mpv-player/mpv/issues/3024 For #1400 to be completely implemented would need ytdl_hook to re-request the same playlist with the last video's ID for the mix to continue indefinitely which would probably too hackish to work reliably. --- player/lua/ytdl_hook.lua | 58 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/player/lua/ytdl_hook.lua b/player/lua/ytdl_hook.lua index b76297033f..59ffbd3b94 100644 --- a/player/lua/ytdl_hook.lua +++ b/player/lua/ytdl_hook.lua @@ -142,6 +142,45 @@ local function is_blacklisted(url) return false end +local function parse_yt_playlist(url, json) + -- return 0-based index to use with --playlist-start + + if not json.extractor or json.extractor ~= "youtube:playlist" then + return nil + end + + local query = url:match("%?.+") + if not query then return nil end + + local args = {} + for arg, param in query:gmatch("(%a+)=([^&?]+)") do + if arg and param then + args[arg] = param + end + end + + local maybe_idx = tonumber(args["index"]) + + -- if index matches v param it's probably the requested item + if maybe_idx and #json.entries >= maybe_idx and + json.entries[maybe_idx].id == args["v"] then + msg.debug("index matches requested video") + return maybe_idx - 1 + end + + -- if there's no index or it doesn't match, look for video + for i = 1, #json.entries do + if json.entries[i] == args["v"] then + msg.debug("found requested video in index " .. (i - 1)) + return i - 1 + end + end + + msg.debug("requested video not found in playlist") + -- if item isn't on the playlist, give up + return nil +end + local function make_absolute_url(base_url, url) if url:find("https?://") == 1 then return url end @@ -417,10 +456,11 @@ mp.add_hook(o.try_ytdl_first and "on_load" or "on_load_fail", 10, function () local raw_options = mp.get_property_native("options/ytdl-raw-options") local allsubs = true local proxy = nil + local use_playlist = false local command = { ytdl.path, "--no-warnings", "-J", "--flat-playlist", - "--sub-format", "ass/srt/best", "--no-playlist" + "--sub-format", "ass/srt/best" } -- Checks if video option is "no", change format accordingly, @@ -445,15 +485,19 @@ mp.add_hook(o.try_ytdl_first and "on_load" or "on_load_fail", 10, function () end if (param == "sub-lang") and (arg ~= "") then allsubs = false - end - if (param == "proxy") and (arg ~= "") then + elseif (param == "proxy") and (arg ~= "") then proxy = arg + elseif (param == "yes-playlist") then + use_playlist = true end end if (allsubs == true) then table.insert(command, "--all-subs") end + if not use_playlist then + table.insert(command, "--no-playlist") + end table.insert(command, "--") table.insert(command, url) msg.debug("Running: " .. table.concat(command,' ')) @@ -559,6 +603,7 @@ mp.add_hook(o.try_ytdl_first and "on_load" or "on_load_fail", 10, function () msg.verbose("Playlist with single entry detected.") add_single_video(json.entries[1]) else + local playlist_index = parse_yt_playlist(url, json) local playlist = {"#EXTM3U"} for i, entry in pairs(json.entries) do local site = entry.url @@ -589,9 +634,12 @@ mp.add_hook(o.try_ytdl_first and "on_load" or "on_load_fail", 10, function () end - if #playlist > 0 then - mp.set_property("stream-open-filename", "memory://" .. table.concat(playlist, "\n")) + if use_playlist and + not option_was_set("playlist-start") and playlist_index then + mp.set_property_number("playlist-start", playlist_index) end + + mp.set_property("stream-open-filename", "memory://" .. table.concat(playlist, "\n")) end else -- probably a video -- cgit v1.2.3