diff --git a/README.md b/README.md index c9fe47a9a9..edd66d4bd5 100644 --- a/README.md +++ b/README.md @@ -342,8 +342,9 @@ ## General Options: extractor plugins; postprocessor plugins can only be loaded from the default plugin directories - --flat-playlist Do not extract the videos of a playlist, - only list them + --flat-playlist Do not extract a playlist's URL result + entries; some entry metadata may be missing + and downloading may be bypassed --no-flat-playlist Fully extract the videos of a playlist (default) --live-from-start Download livestreams from the start. diff --git a/devscripts/changelog_override.json b/devscripts/changelog_override.json index 08ea9666ed..906e5cf728 100644 --- a/devscripts/changelog_override.json +++ b/devscripts/changelog_override.json @@ -234,5 +234,10 @@ "when": "57212a5f97ce367590aaa5c3e9a135eead8f81f7", "short": "[ie/vimeo] Fix API retries (#11351)", "authors": ["bashonly"] + }, + { + "action": "add", + "when": "52c0ffe40ad6e8404d93296f575007b05b04c686", + "short": "[priority] **Login with OAuth is no longer supported for YouTube**\nDue to a change made by the site, yt-dlp is longer able to support OAuth login for YouTube. [Read more](https://github.com/yt-dlp/yt-dlp/issues/11462#issuecomment-2471703090)" } ] diff --git a/yt_dlp/extractor/bandlab.py b/yt_dlp/extractor/bandlab.py index e48d5d3f76..64aa2ba70d 100644 --- a/yt_dlp/extractor/bandlab.py +++ b/yt_dlp/extractor/bandlab.py @@ -1,4 +1,3 @@ - from .common import InfoExtractor from ..utils import ( ExtractorError, diff --git a/yt_dlp/extractor/common.py b/yt_dlp/extractor/common.py index 2aa40a77a7..28a3adf936 100644 --- a/yt_dlp/extractor/common.py +++ b/yt_dlp/extractor/common.py @@ -3767,7 +3767,7 @@ def _merge_subtitles(cls, *dicts, target=None): """ Merge subtitle dictionaries, language by language. """ if target is None: target = {} - for d in dicts: + for d in filter(None, dicts): for lang, subs in d.items(): target[lang] = cls._merge_subtitle_items(target.get(lang, []), subs) return target diff --git a/yt_dlp/extractor/ctvnews.py b/yt_dlp/extractor/ctvnews.py index c3ddcdbee4..6d33f85e4a 100644 --- a/yt_dlp/extractor/ctvnews.py +++ b/yt_dlp/extractor/ctvnews.py @@ -176,7 +176,7 @@ def _real_extract(self, url): self._ninecninemedia_url_result(clip_id) for clip_id in traverse_obj(webpage, ( {find_element(tag='jasper-player-container', html=True)}, - {extract_attributes}, 'axis-ids', {json.loads}, ..., 'axisId')) + {extract_attributes}, 'axis-ids', {json.loads}, ..., 'axisId', {str})) ] return self.playlist_result(entries, page_id) diff --git a/yt_dlp/extractor/facebook.py b/yt_dlp/extractor/facebook.py index 91e2f3489c..c07efcd581 100644 --- a/yt_dlp/extractor/facebook.py +++ b/yt_dlp/extractor/facebook.py @@ -569,7 +569,7 @@ def extract_dash_manifest(vid_data, formats, mpd_url=None): if dash_manifest: formats.extend(self._parse_mpd_formats( compat_etree_fromstring(urllib.parse.unquote_plus(dash_manifest)), - mpd_url=url_or_none(video.get('dash_manifest_url')) or mpd_url)) + mpd_url=url_or_none(vid_data.get('dash_manifest_url')) or mpd_url)) def process_formats(info): # Downloads with browser's User-Agent are rate limited. Working around diff --git a/yt_dlp/extractor/rutube.py b/yt_dlp/extractor/rutube.py index abf9aec727..20365ac5d1 100644 --- a/yt_dlp/extractor/rutube.py +++ b/yt_dlp/extractor/rutube.py @@ -13,7 +13,10 @@ unified_timestamp, url_or_none, ) -from ..utils.traversal import traverse_obj +from ..utils.traversal import ( + subs_list_to_dict, + traverse_obj, +) class RutubeBaseIE(InfoExtractor): @@ -92,11 +95,11 @@ def _extract_formats_and_subtitles(self, options, video_id): hls_url, video_id, 'mp4', fatal=False, m3u8_id='hls') formats.extend(fmts) self._merge_subtitles(subs, target=subtitles) - for caption in traverse_obj(options, ('captions', lambda _, v: url_or_none(v['file']))): - subtitles.setdefault(caption.get('code') or 'ru', []).append({ - 'url': caption['file'], - 'name': caption.get('langTitle'), - }) + self._merge_subtitles(traverse_obj(options, ('captions', ..., { + 'id': 'code', + 'url': 'file', + 'name': ('langTitle', {str}), + }, all, {subs_list_to_dict(lang='ru')})), target=subtitles) return formats, subtitles def _download_and_extract_formats_and_subtitles(self, video_id, query=None): diff --git a/yt_dlp/extractor/soundcloud.py b/yt_dlp/extractor/soundcloud.py index f4beab75b7..03089e98ea 100644 --- a/yt_dlp/extractor/soundcloud.py +++ b/yt_dlp/extractor/soundcloud.py @@ -241,7 +241,7 @@ def _extract_info_dict(self, info, full_title=None, secret_token=None, extract_f format_urls.add(format_url) formats.append({ 'format_id': 'download', - 'ext': urlhandle_detect_ext(urlh) or 'mp3', + 'ext': urlhandle_detect_ext(urlh, default='mp3'), 'filesize': int_or_none(urlh.headers.get('Content-Length')), 'url': format_url, 'quality': 10, diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 6c6a0b3f9d..930d9d4bef 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -419,7 +419,9 @@ def _alias_callback(option, opt_str, value, parser, opts, nargs): general.add_option( '--flat-playlist', action='store_const', dest='extract_flat', const='in_playlist', default=False, - help='Do not extract the videos of a playlist, only list them') + help=( + 'Do not extract a playlist\'s URL result entries; ' + 'some entry metadata may be missing and downloading may be bypassed')) general.add_option( '--no-flat-playlist', action='store_false', dest='extract_flat',