From c102b2096525218a6918a46b415fb167786f9656 Mon Sep 17 00:00:00 2001 From: bashonly <88596187+bashonly@users.noreply.github.com> Date: Fri, 26 Jun 2026 17:36:35 -0500 Subject: [PATCH] [cleanup] Replace dead example/test URL (#17061) * Replace dead example URL in documentation * Replace primary Youtube test URL * Remove obsolete `test_youtube_lists` module Closes #12263 Authored by: bashonly --- CONTRIBUTING.md | 2 +- README.md | 36 ++++----- devscripts/make_issue_template.py | 4 +- test/test_youtube_lists.py | 71 ------------------ yt_dlp/extractor/commonmistakes.py | 2 +- yt_dlp/extractor/commonprotocols.py | 2 +- yt_dlp/extractor/generic.py | 2 +- yt_dlp/extractor/youtube/_mistakes.py | 4 +- yt_dlp/extractor/youtube/_video.py | 102 +++++++++++++------------- 9 files changed, 78 insertions(+), 147 deletions(-) delete mode 100644 test/test_youtube_lists.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3abd30c21b..ae58f4811b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,7 +76,7 @@ For bug reports, this means that your report should contain the **complete** out If the error is `ERROR: Unable to extract ...` and you cannot reproduce it from multiple countries, add `--write-pages` and upload the `.dump` files you get [somewhere](https://gist.github.com). -**Site support requests must contain an example URL**. An example URL is a URL you might want to download, like `https://www.youtube.com/watch?v=BaW_jenozKc`. There should be an obvious video present. Except under very special circumstances, the main page of a video service (e.g. `https://www.youtube.com/`) is *not* an example URL. +**Site support requests must contain an example URL**. An example URL is a URL you might want to download, like `https://www.youtube.com/watch?v=YE7VzlLtp-4`. There should be an obvious video present. Except under very special circumstances, the main page of a video service (e.g. `https://www.youtube.com/`) is *not* an example URL. ### Are you using the latest version? diff --git a/README.md b/README.md index 517ce78420..5400f97af7 100644 --- a/README.md +++ b/README.md @@ -1264,7 +1264,7 @@ As an alternative to using the `.netrc` file, which has the disadvantage of keep E.g. To use an encrypted `.netrc` file stored as `.authinfo.gpg` ``` -yt-dlp --netrc-cmd 'gpg --decrypt ~/.authinfo.gpg' 'https://www.youtube.com/watch?v=BaW_jenozKc' +yt-dlp --netrc-cmd 'gpg --decrypt ~/.authinfo.gpg' 'https://www.youtube.com/watch?v=YE7VzlLtp-4' ``` @@ -1454,7 +1454,7 @@ Available only in `--sponsorblock-chapter-title`: - `name` (string): Friendly name of the smallest category - `type` (string): The [SponsorBlock action type](https://wiki.sponsor.ajay.app/w/Types#Action_Type) of the chapter -Each aforementioned sequence when referenced in an output template will be replaced by the actual value corresponding to the sequence name. E.g. for `-o %(title)s-%(id)s.%(ext)s` and an mp4 video with title `yt-dlp test video` and id `BaW_jenozKc`, this will result in a `yt-dlp test video-BaW_jenozKc.mp4` file created in the current directory. +Each aforementioned sequence when referenced in an output template will be replaced by the actual value corresponding to the sequence name. E.g. for `-o %(title)s-%(id)s.%(ext)s` and an mp4 video with title `yt-dlp test video` and id `YE7VzlLtp-4`, this will result in a `yt-dlp test video-YE7VzlLtp-4.mp4` file created in the current directory. **Note**: Some of the sequences are not guaranteed to be present, since they depend on the metadata obtained by a particular extractor. Such sequences will be replaced with placeholder value provided with `--output-na-placeholder` (`NA` by default). @@ -1473,14 +1473,14 @@ In some cases, you don't want special characters such as δΈ­, spaces, or &, such #### Output template examples ```bash -$ yt-dlp --print filename -o "test video.%(ext)s" BaW_jenozKc +$ yt-dlp --print filename -o "test video.%(ext)s" ptd1NN40vMw test video.webm # Literal name with correct extension -$ yt-dlp --print filename -o "%(title)s.%(ext)s" BaW_jenozKc -youtube-dl test video ''_À↭𝕐.webm # All kinds of weird characters +$ yt-dlp --print filename -o "%(title)s.%(ext)s" ptd1NN40vMw +To'y!πŸ€―πŸ˜‚πŸ€¦πŸ»β€β™‚οΈ.webm # All kinds of weird characters -$ yt-dlp --print filename -o "%(title)s.%(ext)s" BaW_jenozKc --restrict-filenames -youtube-dl_test_video_.webm # Restricted file name +$ yt-dlp --print filename -o "%(title)s.%(ext)s" ptd1NN40vMw --restrict-filenames +To_y.webm # Restricted file name # Download YouTube playlist videos in separate directory indexed by video order in a playlist $ yt-dlp -o "%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s" "https://www.youtube.com/playlist?list=PLwiyx1dc3P2JR9N8gQaQN_BCvlSlap7re" @@ -1489,7 +1489,7 @@ $ yt-dlp -o "%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s" "https://www.y $ yt-dlp -o "%(upload_date>%Y)s/%(title)s.%(ext)s" "https://www.youtube.com/playlist?list=PLwiyx1dc3P2JR9N8gQaQN_BCvlSlap7re" # Prefix playlist index with " - " separator, but only if it is available -$ yt-dlp -o "%(playlist_index&{} - |)s%(title)s.%(ext)s" BaW_jenozKc "https://www.youtube.com/user/TheLinuxFoundation/playlists" +$ yt-dlp -o "%(playlist_index&{} - |)s%(title)s.%(ext)s" YE7VzlLtp-4 "https://www.youtube.com/user/TheLinuxFoundation/playlists" # Download all playlists of YouTube channel/user keeping each playlist in separate directory: $ yt-dlp -o "%(uploader)s/%(playlist)s/%(playlist_index)s - %(title)s.%(ext)s" "https://www.youtube.com/user/TheLinuxFoundation/playlists" @@ -1502,13 +1502,13 @@ $ yt-dlp -P "C:/MyVideos" -o "%(series)s/%(season_number)s - %(season)s/%(episod # Download video as "C:\MyVideos\uploader\title.ext", subtitles as "C:\MyVideos\subs\uploader\title.ext" # and put all temporary files in "C:\MyVideos\tmp" -$ yt-dlp -P "C:/MyVideos" -P "temp:tmp" -P "subtitle:subs" -o "%(uploader)s/%(title)s.%(ext)s" BaW_jenozKc --write-subs +$ yt-dlp -P "C:/MyVideos" -P "temp:tmp" -P "subtitle:subs" -o "%(uploader)s/%(title)s.%(ext)s" YE7VzlLtp-4 --write-subs # Download video as "C:\MyVideos\uploader\title.ext" and subtitles as "C:\MyVideos\uploader\subs\title.ext" -$ yt-dlp -P "C:/MyVideos" -o "%(uploader)s/%(title)s.%(ext)s" -o "subtitle:%(uploader)s/subs/%(title)s.%(ext)s" BaW_jenozKc --write-subs +$ yt-dlp -P "C:/MyVideos" -o "%(uploader)s/%(title)s.%(ext)s" -o "subtitle:%(uploader)s/subs/%(title)s.%(ext)s" YE7VzlLtp-4 --write-subs # Stream the video being downloaded to stdout -$ yt-dlp -o - BaW_jenozKc +$ yt-dlp -o - YE7VzlLtp-4 ``` # FORMAT SELECTION @@ -2062,7 +2062,7 @@ From a Python program, you can embed yt-dlp in a more powerful fashion, like thi ```python from yt_dlp import YoutubeDL -URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] +URLS = ['https://www.youtube.com/watch?v=YE7VzlLtp-4'] with YoutubeDL() as ydl: ydl.download(URLS) ``` @@ -2079,7 +2079,7 @@ Most likely, you'll want to use various options. For a list of options available import json import yt_dlp -URL = 'https://www.youtube.com/watch?v=BaW_jenozKc' +URL = 'https://www.youtube.com/watch?v=YE7VzlLtp-4' # ℹ️ See help(yt_dlp.YoutubeDL) for a list of available options and public functions ydl_opts = {} @@ -2108,7 +2108,7 @@ print('Some videos failed to download' if error_code ```python import yt_dlp -URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] +URLS = ['https://www.youtube.com/watch?v=YE7VzlLtp-4'] ydl_opts = { 'format': 'm4a/bestaudio/best', @@ -2128,7 +2128,7 @@ with yt_dlp.YoutubeDL(ydl_opts) as ydl: ```python import yt_dlp -URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] +URLS = ['https://www.youtube.com/watch?v=YE7VzlLtp-4'] def longer_than_a_minute(info, *, incomplete): """Download only videos longer than a minute (or with unknown duration)""" @@ -2149,7 +2149,7 @@ with yt_dlp.YoutubeDL(ydl_opts) as ydl: ```python import yt_dlp -URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] +URLS = ['https://www.youtube.com/watch?v=YE7VzlLtp-4'] class MyLogger: def debug(self, msg): @@ -2190,7 +2190,7 @@ with yt_dlp.YoutubeDL(ydl_opts) as ydl: ```python import yt_dlp -URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] +URLS = ['https://www.youtube.com/watch?v=YE7VzlLtp-4'] # ℹ️ See help(yt_dlp.postprocessor.PostProcessor) class MyCustomPP(yt_dlp.postprocessor.PostProcessor): @@ -2211,7 +2211,7 @@ with yt_dlp.YoutubeDL() as ydl: ```python import yt_dlp -URLS = ['https://www.youtube.com/watch?v=BaW_jenozKc'] +URLS = ['https://www.youtube.com/watch?v=YE7VzlLtp-4'] def format_selector(ctx): """ Select the best video and the best audio that won't result in an mkv. diff --git a/devscripts/make_issue_template.py b/devscripts/make_issue_template.py index 110fcc245a..cb0793fd37 100644 --- a/devscripts/make_issue_template.py +++ b/devscripts/make_issue_template.py @@ -32,7 +32,7 @@ VERBOSE = ''' description: | It should start like this: placeholder: | - [debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=BaW_jenozKc'] + [debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4'] [debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8 [debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe) [debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023) @@ -44,7 +44,7 @@ VERBOSE = ''' [debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest Latest version: nightly@... from yt-dlp/yt-dlp-nightly-builds yt-dlp is up to date (nightly@... from yt-dlp/yt-dlp-nightly-builds) - [youtube] Extracting URL: https://www.youtube.com/watch?v=BaW_jenozKc + [youtube] Extracting URL: https://www.youtube.com/watch?v=YE7VzlLtp-4 render: shell validations: diff --git a/test/test_youtube_lists.py b/test/test_youtube_lists.py deleted file mode 100644 index b3f323e21e..0000000000 --- a/test/test_youtube_lists.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 - -# Allow direct execution -import os -import sys -import unittest - -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - - -from test.helper import FakeYDL, is_download_test -from yt_dlp.extractor import YoutubeIE, YoutubeTabIE -from yt_dlp.utils import ExtractorError - - -@is_download_test -class TestYoutubeLists(unittest.TestCase): - def assertIsPlaylist(self, info): - """Make sure the info has '_type' set to 'playlist'""" - self.assertEqual(info['_type'], 'playlist') - - def test_youtube_playlist_noplaylist(self): - dl = FakeYDL() - dl.params['noplaylist'] = True - ie = YoutubeTabIE(dl) - result = ie.extract('https://www.youtube.com/watch?v=OmJ-4B-mS-Y&list=PLydZ2Hrp_gPRJViZjLFKaBMgCQOYEEkyp&index=2') - self.assertEqual(result['_type'], 'url') - self.assertEqual(result['ie_key'], YoutubeIE.ie_key()) - self.assertEqual(YoutubeIE.extract_id(result['url']), 'OmJ-4B-mS-Y') - - def test_youtube_mix(self): - dl = FakeYDL() - ie = YoutubeTabIE(dl) - result = ie.extract('https://www.youtube.com/watch?v=tyITL_exICo&list=RDCLAK5uy_kLWIr9gv1XLlPbaDS965-Db4TrBoUTxQ8') - entries = list(result['entries']) - self.assertTrue(len(entries) >= 50) - original_video = entries[0] - self.assertEqual(original_video['id'], 'tyITL_exICo') - - def test_youtube_flat_playlist_extraction(self): - dl = FakeYDL() - dl.params['extract_flat'] = True - ie = YoutubeTabIE(dl) - result = ie.extract('https://www.youtube.com/playlist?list=PL4lCao7KL_QFVb7Iudeipvc2BCavECqzc') - self.assertIsPlaylist(result) - entries = list(result['entries']) - self.assertTrue(len(entries) == 1) - video = entries[0] - self.assertEqual(video['_type'], 'url') - self.assertEqual(video['ie_key'], 'Youtube') - self.assertEqual(video['id'], 'BaW_jenozKc') - self.assertEqual(video['url'], 'https://www.youtube.com/watch?v=BaW_jenozKc') - self.assertEqual(video['title'], 'youtube-dl test video "\'/\\À↭𝕐') - self.assertEqual(video['duration'], 10) - self.assertEqual(video['uploader'], 'Philipp Hagemeister') - - def test_youtube_channel_no_uploads(self): - dl = FakeYDL() - dl.params['extract_flat'] = True - ie = YoutubeTabIE(dl) - # no uploads - with self.assertRaisesRegex(ExtractorError, r'no uploads'): - ie.extract('https://www.youtube.com/channel/UC2yXPzFejc422buOIzn_0CA') - - # no uploads and no UCID given - with self.assertRaisesRegex(ExtractorError, r'no uploads'): - ie.extract('https://www.youtube.com/news') - - -if __name__ == '__main__': - unittest.main() diff --git a/yt_dlp/extractor/commonmistakes.py b/yt_dlp/extractor/commonmistakes.py index 8ddb164b97..4ff7bf2ca4 100644 --- a/yt_dlp/extractor/commonmistakes.py +++ b/yt_dlp/extractor/commonmistakes.py @@ -30,7 +30,7 @@ class UnicodeBOMIE(InfoExtractor): _VALID_URL = r'(?P\ufeff)(?P.*)$' _TESTS = [{ - 'url': '\ufeffhttp://www.youtube.com/watch?v=BaW_jenozKc', + 'url': '\ufeffhttp://www.youtube.com/watch?v=YE7VzlLtp-4', 'only_matching': True, }] diff --git a/yt_dlp/extractor/commonprotocols.py b/yt_dlp/extractor/commonprotocols.py index 7b3a5b6546..6d9ba0d81c 100644 --- a/yt_dlp/extractor/commonprotocols.py +++ b/yt_dlp/extractor/commonprotocols.py @@ -62,7 +62,7 @@ class ViewSourceIE(InfoExtractor): _VALID_URL = r'view-source:(?P.+)' _TEST = { - 'url': 'view-source:https://www.youtube.com/watch?v=BaW_jenozKc', + 'url': 'view-source:https://www.youtube.com/watch?v=YE7VzlLtp-4', 'only_matching': True, } diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py index 7c7bb71a74..4443da40e9 100644 --- a/yt_dlp/extractor/generic.py +++ b/yt_dlp/extractor/generic.py @@ -778,7 +778,7 @@ class GenericIE(InfoExtractor): if default_search == 'auto_warning': if re.match(r'^(?:url|URL)$', url): raise ExtractorError( - f'Invalid URL: {url!r} . Call yt-dlp like this: yt-dlp -v "https://www.youtube.com/watch?v=BaW_jenozKc" ', + f'Invalid URL: {url!r} . Call yt-dlp like this: yt-dlp -v "https://www.youtube.com/watch?v=YE7VzlLtp-4" ', expected=True) else: self.report_warning( diff --git a/yt_dlp/extractor/youtube/_mistakes.py b/yt_dlp/extractor/youtube/_mistakes.py index c5eb5161c2..4087d85a5b 100644 --- a/yt_dlp/extractor/youtube/_mistakes.py +++ b/yt_dlp/extractor/youtube/_mistakes.py @@ -47,8 +47,8 @@ class YoutubeTruncatedURLIE(YoutubeBaseInfoExtractor): 'Did you forget to quote the URL? Remember that & is a meta ' 'character in most shells, so you want to put the URL in quotes, ' 'like yt-dlp ' - '"https://www.youtube.com/watch?feature=foo&v=BaW_jenozKc" ' - ' or simply yt-dlp BaW_jenozKc .', + '"https://www.youtube.com/watch?feature=foo&v=YE7VzlLtp-4" ' + ' or simply yt-dlp YE7VzlLtp-4 .', expected=True) diff --git a/yt_dlp/extractor/youtube/_video.py b/yt_dlp/extractor/youtube/_video.py index 9a81c709c9..3796a5527f 100644 --- a/yt_dlp/extractor/youtube/_video.py +++ b/yt_dlp/extractor/youtube/_video.py @@ -152,37 +152,38 @@ class YoutubeIE(YoutubeBaseInfoExtractor): IE_NAME = 'youtube' _TESTS = [{ - 'url': 'https://www.youtube.com/watch?v=BaW_jenozKc&t=1s&end=9', + 'url': 'https://www.youtube.com/watch?v=YE7VzlLtp-4&t=1s&end=9', 'info_dict': { - 'id': 'BaW_jenozKc', + 'id': 'YE7VzlLtp-4', 'ext': 'mp4', - 'title': 'youtube-dl test video "\'/\\À↭𝕐', - 'age_limit': 0, - 'availability': 'public', - 'categories': ['Science & Technology'], - 'channel': 'Philipp Hagemeister', + 'title': 'Big Buck Bunny', + 'description': 'md5:e95316924b5eca2a74b87ab0b290724a', + 'media_type': 'video', + 'uploader': 'Blender', + 'uploader_id': '@BlenderOfficial', + 'uploader_url': 'https://www.youtube.com/@BlenderOfficial', + 'channel': 'Blender', + 'channel_id': 'UCSMOQeBJ2RAnuFungnQOxLg', + 'channel_url': 'https://www.youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg', + 'channel_is_verified': True, 'channel_follower_count': int, - 'channel_id': 'UCLqxVugv74EIW3VWh2NOa3Q', - 'channel_url': 'https://www.youtube.com/channel/UCLqxVugv74EIW3VWh2NOa3Q', 'comment_count': int, - 'description': 'md5:8fb536f4877b8a7455c2ec23794dbc22', - 'duration': 10, - 'end_time': 9, - 'heatmap': 'count:100', - 'like_count': int, - 'live_status': 'not_live', - 'playable_in_embed': True, - 'start_time': 1, - 'tags': 'count:1', - 'thumbnail': r're:https?://i\.ytimg\.com/.+', - 'timestamp': 1349198244, - 'upload_date': '20121002', - 'uploader': 'Philipp Hagemeister', - 'uploader_id': '@PhilippHagemeister', - 'uploader_url': 'https://www.youtube.com/@PhilippHagemeister', 'view_count': int, + 'like_count': int, + 'age_limit': 0, + 'duration': 597, + 'thumbnail': 'https://i.ytimg.com/vi/YE7VzlLtp-4/maxresdefault.jpg', + 'heatmap': 'count:100', + 'start_time': 1.0, + 'end_time': 9.0, + 'categories': ['Film & Animation'], + 'tags': 'count:16', + 'timestamp': 1212060266, + 'upload_date': '20080529', + 'playable_in_embed': True, + 'availability': 'public', + 'live_status': 'not_live', }, - 'skip': 'Video unavailable', }, { 'note': 'Embed-only video (#1746)', 'url': '//www.YouTube.com/watch?v=yZIXLfi8CZQ', @@ -197,35 +198,36 @@ class YoutubeIE(YoutubeBaseInfoExtractor): 'skip': 'Private video', }, { 'note': 'Use the first video ID in the URL', - 'url': 'https://www.youtube.com/watch?v=BaW_jenozKc&v=yZIXLfi8CZQ', + 'url': 'https://www.youtube.com/watch?v=YE7VzlLtp-4&v=BaW_jenozKc', 'info_dict': { - 'id': 'BaW_jenozKc', + 'id': 'YE7VzlLtp-4', 'ext': 'mp4', - 'title': 'youtube-dl test video "\'/\\À↭𝕐', - 'age_limit': 0, - 'availability': 'public', - 'categories': ['Science & Technology'], - 'channel': 'Philipp Hagemeister', + 'title': 'Big Buck Bunny', + 'description': 'md5:e95316924b5eca2a74b87ab0b290724a', + 'media_type': 'video', + 'uploader': 'Blender', + 'uploader_id': '@BlenderOfficial', + 'uploader_url': 'https://www.youtube.com/@BlenderOfficial', + 'channel': 'Blender', + 'channel_id': 'UCSMOQeBJ2RAnuFungnQOxLg', + 'channel_url': 'https://www.youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg', + 'channel_is_verified': True, 'channel_follower_count': int, - 'channel_id': 'UCLqxVugv74EIW3VWh2NOa3Q', - 'channel_url': 'https://www.youtube.com/channel/UCLqxVugv74EIW3VWh2NOa3Q', 'comment_count': int, - 'description': 'md5:8fb536f4877b8a7455c2ec23794dbc22', - 'duration': 10, - 'heatmap': 'count:100', - 'like_count': int, - 'live_status': 'not_live', - 'playable_in_embed': True, - 'tags': 'count:1', - 'thumbnail': r're:https?://i\.ytimg\.com/.+', - 'timestamp': 1349198244, - 'upload_date': '20121002', - 'uploader': 'Philipp Hagemeister', - 'uploader_id': '@PhilippHagemeister', - 'uploader_url': 'https://www.youtube.com/@PhilippHagemeister', 'view_count': int, + 'like_count': int, + 'age_limit': 0, + 'duration': 597, + 'thumbnail': 'https://i.ytimg.com/vi/YE7VzlLtp-4/maxresdefault.jpg', + 'heatmap': 'count:100', + 'categories': ['Film & Animation'], + 'tags': 'count:16', + 'timestamp': 1212060266, + 'upload_date': '20080529', + 'playable_in_embed': True, + 'availability': 'public', + 'live_status': 'not_live', }, - 'skip': 'Video unavailable', }, { 'note': '256k DASH audio (format 141) via DASH manifest', 'url': 'https://www.youtube.com/watch?v=a9LDPn-MO4I', @@ -823,10 +825,10 @@ class YoutubeIE(YoutubeBaseInfoExtractor): 'url': 'sJL6WA-aGkQ', 'only_matching': True, }, { - 'url': 'https://invidio.us/watch?v=BaW_jenozKc', + 'url': 'https://invidio.us/watch?v=YE7VzlLtp-4', 'only_matching': True, }, { - 'url': 'https://redirect.invidious.io/watch?v=BaW_jenozKc', + 'url': 'https://redirect.invidious.io/watch?v=YE7VzlLtp-4', 'only_matching': True, }, { # from https://nitter.pussthecat.org/YouTube/status/1360363141947944964#m