diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index d181279a41..fb98a04def 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -814,7 +814,6 @@ Program Behavior ``--script-opts`` option (using ``ytdl_hook-`` as prefix): ``try_ytdl_first=`` - If 'yes' will try parsing the URL with youtube-dl first, instead of the default where it's only after mpv failed to open it. This mostly depends on whether most of your URLs need youtube-dl parsing. @@ -855,22 +854,40 @@ Program Behavior slow, which can't be really fixed.) In general, this option is not useful, and was only added to show that it's possible. - ``skip_muxed=`` + There are two cases that must be considered when doing quality/bandwidth + selection: + + 1. Completely separate audio and video streams (DASH-like). Each of + these streams contain either only audio or video, so you can + mix and combine audio/video bandwidths without restriction. This + intuitively matches best with the concept of selecting quality + by track (what ``all_formats`` is supposed to do). + + 2. Separate sets of muxed audio and video streams. Each version of + the media contains both an audio and video stream, and they are + interleaved. In order not to waste bandwidth, you should only + select one of these versions (if, for example, you select an + audio stream, then video will be downloaded, even if you selected + video from a different stream). + + mpv will still represent them as separate tracks, but will set + the title of each track to ``muxed-N``, where ``N`` is replaced + with the youtube-dl format ID of the originating stream. + + Some sites will mix 1. and 2., but we assume that they do so for + compatibility reasons, and there is no reason to use them at all. + + ``force_all_formats=`` If set to 'yes', and ``all_formats`` is also set to 'yes', this will - skip formats that have both audio and video streams (default: yes). + try to represent all youtube-dl reported formats as tracks, even if + mpv would normally use the direct URL reported by it (default: yes). - Some sites that provide multiple qualities will do so with separated - audio and video streams (which is what ``all_formats`` is supposed to - make use of), still provide formats that include both audio and video. - We assume that they do so for compatibility reasons, and ``skip_muxed`` - filters them out. This will make loading faster, and potentially avoid - wasting bandwidth by using only one stream of a muxed stream. On the - other hand, if muxed streams are present, but the separate streams lack - either video or audio or do not exist at all, then the stream selection - as done by youtube-dl (via ``--ytdl-format``) is used. + It appears this normally makes a difference if youtube-dl works on a + master HLS playlist. - This appears to terribly break with some sites that provide a HLS master - playlist on the lowest level. + If this is set to 'no', this specific kind of stream is treated like + ``all_formats`` is set to 'no', and the stream selection as done by + youtube-dl (via ``--ytdl-format``) is used. ``use_manifests=`` Make mpv use the master manifest URL for formats like HLS and DASH, diff --git a/player/lua/ytdl_hook.lua b/player/lua/ytdl_hook.lua index 8951e06c44..7269f3f4b7 100644 --- a/player/lua/ytdl_hook.lua +++ b/player/lua/ytdl_hook.lua @@ -7,7 +7,7 @@ local o = { try_ytdl_first = false, use_manifests = false, all_formats = false, - skip_muxed = true, + force_all_formats = true, } options.read_options(o) @@ -343,8 +343,6 @@ local function formats_to_edl(json, formats, use_all_formats) local duration = as_integer(json["duration"]) local single_url = nil local streams = {} - local separate_present = {} - local muxed_present = false for index, track in ipairs(formats) do local edl_track = nil @@ -376,14 +374,10 @@ local function formats_to_edl(json, formats, use_all_formats) local url = edl_track or track.url local hdr = {"!new_stream", "!no_clip", "!no_chapters"} - local as_muxed = false + local skip = false local params = "" if use_all_formats then - if #tracks > 1 and o.skip_muxed then - as_muxed = true - tracks = {} -- skip - end for _, sub in ipairs(tracks) do -- A single track that is either audio or video. Delay load it. local codec = map_codec_to_mpv(sub.codec) @@ -418,10 +412,6 @@ local function formats_to_edl(json, formats, use_all_formats) hdr[#hdr + 1] = "!track_meta,title=" .. edl_escape(title) .. ",byterate=" .. byterate - if #tracks == 1 then - separate_present[sub.media_type] = true - end - if duration > 0 then params = params .. ",length=" .. duration end @@ -430,23 +420,12 @@ local function formats_to_edl(json, formats, use_all_formats) hdr[#hdr + 1] = edl_escape(url) .. params - if as_muxed then - muxed_present = true - else - streams[#streams + 1] = table.concat(hdr, ";") - end + 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 "skip_muxed" is enabled, we discard formats that have both audio - -- and video aka muxed (because it's a pain). But if the single-media - -- type formats do not provide both video and audio, then discard them - -- and use the muxed streams instead. - res.muxed_needed = muxed_present and (not (separate_present["video"] and - separate_present["audio"])) - -- Merge all tracks into a single virtual file, but avoid EDL if it's -- only a single track (i.e. redundant). if #streams == 1 and single_url then @@ -495,8 +474,13 @@ local function add_single_video(json) if streamurl == "" then -- possibly DASH/split tracks local res = nil + local has_requested_formats = requested_formats and #requested_formats > 0 - if all_formats and o.all_formats then + -- Not having requested_formats usually hints to HLS master playlist + -- usage, which we don't want to split off, at least not yet. + if (all_formats and o.all_formats) and + (has_requested_formats or o.force_all_formats) + then format_info = "all_formats (separate)" res = formats_to_edl(json, all_formats, true) -- Note: since we don't delay-load muxed streams, use normal stream @@ -506,7 +490,7 @@ local function add_single_video(json) end end - if (not res) and requested_formats and #requested_formats > 0 then + if (not res) and has_requested_formats then format_info = "youtube-dl (separate)" res = formats_to_edl(json, requested_formats, false) end