an empty value to a commandline option usually means that parameter does
not expect anything, but in case of `--proxy`, yt-dlp use an empty value to
disable proxy setting, the empty value need to be passed to `--proxy`
Add support for tracking playlist_title and playlist_id metadata
corresponding to a given playlist url and the entries associated
with it.
This allows the inclusion of ytdl_playlist_title and ytdl_playlist_id
in the metadata property for single videos which have a corresponding
playlist-path property.
This commit also resolvesyt-dlp/yt-dlp#11234
Currently by default mpv sets --all-subs when calling yt-dlp for JSON
info. --all-subs is an option that simply expands to --sub-langs all
--write-subs. --write-subs is special that without it yt-dlp will no
longer extract any subtitle info.
mpv's yt-dlp hook has a logic that if user specify any sub-langs in
--ytdl-raw-options, it no longer uses --all-subs. Unfortunately, this
means unaware users will not get any subtitle any more until they study
the mpv internal code and add their own --write-subs.
This PR always specifies --write-srt, an alias of --write-subs, in the
hook, so users don't have to. The alias is used to maintain
compatibility with youtube-dl.
Fixes issue #14818
By the default mpv tries opening URLs with ffmpeg first, and users who
don't configure try_ytdl_first get a slower startup for youtube URLs, on
top of yt-dlp already being slow.
Fix this by adding a script-opt of URL pattern to try with ytdl first.
Youtube and twitch are included by default.
Compared to the alternative of trying ytdl first by default and
excluding URLs with a media extension, this only works for the sites
explicitly included in the new option's value, but doesn't have false
positives on media URLs without an extension.
It's useful for user scripts to be able to use the same ytdl binary that
ytdl_hook uses without having to replicate ytdl_hook's process of
searching for the ytdl binary.
Some user scripts might also find it useful to be able to access ytdl's
json output that the ytdl_hook already receives, sparing user scripts
from having to make a duplicate ytdl binary invocation to get the json
output.
Providing just the json output is not enough though, as ytdl doesn't communicate
errors though it -- if an error occurs, ytdl provides no json output and instead
prints to stderr. So without stderr, there is no way for user scripts to figure
out why ytdl has failed: no such username / video id, the channel is not live
yet, etc. Because of that, the entire result of the subprocess call is provided
to the user scripts, containing stdout (json), stderr, ytdl's exit code, etc.
For whatever reason, some of the lua code (particularly the osc and
ytdl_hook) is full of a bunch of stuff like if (foo), if not (foo ==
nil), etc. The parenthesis aren't needed in lua and actually just look
weird since nobody actually writes lua like this. You can see most of
the other conditionals are written normally. So cleanup the style to
match when the parenthesis clearly aren't doing anything. Not directly
related, but also add some spaces on a few math operations while we're
at it.
ytdl lists thumbnails in ascending order according to height/preference.
all_formats=yes adds formats from best to worst, so the same should also
be done for thumbnails.
yt-dlp has a preference field for it's thumbnails, and not all of it's
listed thumbnails have fields with their dimensions.
Therefore prefere the preference field when available and fall back to
height if it's not.
Use EDL for single tracks with metadata to set the uploader, channel url
and description metadata with --ytdl-format=best. Currently, these are
only set with the other ytdl formats with video and audio in different
streams.
The uploader tag is commonly available in sites other than Youtube too,
so it may be simpler to always use EDL with single tracks.
An error indicates that something doesn't work, but as long as a
safe url is available, playback is still expected to work.
Thus reduce logging level of MP4 DASH without fragments message and
add a new error message for when there is no safe url available either.
Also adds a missing space.
With dash the first fragment was always considered an init fragment if
there wasn't a duration. However that only makes sense when there are
also other fragments, so check if there are other fragments in addition
to the lack of a duration.
The console.lua check is still kind of dumb since we check an
environment variable to distinguish between wayland and x11, but
otherwise it should be better in theory.
ytdl_hook always set force-media-title, making users unable to force
a media-title via options.
To prevent that, check if force-media-title is already set to avoid
overwriting it.
A better solution would be to use tags like is already done for some
metadata, however that doesn't work when `all_formats=yes` is used.
See cbb8f534b0
A comment was added to hint at why it isn't done via tags.
ref.
https://github.com/mpv-player/mpv/pull/10453#issuecomment-1445277496
This refactors exec to only return the result of the subprocess command,
and makes the rest of run_ytdl_hook use the fields of this result,
because specifying all those return values multiple times is unwieldy
now that exec is called several times, and this is easier to read
anyway.
I removed the line
err = string.format("%s returned '%d'", err, es)
altogether instead of updating the es variable, because there was no
chance of it being executed since it would only happen when
result.killed_by_us is true, but run_ytdl_hook returns early when it is.
Only matters when configuring ytdl_hook with `all_formats=yes`.
So far the tracks were ordered from worst to best quality.
Web players with quality selection always show the highest quality
option at the top. Since tracks are usually listed with the first
track at the top, that should also be the highest quality one.
yt-dlp/youtube-dl sorts it's formats from worst to best.
Iterate in reverse to get best track first.
Every format that was not detected as a video format was added to the
audio tracks. This resulted in e.g. YouTube storyboards from ending up
in the list of audio tracks.
Now formats that are already known to be neither video formats nor audio
formats, will also not end up in any track list.
Formats where it is unknown if they are video or audio get added to
tracks if `force_all_formats` is used, otherwise only
formats that are known to contain video or audio become video or audio
tracks respectively.
https://github.com/yt-dlp/yt-dlp/issues/4373#issuecomment-1186637357
One would expect that e.g.
`--script-opts=ytdl_hook-all_formats=no --ytdl-format=bestaudio` and
`--script-opts=ytdl_hook-all_formats=yes --ytdl-format=bestaudio`
to play the exact same tracks without manual intervention.
This already worked when two formats were requested.
For a single format with `all_formats=yes` it would also play a track
that was not requested when available. This was inconsistant with the
behavior of `all_formats=no` (default), which would not play a second
track when only a single one was requested.
This combined with #10395 now plays the exact same tracks with
`all_formats=yes` as without, even when only one format is requested.
Tracks are marked as default tracks based on what yt-dlp/youtube-dl
returns in the field `requested_formats`. The problem is that this field
only exists when there is more then one requested format.
So `ytdl-format=bestvideo+bestaudio` would have that field,
but `ytdl-format=bestaudio` would not,
leading to no tracks being marked as default tracks.
The requested formats can also be found under `requested_downloads`,
which exists regardless of the number of requested formats.
However when there is more then one requested format,
`requested_downloads` doesn't contain those formats directly and instead
has a field `requested_formats` that is identical to the other
`requested_formats`. Therefore use `requested_downloads` as a fallback
for when `requested_formats` doesn't exist.
The example given in #3024 would not play the correct video when
combined with `--ytdl-raw-options=yes-playlist=`.
Allowing `youtube:tab` as extractor and correcting the id check fixes
that.
Previously only status<0 was considered as error, but status>0 is
also an error (the process exit code). Change to status != 0.
This likely makes little to no difference in practice, because if
stdout is empty or can't be parsed as JSON then it's considered
an error anyway, but still, this is more correct.
Also, on error, add the complete subprocess result to the verbose log.
Some youtube_dl extractors retrieve URLs which contain other URLs
inside of them, for example Funimation, like this:
https://example.com/video?parameter=https://example.net/something
The url_is_safe function uses a pattern to match the protocol at the
start of the URL. Before this commit, this pattern was not compliant
with the URL spec (see the definition of "A URL-scheme string"):
https://url.spec.whatwg.org/#url-writing
Therefore it would match any characters, including "://", until the
last occurence of "://" in the string. Thus the above URL would match
https://example.com/video?parameter=https
which is not in safe_protos so the video will not play.
Now the protocol can only start with a letter and only contain
alphanumerics, "." "+" or "-" as the spec says, so it will only match
the first protocol in the URL ("https" in the above example.)
Previously the URL also had to contain "//" after the ":". Data URLs
do not contain "//": https://datatracker.ietf.org/doc/html/rfc2397
so now the pattern does not look for "//", only ":".
youtube-dl and yt-dlp both support --sub-langs and --srt-lang in
addition to --sub-lang for defining languages of subtitles. This hook
only checked for sub-lang in --ytdl-raw-options and inserted --all-subs
in its absence.
Because youtube-dl is inactive and the yt-dlp fork is becoming more
popular, make mpv use yt-dlp without any extra configuration.
yt-dlp is ordered before youtube-dl because it's more obscure, so users
who have yt-dlp installed are more likely to want to use it rather than
youtube-dl.
Fixes#9208.
This moves the JSON parsing above the main youtube-dl error-handling
block and integrates parsing errors into that block. Now, if a parsing
error occurs, youtube-dl's stderr will be logged as it is with other
errors. This also catches errors that cause youtube-dl to output
"null", which would previously be mishandled as a parsing error and
crash ytdl_hook when it attempted to concatenate the error string from
parse_json.
Shows uploader, channel, description fields. This works only if the
media media is constructed as EDL (for youtube it usually does this),
and if the all_formats option is not set to true (does anyone even use
it?). The former usually happens because youtube serves audio and video
separately, though it will not for live HLS/DASH. The latter uses
delayed media opening, which breaks the global_tags mechanism (see
previous commit).
Some tracks happen to lack bitrate information (ie. no tbr value).
In that case, just ignore the track while computing the max bitrate.
For an example, this is a stream in which all audio tracks
have no bitrate: https://www.raiplay.it/dirette/rai1
The subtitle list is returned in randomized order, because a table (i.e.
JSON object) is used. To make the order stable across repeated
invocations, sort it by language.