mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2026-06-22 02:34:39 +00:00
Compare commits
No commits in common. "ffb7b7f446b6c67a28c66598ae91f4f2263e0d75" and "e8a6b1ca92f2a0ce2c187668165be23dc5506aab" have entirely different histories.
ffb7b7f446
...
e8a6b1ca92
@ -1840,7 +1840,7 @@ The following extractors use this feature:
|
|||||||
#### youtube
|
#### youtube
|
||||||
* `lang`: Prefer translated metadata (`title`, `description` etc) of this language code (case-sensitive). By default, the video primary language metadata is preferred, with a fallback to `en` translated. See [youtube/_base.py](https://github.com/yt-dlp/yt-dlp/blob/415b4c9f955b1a0391204bd24a7132590e7b3bdb/yt_dlp/extractor/youtube/_base.py#L402-L409) for the list of supported content language codes
|
* `lang`: Prefer translated metadata (`title`, `description` etc) of this language code (case-sensitive). By default, the video primary language metadata is preferred, with a fallback to `en` translated. See [youtube/_base.py](https://github.com/yt-dlp/yt-dlp/blob/415b4c9f955b1a0391204bd24a7132590e7b3bdb/yt_dlp/extractor/youtube/_base.py#L402-L409) for the list of supported content language codes
|
||||||
* `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively
|
* `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively
|
||||||
* `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `android`, `android_sdkless`, `android_vr`, `tv`, `tv_simply`, `tv_downgraded`, and `tv_embedded`. By default, `tv,android_sdkless,web` is used. If no JavaScript runtime is available, then `android_sdkless,web_safari,web` is used. If logged-in cookies are passed to yt-dlp, then `tv_downgraded,web_safari,web` is used for free accounts and `tv_downgraded,web_creator,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only works if the video is embeddable. The `tv_embedded` and `web_creator` clients are added for age-restricted videos if account age-verification is required. Some clients, such as `web` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-ios`
|
* `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `android`, `android_sdkless`, `android_vr`, `tv`, `tv_simply` and `tv_embedded`. By default, `tv,android_sdkless,web` is used. If no JavaScript runtime is available, then `android_sdkless,web_safari,web` is used. If logged-in cookies are passed to yt-dlp, then `tv,web_safari,web` is used for free accounts and `tv,web_creator,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only works if the video is embeddable. The `tv_embedded` and `web_creator` clients are added for age-restricted videos if account age-verification is required. Some clients, such as `web` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-ios`
|
||||||
* `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player), `initial_data` (skip initial data/next ep request). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause issues such as missing formats or metadata. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) and [#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details
|
* `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player), `initial_data` (skip initial data/next ep request). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause issues such as missing formats or metadata. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) and [#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details
|
||||||
* `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. These options are for testing purposes and don't skip any network requests
|
* `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. These options are for testing purposes and don't skip any network requests
|
||||||
* `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp.
|
* `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp.
|
||||||
|
|||||||
@ -488,6 +488,20 @@ class FFmpegFD(ExternalFD):
|
|||||||
if not self.params.get('verbose'):
|
if not self.params.get('verbose'):
|
||||||
args += ['-hide_banner']
|
args += ['-hide_banner']
|
||||||
|
|
||||||
|
args += traverse_obj(info_dict, ('downloader_options', 'ffmpeg_args', ...))
|
||||||
|
|
||||||
|
# These exists only for compatibility. Extractors should use
|
||||||
|
# info_dict['downloader_options']['ffmpeg_args'] instead
|
||||||
|
args += info_dict.get('_ffmpeg_args') or []
|
||||||
|
seekable = info_dict.get('_seekable')
|
||||||
|
if seekable is not None:
|
||||||
|
# setting -seekable prevents ffmpeg from guessing if the server
|
||||||
|
# supports seeking(by adding the header `Range: bytes=0-`), which
|
||||||
|
# can cause problems in some cases
|
||||||
|
# https://github.com/ytdl-org/youtube-dl/issues/11800#issuecomment-275037127
|
||||||
|
# http://trac.ffmpeg.org/ticket/6125#comment:10
|
||||||
|
args += ['-seekable', '1' if seekable else '0']
|
||||||
|
|
||||||
env = None
|
env = None
|
||||||
proxy = self.params.get('proxy')
|
proxy = self.params.get('proxy')
|
||||||
if proxy:
|
if proxy:
|
||||||
@ -507,39 +521,17 @@ class FFmpegFD(ExternalFD):
|
|||||||
env['HTTP_PROXY'] = proxy
|
env['HTTP_PROXY'] = proxy
|
||||||
env['http_proxy'] = proxy
|
env['http_proxy'] = proxy
|
||||||
|
|
||||||
start_time, end_time = info_dict.get('section_start') or 0, info_dict.get('section_end')
|
protocol = info_dict.get('protocol')
|
||||||
|
|
||||||
fallback_input_args = traverse_obj(info_dict, ('downloader_options', 'ffmpeg_args', ...))
|
|
||||||
|
|
||||||
selected_formats = info_dict.get('requested_formats') or [info_dict]
|
|
||||||
for i, fmt in enumerate(selected_formats):
|
|
||||||
is_http = re.match(r'https?://', fmt['url'])
|
|
||||||
cookies = self.ydl.cookiejar.get_cookies_for_url(fmt['url']) if is_http else []
|
|
||||||
if cookies:
|
|
||||||
args.extend(['-cookies', ''.join(
|
|
||||||
f'{cookie.name}={cookie.value}; path={cookie.path}; domain={cookie.domain};\r\n'
|
|
||||||
for cookie in cookies)])
|
|
||||||
if fmt.get('http_headers') and is_http:
|
|
||||||
# Trailing \r\n after each HTTP header is important to prevent warning from ffmpeg:
|
|
||||||
# [http @ 00000000003d2fa0] No trailing CRLF found in HTTP header.
|
|
||||||
args.extend(['-headers', ''.join(f'{key}: {val}\r\n' for key, val in fmt['http_headers'].items())])
|
|
||||||
|
|
||||||
if start_time:
|
|
||||||
args += ['-ss', str(start_time)]
|
|
||||||
if end_time:
|
|
||||||
args += ['-t', str(end_time - start_time)]
|
|
||||||
|
|
||||||
protocol = fmt.get('protocol')
|
|
||||||
|
|
||||||
if protocol == 'rtmp':
|
if protocol == 'rtmp':
|
||||||
player_url = fmt.get('player_url')
|
player_url = info_dict.get('player_url')
|
||||||
page_url = fmt.get('page_url')
|
page_url = info_dict.get('page_url')
|
||||||
app = fmt.get('app')
|
app = info_dict.get('app')
|
||||||
play_path = fmt.get('play_path')
|
play_path = info_dict.get('play_path')
|
||||||
tc_url = fmt.get('tc_url')
|
tc_url = info_dict.get('tc_url')
|
||||||
flash_version = fmt.get('flash_version')
|
flash_version = info_dict.get('flash_version')
|
||||||
live = fmt.get('rtmp_live', False)
|
live = info_dict.get('rtmp_live', False)
|
||||||
conn = fmt.get('rtmp_conn')
|
conn = info_dict.get('rtmp_conn')
|
||||||
if player_url is not None:
|
if player_url is not None:
|
||||||
args += ['-rtmp_swfverify', player_url]
|
args += ['-rtmp_swfverify', player_url]
|
||||||
if page_url is not None:
|
if page_url is not None:
|
||||||
@ -560,6 +552,26 @@ class FFmpegFD(ExternalFD):
|
|||||||
elif isinstance(conn, str):
|
elif isinstance(conn, str):
|
||||||
args += ['-rtmp_conn', conn]
|
args += ['-rtmp_conn', conn]
|
||||||
|
|
||||||
|
start_time, end_time = info_dict.get('section_start') or 0, info_dict.get('section_end')
|
||||||
|
|
||||||
|
selected_formats = info_dict.get('requested_formats') or [info_dict]
|
||||||
|
for i, fmt in enumerate(selected_formats):
|
||||||
|
is_http = re.match(r'https?://', fmt['url'])
|
||||||
|
cookies = self.ydl.cookiejar.get_cookies_for_url(fmt['url']) if is_http else []
|
||||||
|
if cookies:
|
||||||
|
args.extend(['-cookies', ''.join(
|
||||||
|
f'{cookie.name}={cookie.value}; path={cookie.path}; domain={cookie.domain};\r\n'
|
||||||
|
for cookie in cookies)])
|
||||||
|
if fmt.get('http_headers') and is_http:
|
||||||
|
# Trailing \r\n after each HTTP header is important to prevent warning from ffmpeg:
|
||||||
|
# [http @ 00000000003d2fa0] No trailing CRLF found in HTTP header.
|
||||||
|
args.extend(['-headers', ''.join(f'{key}: {val}\r\n' for key, val in fmt['http_headers'].items())])
|
||||||
|
|
||||||
|
if start_time:
|
||||||
|
args += ['-ss', str(start_time)]
|
||||||
|
if end_time:
|
||||||
|
args += ['-t', str(end_time - start_time)]
|
||||||
|
|
||||||
url = fmt['url']
|
url = fmt['url']
|
||||||
if self.params.get('enable_file_urls') and url.startswith('file:'):
|
if self.params.get('enable_file_urls') and url.startswith('file:'):
|
||||||
# The default protocol_whitelist is 'file,crypto,data' when reading local m3u8 URLs,
|
# The default protocol_whitelist is 'file,crypto,data' when reading local m3u8 URLs,
|
||||||
@ -574,7 +586,6 @@ class FFmpegFD(ExternalFD):
|
|||||||
# https://trac.ffmpeg.org/ticket/2702
|
# https://trac.ffmpeg.org/ticket/2702
|
||||||
url = re.sub(r'^file://(?:localhost)?/', 'file:' if os.name == 'nt' else 'file:/', url)
|
url = re.sub(r'^file://(?:localhost)?/', 'file:' if os.name == 'nt' else 'file:/', url)
|
||||||
|
|
||||||
args += traverse_obj(fmt, ('downloader_options', 'ffmpeg_args', ...)) or fallback_input_args
|
|
||||||
args += [*self._configuration_args((f'_i{i + 1}', '_i')), '-i', url]
|
args += [*self._configuration_args((f'_i{i + 1}', '_i')), '-i', url]
|
||||||
|
|
||||||
if not (start_time or end_time) or not self.params.get('force_keyframes_at_cuts'):
|
if not (start_time or end_time) or not self.params.get('force_keyframes_at_cuts'):
|
||||||
|
|||||||
@ -327,17 +327,6 @@ INNERTUBE_CLIENTS = {
|
|||||||
# See: https://github.com/youtube/cobalt/blob/main/cobalt/browser/user_agent/user_agent_platform_info.cc#L506
|
# See: https://github.com/youtube/cobalt/blob/main/cobalt/browser/user_agent/user_agent_platform_info.cc#L506
|
||||||
'AUTHENTICATED_USER_AGENT': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/25.lts.30.1034943-gold (unlike Gecko), Unknown_TV_Unknown_0/Unknown (Unknown, Unknown)',
|
'AUTHENTICATED_USER_AGENT': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/25.lts.30.1034943-gold (unlike Gecko), Unknown_TV_Unknown_0/Unknown (Unknown, Unknown)',
|
||||||
},
|
},
|
||||||
'tv_downgraded': {
|
|
||||||
'INNERTUBE_CONTEXT': {
|
|
||||||
'client': {
|
|
||||||
'clientName': 'TVHTML5',
|
|
||||||
'clientVersion': '4',
|
|
||||||
'userAgent': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/Version',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'INNERTUBE_CONTEXT_CLIENT_NAME': 7,
|
|
||||||
'SUPPORTS_COOKIES': True,
|
|
||||||
},
|
|
||||||
'tv_simply': {
|
'tv_simply': {
|
||||||
'INNERTUBE_CONTEXT': {
|
'INNERTUBE_CONTEXT': {
|
||||||
'client': {
|
'client': {
|
||||||
|
|||||||
@ -147,9 +147,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
_SUBTITLE_FORMATS = ('json3', 'srv1', 'srv2', 'srv3', 'ttml', 'srt', 'vtt')
|
_SUBTITLE_FORMATS = ('json3', 'srv1', 'srv2', 'srv3', 'ttml', 'srt', 'vtt')
|
||||||
_DEFAULT_CLIENTS = ('tv', 'android_sdkless', 'web')
|
_DEFAULT_CLIENTS = ('tv', 'android_sdkless', 'web')
|
||||||
_DEFAULT_JSLESS_CLIENTS = ('android_sdkless', 'web_safari', 'web')
|
_DEFAULT_JSLESS_CLIENTS = ('android_sdkless', 'web_safari', 'web')
|
||||||
_DEFAULT_AUTHED_CLIENTS = ('tv_downgraded', 'web_safari', 'web')
|
_DEFAULT_AUTHED_CLIENTS = ('tv', 'web_safari', 'web')
|
||||||
# Premium does not require POT (except for subtitles)
|
# Premium does not require POT (except for subtitles)
|
||||||
_DEFAULT_PREMIUM_CLIENTS = ('tv_downgraded', 'web_creator', 'web')
|
_DEFAULT_PREMIUM_CLIENTS = ('tv', 'web_creator', 'web')
|
||||||
|
|
||||||
_GEO_BYPASS = False
|
_GEO_BYPASS = False
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user