summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--player/lua/ytdl_hook.lua163
1 files changed, 163 insertions, 0 deletions
diff --git a/player/lua/ytdl_hook.lua b/player/lua/ytdl_hook.lua
new file mode 100644
index 0000000000..8f3c319758
--- /dev/null
+++ b/player/lua/ytdl_hook.lua
@@ -0,0 +1,163 @@
+local utils = require 'mp.utils'
+local msg = require 'mp.msg'
+
+local ytdl = {
+ path = "youtube-dl",
+ minver = "2014.11.09",
+ vercheck = nil,
+}
+
+mp.add_hook("on_load", 10, function ()
+
+ local function exec(args)
+ local ret = utils.subprocess({args = args})
+ return ret.status, ret.stdout
+ end
+
+ local url = mp.get_property("stream-open-filename")
+
+ if (url:find("http://") == 1) or (url:find("https://") == 1)
+ or (url:find("ytdl://") == 1) then
+
+ -- check version of youtube-dl if not done yet
+ if (ytdl.vercheck == nil) then
+
+ -- check for youtube-dl in mpv's config dir
+ local ytdl_mcd = mp.find_config_file("youtube-dl")
+ if not (ytdl_mcd == nil) then
+ msg.verbose("found youtube-dl at: " .. ytdl_mcd)
+ ytdl.path = ytdl_mcd
+ end
+
+ msg.debug("checking ytdl version ...")
+ local es, version = exec({ytdl.path, "--version"})
+ if (es < 0) then
+ msg.warn("youtube-dl not found, not executable, or broken.")
+ ytdl.vercheck = false
+ elseif (version < ytdl.minver) then
+ msg.verbose("found youtube-dl version: " .. version)
+ msg.warn("Your version of youtube-dl is too old! "
+ .. "You need at least version '"..ytdl.minver
+ .. "', try running `youtube-dl -U`.")
+ ytdl.vercheck = false
+ else
+ msg.verbose("found youtube-dl version: " .. version)
+ ytdl.vercheck = true
+ end
+ end
+
+ if not (ytdl.vercheck) then
+ return
+ end
+
+ -- strip ytdl://
+ if (url:find("ytdl://") == 1) then
+ url = url:sub(8)
+ end
+
+ -- subformat workaround
+ local subformat = "srt"
+ if url:find("crunchyroll.com") then
+ subformat = "ass"
+ end
+
+ local es, json = exec({
+ ytdl.path, "-J", "--flat-playlist", "--all-subs",
+ "--sub-format", subformat, "--no-playlist", "--", url
+ })
+
+ if (es < 0) or (json == nil) or (json == "") then
+ msg.warn("youtube-dl failed, trying to play URL directly ...")
+ return
+ end
+
+ local json, err = utils.parse_json(json)
+
+ if (json == nil) then
+ msg.error("failed to parse JSON data: " .. err)
+ return
+ end
+
+ msg.info("youtube-dl succeeded!")
+
+ -- what did we get?
+ if not (json["direct"] == nil) and (json["direct"] == true) then
+ -- direct URL, nothing to do
+ msg.verbose("Got direct URL")
+ return
+ elseif not (json["_type"] == nil) and (json["_type"] == "playlist") then
+ -- a playlist
+
+ local playlist = "#EXTM3U\n"
+ for i, entry in pairs(json.entries) do
+ local site = entry.url
+
+ -- some extractors will still return the full info for
+ -- all clips in the playlist and the URL will point
+ -- directly to the file in that case, which we don't
+ -- want so get the webpage URL instead, which is what
+ -- we want
+ if not (entry["webpage_url"] == nil) then
+ site = entry["webpage_url"]
+ end
+
+ playlist = playlist .. "ytdl://" .. site .. "\n"
+ end
+
+ mp.set_property("stream-open-filename", "memory://" .. playlist)
+
+ else -- probably a video
+ local streamurl = ""
+
+ -- DASH?
+ if not (json["requested_formats"] == nil) then
+ msg.info("NOTE: Using DASH, expect inaccurate duration.")
+ -- video url
+ streamurl = json["requested_formats"][1].url
+
+ -- audio url
+ mp.set_property("file-local-options/audio-file",
+ json["requested_formats"][2].url)
+
+ -- workaround for slow startup (causes inaccurate duration)
+ mp.set_property("file-local-options/demuxer-lavf-o",
+ "fflags=+ignidx")
+
+ elseif not (json.url == nil) then
+ -- normal video
+ streamurl = json.url
+ else
+ msg.error("No URL found in JSON data.")
+ return
+ end
+
+ msg.debug("streamurl: " .. streamurl)
+
+ mp.set_property("stream-open-filename", streamurl)
+
+ mp.set_property("file-local-options/media-title", json.title)
+
+ -- add subtitles
+ if not (json.subtitles == nil) then
+ for lang, script in pairs(json.subtitles) do
+ msg.verbose("adding subtitle ["..lang.."]")
+
+ local slang = lang
+ if (lang:len() > 3) then
+ slang = lang:sub(1,2)
+ end
+
+ mp.commandv("sub_add", "memory://"..script,
+ "auto", lang.." "..subformat, slang)
+ end
+ end
+
+ -- for rtmp
+ if not (json.play_path == nil) then
+ mp.set_property("file-local-options/stream-lavf-o",
+ "rtmp_tcurl=\""..streamurl..
+ "\",rtmp_playpath=\""..json.play_path.."\"")
+ end
+ end
+ end
+end)