parent
30031be974
commit
a538772969
26 changed files with 84 additions and 47 deletions
|
|
@ -3665,6 +3665,7 @@ class YoutubeDL:
|
|||
format_field(f, 'asr', '\t%s', func=format_decimal_suffix),
|
||||
join_nonempty(
|
||||
self._format_out('UNSUPPORTED', 'light red') if f.get('ext') in ('f4f', 'f4m') else None,
|
||||
self._format_out('DRM', 'light red') if f.get('has_drm') else None,
|
||||
format_field(f, 'language', '[%s]'),
|
||||
join_nonempty(format_field(f, 'format_note'),
|
||||
format_field(f, 'container', ignore=(None, f.get('ext'))),
|
||||
|
|
@ -3764,12 +3765,13 @@ class YoutubeDL:
|
|||
source = detect_variant()
|
||||
if VARIANT not in (None, 'pip'):
|
||||
source += '*'
|
||||
klass = type(self)
|
||||
write_debug(join_nonempty(
|
||||
f'{"yt-dlp" if REPOSITORY == "yt-dlp/yt-dlp" else REPOSITORY} version',
|
||||
__version__,
|
||||
f'[{RELEASE_GIT_HEAD}]' if RELEASE_GIT_HEAD else '',
|
||||
'' if source == 'unknown' else f'({source})',
|
||||
'' if _IN_CLI else 'API',
|
||||
'' if _IN_CLI else 'API' if klass == YoutubeDL else f'API:{self.__module__}.{klass.__qualname__}',
|
||||
delim=' '))
|
||||
|
||||
if not _IN_CLI:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import contextlib
|
||||
import errno
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ query content($sessionIdToken: String!, $deviceLocale: String, $contentId: ID!,
|
|||
class AmazonMiniTVSeasonIE(AmazonMiniTVBaseIE):
|
||||
IE_NAME = 'amazonminitv:season'
|
||||
_VALID_URL = r'amazonminitv:season:(?:amzn1\.dv\.gti\.)?(?P<id>[a-f0-9-]+)'
|
||||
IE_DESC = 'Amazon MiniTV Series, "minitv:season:" prefix'
|
||||
IE_DESC = 'Amazon MiniTV Season, "minitv:season:" prefix'
|
||||
_TESTS = [{
|
||||
'url': 'amazonminitv:season:amzn1.dv.gti.0aa996eb-6a1b-4886-a342-387fbd2f1db0',
|
||||
'playlist_mincount': 6,
|
||||
|
|
@ -250,6 +250,7 @@ query getEpisodes($sessionIdToken: String!, $clientId: String, $episodeOrSeasonI
|
|||
class AmazonMiniTVSeriesIE(AmazonMiniTVBaseIE):
|
||||
IE_NAME = 'amazonminitv:series'
|
||||
_VALID_URL = r'amazonminitv:series:(?:amzn1\.dv\.gti\.)?(?P<id>[a-f0-9-]+)'
|
||||
IE_DESC = 'Amazon MiniTV Series, "minitv:series:" prefix'
|
||||
_TESTS = [{
|
||||
'url': 'amazonminitv:series:amzn1.dv.gti.56521d46-b040-4fd5-872e-3e70476a04b0',
|
||||
'playlist_mincount': 3,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,35 @@ class EmbedlyIE(InfoExtractor):
|
|||
'only_matching': True,
|
||||
}]
|
||||
|
||||
_WEBPAGE_TESTS = [{
|
||||
'url': 'http://www.permacultureetc.com/2022/12/comment-greffer-facilement-les-arbres-fruitiers.html',
|
||||
'info_dict': {
|
||||
'id': 'pfUK_ADTvgY',
|
||||
'ext': 'mp4',
|
||||
'title': 'Comment greffer facilement les arbres fruitiers ? (mois par mois)',
|
||||
'description': 'md5:d3a876995e522f138aabb48e040bfb4c',
|
||||
'view_count': int,
|
||||
'upload_date': '20221210',
|
||||
'comment_count': int,
|
||||
'live_status': 'not_live',
|
||||
'channel_id': 'UCsM4_jihNFYe4CtSkXvDR-Q',
|
||||
'channel_follower_count': int,
|
||||
'tags': ['permaculture', 'jardinage', 'dekarz', 'autonomie', 'greffe', 'fruitiers', 'arbres', 'jardin forêt', 'forêt comestible', 'damien'],
|
||||
'playable_in_embed': True,
|
||||
'uploader': 'permaculture agroécologie etc...',
|
||||
'channel': 'permaculture agroécologie etc...',
|
||||
'thumbnail': 'https://i.ytimg.com/vi/pfUK_ADTvgY/sddefault.jpg',
|
||||
'duration': 1526,
|
||||
'channel_url': 'https://www.youtube.com/channel/UCsM4_jihNFYe4CtSkXvDR-Q',
|
||||
'age_limit': 0,
|
||||
'uploader_id': 'permacultureetc',
|
||||
'like_count': int,
|
||||
'uploader_url': 'http://www.youtube.com/user/permacultureetc',
|
||||
'categories': ['Education'],
|
||||
'availability': 'public',
|
||||
},
|
||||
}]
|
||||
|
||||
@classmethod
|
||||
def _extract_from_webpage(cls, url, webpage):
|
||||
# Bypass "ie=cls" and suitable check
|
||||
|
|
|
|||
|
|
@ -133,9 +133,9 @@ class RadikoBaseIE(InfoExtractor):
|
|||
'X-Radiko-AreaId': area_id,
|
||||
'X-Radiko-AuthToken': auth_token,
|
||||
})
|
||||
not_preferred = is_onair and not pcu.startswith(self._HOSTS_FOR_LIVE) or (not is_onair and (pcu.startswith(self._HOSTS_FOR_TIME_FREE_FFMPEG_UNSUPPORTED) or pcu.startswith(self._HOSTS_FOR_LIVE)))
|
||||
for sf in subformats:
|
||||
if not_preferred:
|
||||
if (is_onair ^ pcu.startswith(self._HOSTS_FOR_LIVE)) or (
|
||||
not is_onair and pcu.startswith(self._HOSTS_FOR_TIME_FREE_FFMPEG_UNSUPPORTED)):
|
||||
sf['preference'] = -100
|
||||
sf['format_note'] = 'not preferred'
|
||||
if not is_onair and url_attrib['timefree'] == '1' and time_to_skip:
|
||||
|
|
|
|||
|
|
@ -4459,19 +4459,6 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
|||
return info_dict
|
||||
return wrapper
|
||||
|
||||
def _extract_channel_id(self, webpage):
|
||||
channel_id = self._html_search_meta(
|
||||
'channelId', webpage, 'channel id', default=None)
|
||||
if channel_id:
|
||||
return channel_id
|
||||
channel_url = self._html_search_meta(
|
||||
('og:url', 'al:ios:url', 'al:android:url', 'al:web:url',
|
||||
'twitter:url', 'twitter:app:url:iphone', 'twitter:app:url:ipad',
|
||||
'twitter:app:url:googleplay'), webpage, 'channel url')
|
||||
return self._search_regex(
|
||||
r'https?://(?:www\.)?youtube\.com/channel/([^/?#&])+',
|
||||
channel_url, 'channel id')
|
||||
|
||||
@staticmethod
|
||||
def _extract_basic_item_renderer(item):
|
||||
# Modified from _extract_grid_item_renderer
|
||||
|
|
|
|||
|
|
@ -1031,7 +1031,7 @@ def create_parser():
|
|||
metavar='URL', dest='referer', default=None,
|
||||
help=optparse.SUPPRESS_HELP)
|
||||
workarounds.add_option(
|
||||
'--add-header',
|
||||
'--add-headers',
|
||||
metavar='FIELD:VALUE', dest='headers', default={}, type='str',
|
||||
action='callback', callback=_dict_from_options_callback,
|
||||
callback_kwargs={'multiple_keys': False},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import re
|
||||
|
||||
from .common import PostProcessor
|
||||
from ..utils import Namespace, filter_dict
|
||||
from ..utils import Namespace, filter_dict, function_with_repr
|
||||
|
||||
|
||||
class MetadataParserPP(PostProcessor):
|
||||
|
|
@ -60,6 +60,7 @@ class MetadataParserPP(PostProcessor):
|
|||
f(info)
|
||||
return [], info
|
||||
|
||||
@function_with_repr
|
||||
def interpretter(self, inp, out):
|
||||
def f(info):
|
||||
data_to_parse = self._downloader.evaluate_outtmpl(template, info)
|
||||
|
|
@ -76,6 +77,7 @@ class MetadataParserPP(PostProcessor):
|
|||
out_re = re.compile(self.format_to_regex(out))
|
||||
return f
|
||||
|
||||
@function_with_repr
|
||||
def replacer(self, field, search, replace):
|
||||
def f(info):
|
||||
val = info.get(field)
|
||||
|
|
|
|||
|
|
@ -3650,7 +3650,8 @@ def get_compatible_ext(*, vcodecs, acodecs, vexts, aexts, preferences=None):
|
|||
},
|
||||
}
|
||||
|
||||
sanitize_codec = functools.partial(try_get, getter=lambda x: x[0].split('.')[0].replace('0', ''))
|
||||
sanitize_codec = functools.partial(
|
||||
try_get, getter=lambda x: x[0].split('.')[0].replace('0', '').lower())
|
||||
vcodec, acodec = sanitize_codec(vcodecs), sanitize_codec(acodecs)
|
||||
|
||||
for ext in preferences or COMPATIBLE_CODECS.keys():
|
||||
|
|
@ -3915,7 +3916,7 @@ class download_range_func:
|
|||
and self.chapters == other.chapters and self.ranges == other.ranges)
|
||||
|
||||
def __repr__(self):
|
||||
return f'{type(self).__name__}({self.chapters}, {self.ranges})'
|
||||
return f'{__name__}.{type(self).__name__}({self.chapters}, {self.ranges})'
|
||||
|
||||
|
||||
def parse_dfxp_time_expr(time_expr):
|
||||
|
|
@ -6018,6 +6019,18 @@ class classproperty:
|
|||
return self._cache[cls]
|
||||
|
||||
|
||||
class function_with_repr:
|
||||
def __init__(self, func):
|
||||
functools.update_wrapper(self, func)
|
||||
self.func = func
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self.func(*args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self.func.__module__}.{self.func.__qualname__}'
|
||||
|
||||
|
||||
class Namespace(types.SimpleNamespace):
|
||||
"""Immutable namespace"""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue