Skip to content

Commit

Permalink
ytdl_hook: parse youtube playlist urls to set start index
Browse files Browse the repository at this point in the history
Still needs `--ytdl-raw-option=yes-playlist=` because this only
works for youtube.

This was requested in a few issues:
#1400
#2592
#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.
  • Loading branch information
wiiaboo committed Feb 11, 2018
1 parent 0578afd commit 58be7c1
Showing 1 changed file with 53 additions and 5 deletions.
58 changes: 53 additions & 5 deletions player/lua/ytdl_hook.lua
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand All @@ -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,' '))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 58be7c1

Please sign in to comment.