mirror of
https://github.com/mpv-player/mpv
synced 2024-12-28 18:12:22 +00:00
ytdl_hook: add all_formats option
Pretty worthless I guess. I only tested one site (and 2 videos), it's somewhat likely that it will break with other sites. Even if you leave the option disabled (the default). Slightly related to #3548. This will allows you to use the bitrate stream selection mechanism, that was added for HLS, with normal videos.
This commit is contained in:
parent
43c13e5ea2
commit
6d8b4ca742
@ -823,6 +823,19 @@ Program Behavior
|
||||
should use ``%`` before any of the characters ``^$()%|,.[]*+-?`` to match
|
||||
that character.
|
||||
|
||||
The ``all_formats`` script option accepts a boolean 'yes' or 'no',
|
||||
and if 'yes' will attempt to add all formats found reported by youtube-dl
|
||||
(default: no). Each format is added as a separate track. In addition, they
|
||||
are delay-loaded, and actually opened only when a track is selected (this
|
||||
should keep load times as low as without this option). It also adds average
|
||||
bitrate metadata, if available, which means ``--hls-bitrate`` will decide
|
||||
which track to select. (HLS used to be the only format whose alternative
|
||||
quality streams were exposed in a similar way, thus the option name.) The
|
||||
``--ytdl-format`` option is essentially ignored. Although this mechanism
|
||||
makes it possible to switch streams at runtime, it's not suitable for this
|
||||
purpose for various technical reasons. In general, this option is not
|
||||
useful, and was only added to show that it's possible.
|
||||
|
||||
.. admonition:: Examples
|
||||
|
||||
- ``--script-opts=ytdl_hook-exclude='^youtube%.com'``
|
||||
@ -837,6 +850,10 @@ Program Behavior
|
||||
formats like HLS and DASH, if available, allowing for video/audio selection
|
||||
in runtime. It's disabled ("no") by default for performance reasons.
|
||||
|
||||
.. admonition:: Why do the option names mix ``_`` and ``-``?
|
||||
|
||||
I have no idea.
|
||||
|
||||
``--ytdl-format=<ytdl|best|worst|mp4|webm|...>``
|
||||
Video format/quality that is directly passed to youtube-dl. The possible
|
||||
values are specific to the website and the video, for a given url the
|
||||
|
@ -5,7 +5,8 @@ local options = require 'mp.options'
|
||||
local o = {
|
||||
exclude = "",
|
||||
try_ytdl_first = false,
|
||||
use_manifests = false
|
||||
use_manifests = false,
|
||||
all_formats = false,
|
||||
}
|
||||
options.read_options(o)
|
||||
|
||||
@ -29,11 +30,38 @@ local safe_protos = Set {
|
||||
"data"
|
||||
}
|
||||
|
||||
-- Codec name as reported by youtube-dl mapped to mpv internal codec names.
|
||||
local map_codec_to_mpv = {
|
||||
["vtt"] = "webvtt",
|
||||
local codec_map = {
|
||||
["vtt"] = "webvtt",
|
||||
["opus"] = "opus",
|
||||
["vp9"] = "vp9",
|
||||
}
|
||||
|
||||
-- Codec name as reported by youtube-dl mapped to mpv internal codec names.
|
||||
-- Fun fact: mpv will not really use the codec, but will still try to initialize
|
||||
-- the codec on track selection (just to scrap it), meaning it's only a hint,
|
||||
-- but one that may make initialization fail. On the other hand, if the codec
|
||||
-- is valid but completely different from the actual media, nothing bad happens.
|
||||
local function map_codec_to_mpv(codec)
|
||||
if codec == nil then
|
||||
return nil
|
||||
end
|
||||
local mc = codec_map[codec]
|
||||
if mc then
|
||||
return mc
|
||||
end
|
||||
if codec:sub(1, 5) == "avc1." then
|
||||
return "h264"
|
||||
end
|
||||
if codec:sub(1, 5) == "av01." then
|
||||
return "av1"
|
||||
end
|
||||
if codec:sub(1, 5) == "mp4a." then
|
||||
return "aac"
|
||||
end
|
||||
print("unknoiwn codec " .. codec)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function exec(args)
|
||||
local ret = mp.command_native({name = "subprocess",
|
||||
args = args,
|
||||
@ -288,10 +316,26 @@ local function valid_manifest(json)
|
||||
proto:find("^m3u8")
|
||||
end
|
||||
|
||||
local function as_integer(v, def)
|
||||
def = def or 0
|
||||
local num = math.floor(tonumber(v) or def)
|
||||
if num > -math.huge and num < math.huge then
|
||||
return num
|
||||
end
|
||||
return def
|
||||
end
|
||||
|
||||
local function add_single_video(json)
|
||||
local streamurl = ""
|
||||
local max_bitrate = 0
|
||||
local reqfmts = json["requested_formats"]
|
||||
local formats = json["requested_formats"]
|
||||
local duration = as_integer(json["duration"])
|
||||
|
||||
local use_all_formats = o.all_formats
|
||||
local all_formats = json["formats"]
|
||||
if use_all_formats and all_formats and (#all_formats > 0) then
|
||||
formats = all_formats
|
||||
end
|
||||
|
||||
-- prefer manifest_url if present
|
||||
if o.use_manifests and valid_manifest(json) then
|
||||
@ -316,10 +360,11 @@ local function add_single_video(json)
|
||||
end
|
||||
|
||||
-- DASH/split tracks
|
||||
elseif reqfmts then
|
||||
elseif formats then
|
||||
local streams = {}
|
||||
local single_url = nil
|
||||
|
||||
for _, track in pairs(reqfmts) do
|
||||
for _, track in pairs(formats) do
|
||||
local edl_track = nil
|
||||
edl_track = edl_track_joined(track.fragments,
|
||||
track.protocol, json.is_live,
|
||||
@ -327,24 +372,46 @@ local function add_single_video(json)
|
||||
if not edl_track and not url_is_safe(track.url) then
|
||||
return
|
||||
end
|
||||
local media_type = nil
|
||||
local codec = nil
|
||||
if track.vcodec and track.vcodec ~= "none" then
|
||||
-- video track
|
||||
streams[#streams + 1] = edl_track or track.url
|
||||
media_type = "video"
|
||||
codec = track.vcodec
|
||||
elseif track.vcodec == "none" then
|
||||
-- audio track
|
||||
streams[#streams + 1] = edl_track or track.url
|
||||
media_type = "audio"
|
||||
codec = track.acodec
|
||||
end
|
||||
if not media_type then
|
||||
return
|
||||
end
|
||||
local url = edl_track or track.url
|
||||
local hdr = {"!new_stream", "!no_clip", "!no_chapters"}
|
||||
if use_all_formats then
|
||||
local codec = map_codec_to_mpv(codec)
|
||||
hdr[#hdr + 1] = "!delay_open,media_type=" .. media_type ..
|
||||
",codec=" .. (codec or "null") .. ",w=" ..
|
||||
as_integer(track.width) .. ",h=" .. as_integer(track.height)
|
||||
local size = as_integer(track["filesize"])
|
||||
local byterate = 0
|
||||
if size > 0 and duration > 0 then
|
||||
byterate = as_integer(size / duration)
|
||||
end
|
||||
hdr[#hdr + 1] = "!track_meta,title=" ..
|
||||
edl_escape(track.format_note or "") ..
|
||||
",byterate=" .. byterate
|
||||
end
|
||||
hdr[#hdr + 1] = edl_escape(url)
|
||||
streams[#streams + 1] = table.concat(hdr, ";")
|
||||
-- In case there is only 1 of these streams.
|
||||
-- Note: assumes it has no important EDL headers
|
||||
single_url = url
|
||||
end
|
||||
|
||||
if #streams > 1 then
|
||||
-- merge them via EDL
|
||||
for i = 1, #streams do
|
||||
streams[i] = "!no_clip;!no_chapters;" .. edl_escape(streams[i])
|
||||
end
|
||||
streamurl = "edl://" ..
|
||||
table.concat(streams, ";!new_stream;") .. ";"
|
||||
streamurl = "edl://" .. table.concat(streams, ";")
|
||||
else
|
||||
streamurl = streams[1]
|
||||
streamurl = single_url
|
||||
end
|
||||
|
||||
elseif not (json.url == nil) then
|
||||
@ -392,7 +459,7 @@ local function add_single_video(json)
|
||||
|
||||
if not (sub == nil) then
|
||||
local edl = "edl://!no_clip;!delay_open,media_type=sub"
|
||||
local codec = map_codec_to_mpv[sub_info.ext]
|
||||
local codec = map_codec_to_mpv(sub_info.ext)
|
||||
if codec then
|
||||
edl = edl .. ",codec=" .. codec
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user