aboutsummaryrefslogtreecommitdiffstats
path: root/yt_dlp
diff options
context:
space:
mode:
Diffstat (limited to 'yt_dlp')
-rw-r--r--yt_dlp/YoutubeDL.py7
-rw-r--r--yt_dlp/__init__.py56
-rw-r--r--yt_dlp/extractor/francetv.py2
-rw-r--r--yt_dlp/extractor/funimation.py2
-rw-r--r--yt_dlp/extractor/linkedin.py2
-rw-r--r--yt_dlp/extractor/pbs.py2
-rw-r--r--yt_dlp/extractor/tenplay.py2
-rw-r--r--yt_dlp/extractor/youtube.py27
8 files changed, 51 insertions, 49 deletions
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index 197ec11e6..e078e62ef 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -528,7 +528,6 @@ class YoutubeDL(object):
self.cache = Cache(self)
windows_enable_vt_mode()
- # FIXME: This will break if we ever print color to stdout
self._allow_colors = {
'screen': not self.params.get('no_color') and supports_terminal_sequences(self._screen_file),
'err': not self.params.get('no_color') and supports_terminal_sequences(self._err_file),
@@ -2012,10 +2011,10 @@ class YoutubeDL(object):
# TODO: Add allvideo, allaudio etc by generalizing the code with best/worst selector
if format_spec == 'all':
def selector_function(ctx):
- yield from _check_formats(ctx['formats'])
+ yield from _check_formats(ctx['formats'][::-1])
elif format_spec == 'mergeall':
def selector_function(ctx):
- formats = list(_check_formats(ctx['formats']))
+ formats = list(_check_formats(ctx['formats'][::-1]))
if not formats:
return
merged_format = formats[-1]
@@ -3163,7 +3162,7 @@ class YoutubeDL(object):
return 'images'
else:
return default
- return f'{res} images' if is_images else res
+ return f'img {res}' if is_images else res
def _format_note(self, fdict):
res = ''
diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py
index 63b9b6e2f..7960d3b03 100644
--- a/yt_dlp/__init__.py
+++ b/yt_dlp/__init__.py
@@ -378,8 +378,6 @@ def _real_main(argv=None):
opts.sponsorblock_remove = set()
sponsorblock_query = opts.sponsorblock_mark | opts.sponsorblock_remove
- if (opts.addmetadata or opts.sponsorblock_mark) and opts.addchapters is None:
- opts.addchapters = True
opts.remove_chapters = opts.remove_chapters or []
if (opts.remove_chapters or sponsorblock_query) and opts.sponskrub is not False:
@@ -400,40 +398,32 @@ def _real_main(argv=None):
opts.remuxvideo = False
if opts.allow_unplayable_formats:
- if opts.extractaudio:
- report_conflict('--allow-unplayable-formats', '--extract-audio')
- opts.extractaudio = False
- if opts.remuxvideo:
- report_conflict('--allow-unplayable-formats', '--remux-video')
- opts.remuxvideo = False
- if opts.recodevideo:
- report_conflict('--allow-unplayable-formats', '--recode-video')
- opts.recodevideo = False
- if opts.addmetadata:
- report_conflict('--allow-unplayable-formats', '--add-metadata')
- opts.addmetadata = False
- if opts.embedsubtitles:
- report_conflict('--allow-unplayable-formats', '--embed-subs')
- opts.embedsubtitles = False
- if opts.embedthumbnail:
- report_conflict('--allow-unplayable-formats', '--embed-thumbnail')
- opts.embedthumbnail = False
- if opts.xattrs:
- report_conflict('--allow-unplayable-formats', '--xattrs')
- opts.xattrs = False
- if opts.fixup and opts.fixup.lower() not in ('never', 'ignore'):
- report_conflict('--allow-unplayable-formats', '--fixup')
+ def report_unplayable_conflict(opt_name, arg, default=False, allowed=None):
+ val = getattr(opts, opt_name)
+ if (not allowed and val) or not allowed(val):
+ report_conflict('--allow-unplayable-formats', arg)
+ setattr(opts, opt_name, default)
+
+ report_unplayable_conflict('extractaudio', '--extract-audio')
+ report_unplayable_conflict('remuxvideo', '--remux-video')
+ report_unplayable_conflict('recodevideo', '--recode-video')
+ report_unplayable_conflict('addmetadata', '--embed-metadata')
+ report_unplayable_conflict('addchapters', '--embed-chapters')
+ report_unplayable_conflict('embed_infojson', '--embed-info-json')
+ opts.embed_infojson = False
+ report_unplayable_conflict('embedsubtitles', '--embed-subs')
+ report_unplayable_conflict('embedthumbnail', '--embed-thumbnail')
+ report_unplayable_conflict('xattrs', '--xattrs')
+ report_unplayable_conflict('fixup', '--fixup', default='never', allowed=lambda x: x in (None, 'never', 'ignore'))
opts.fixup = 'never'
- if opts.remove_chapters:
- report_conflict('--allow-unplayable-formats', '--remove-chapters')
- opts.remove_chapters = []
- if opts.sponsorblock_remove:
- report_conflict('--allow-unplayable-formats', '--sponsorblock-remove')
- opts.sponsorblock_remove = set()
- if opts.sponskrub:
- report_conflict('--allow-unplayable-formats', '--sponskrub')
+ report_unplayable_conflict('remove_chapters', '--remove-chapters', default=[])
+ report_unplayable_conflict('sponsorblock_remove', '--sponsorblock-remove', default=set())
+ report_unplayable_conflict('sponskrub', '--sponskrub', default=set())
opts.sponskrub = False
+ if (opts.addmetadata or opts.sponsorblock_mark) and opts.addchapters is None:
+ opts.addchapters = True
+
# PostProcessors
postprocessors = list(opts.add_postprocessors)
if sponsorblock_query:
diff --git a/yt_dlp/extractor/francetv.py b/yt_dlp/extractor/francetv.py
index 3bbab69e6..bc5ef4df9 100644
--- a/yt_dlp/extractor/francetv.py
+++ b/yt_dlp/extractor/francetv.py
@@ -185,7 +185,7 @@ class FranceTVIE(InfoExtractor):
'vcodec': 'none',
'ext': 'mhtml',
'protocol': 'mhtml',
- 'url': 'about:dummy',
+ 'url': 'about:invalid',
'fragments': [{
'path': sheet,
# XXX: not entirely accurate; each spritesheet seems to be
diff --git a/yt_dlp/extractor/funimation.py b/yt_dlp/extractor/funimation.py
index 42711083e..96dad2ca3 100644
--- a/yt_dlp/extractor/funimation.py
+++ b/yt_dlp/extractor/funimation.py
@@ -276,7 +276,7 @@ class FunimationIE(FunimationBaseIE):
def _get_subtitles(self, subtitles, experience_id, episode, display_id, format_name):
if isinstance(episode, str):
webpage = self._download_webpage(
- f'https://www.funimation.com/player/{experience_id}', display_id,
+ f'https://www.funimation.com/player/{experience_id}/', display_id,
fatal=False, note=f'Downloading player webpage for {format_name}')
episode, _, _ = self._get_episode(webpage, episode_id=episode, fatal=False)
diff --git a/yt_dlp/extractor/linkedin.py b/yt_dlp/extractor/linkedin.py
index 9255b3301..bd76ae166 100644
--- a/yt_dlp/extractor/linkedin.py
+++ b/yt_dlp/extractor/linkedin.py
@@ -109,7 +109,7 @@ class LinkedInIE(LinkedInBaseIE):
description = clean_html(get_element_by_class('share-update-card__update-text', webpage))
like_count = int_or_none(get_element_by_class('social-counts-reactions__social-counts-numRections', webpage))
creator = strip_or_none(clean_html(get_element_by_class('comment__actor-name', webpage)))
-
+
sources = self._parse_json(extract_attributes(self._search_regex(r'(<video[^>]+>)', webpage, 'video'))['data-sources'], video_id)
formats = [{
'url': source['src'],
diff --git a/yt_dlp/extractor/pbs.py b/yt_dlp/extractor/pbs.py
index 0eabf9bee..ffaa6bf92 100644
--- a/yt_dlp/extractor/pbs.py
+++ b/yt_dlp/extractor/pbs.py
@@ -193,7 +193,7 @@ class PBSIE(InfoExtractor):
# Article with embedded player (or direct video)
(?:www\.)?pbs\.org/(?:[^/]+/){1,5}(?P<presumptive_id>[^/]+?)(?:\.html)?/?(?:$|[?\#]) |
# Player
- (?:video|player)\.pbs\.org/(?:widget/)?partnerplayer/(?P<player_id>[^/]+)/
+ (?:video|player)\.pbs\.org/(?:widget/)?partnerplayer/(?P<player_id>[^/]+)
)
''' % '|'.join(list(zip(*_STATIONS))[0])
diff --git a/yt_dlp/extractor/tenplay.py b/yt_dlp/extractor/tenplay.py
index c810cfd0d..5b3222ecf 100644
--- a/yt_dlp/extractor/tenplay.py
+++ b/yt_dlp/extractor/tenplay.py
@@ -58,7 +58,7 @@ class TenPlayIE(InfoExtractor):
'email': username,
'password': password,
}))
- return "Bearer " + data['jwt']['accessToken']
+ return 'Bearer ' + data['jwt']['accessToken']
def _real_extract(self, url):
content_id = self._match_id(url)
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
index 41e7fce10..1fbdcd98b 100644
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -508,9 +508,9 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
Extracts visitorData from an API response or ytcfg
Appears to be used to track session state
"""
- return traverse_obj(
- args, (..., ('VISITOR_DATA', ('INNERTUBE_CONTEXT', 'client', 'visitorData'), ('responseContext', 'visitorData'))),
- expected_type=compat_str, get_all=False)
+ return get_first(
+ args, (('VISITOR_DATA', ('INNERTUBE_CONTEXT', 'client', 'visitorData'), ('responseContext', 'visitorData'))),
+ expected_type=str)
@property
def is_authenticated(self):
@@ -1674,7 +1674,20 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
# shorts
'url': 'https://www.youtube.com/shorts/BGQWPY4IigY',
'only_matching': True,
- },
+ }, {
+ 'note': 'Storyboards',
+ 'url': 'https://www.youtube.com/watch?v=5KLPxDtMqe8',
+ 'info_dict': {
+ 'id': '5KLPxDtMqe8',
+ 'ext': 'mhtml',
+ 'format_id': 'sb0',
+ 'title': 'Your Brain is Plastic',
+ 'uploader_id': 'scishow',
+ 'description': 'md5:89cd86034bdb5466cd87c6ba206cd2bc',
+ 'upload_date': '20140324',
+ 'uploader': 'SciShow',
+ }, 'params': {'format': 'mhtml', 'skip_download': True}
+ }
]
@classmethod
@@ -1920,9 +1933,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
return sts
def _mark_watched(self, video_id, player_responses):
- playback_url = traverse_obj(
- player_responses, (..., 'playbackTracking', 'videostatsPlaybackUrl', 'baseUrl'),
- expected_type=url_or_none, get_all=False)
+ playback_url = get_first(
+ player_responses, ('playbackTracking', 'videostatsPlaybackUrl', 'baseUrl'),
+ expected_type=url_or_none)
if not playback_url:
self.report_warning('Unable to mark watched')
return