mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-25 02:45:12 +00:00
[ie/soundcloud] Add formats
extractor-arg (#10004)
Authored by: bashonly
This commit is contained in:
parent
eef1e9f44f
commit
beaf832c7a
2 changed files with 42 additions and 19 deletions
|
@ -1841,6 +1841,9 @@ #### jiosaavn
|
||||||
#### afreecatvlive
|
#### afreecatvlive
|
||||||
* `cdn`: One or more CDN IDs to use with the API call for stream URLs, e.g. `gcp_cdn`, `gs_cdn_pc_app`, `gs_cdn_mobile_web`, `gs_cdn_pc_web`
|
* `cdn`: One or more CDN IDs to use with the API call for stream URLs, e.g. `gcp_cdn`, `gs_cdn_pc_app`, `gs_cdn_mobile_web`, `gs_cdn_pc_web`
|
||||||
|
|
||||||
|
#### soundcloud
|
||||||
|
* `formats`: Formats to request from the API. Requested values should be in the format of `{protocol}_{extension}` (omitting the bitrate), e.g. `hls_opus,http_aac`. The `*` character functions as a wildcard, e.g. `*_mp3`, and can passed by itself to request all formats. Known protocols include `http`, `hls` and `hls-aes`; known extensions include `aac`, `opus` and `mp3`. Original `download` formats are always extracted. Default is `http_aac,hls_aac,http_opus,hls_opus,http_mp3,hls_mp3`
|
||||||
|
|
||||||
**Note**: These options may be changed/removed in the future without concern for backward compatibility
|
**Note**: These options may be changed/removed in the future without concern for backward compatibility
|
||||||
|
|
||||||
<!-- MANPAGE: MOVE "INSTALLATION" SECTION HERE -->
|
<!-- MANPAGE: MOVE "INSTALLATION" SECTION HERE -->
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import functools
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
error_to_compat_str,
|
error_to_compat_str,
|
||||||
float_or_none,
|
float_or_none,
|
||||||
int_or_none,
|
int_or_none,
|
||||||
|
join_nonempty,
|
||||||
mimetype2ext,
|
mimetype2ext,
|
||||||
parse_qs,
|
parse_qs,
|
||||||
str_or_none,
|
str_or_none,
|
||||||
|
@ -68,6 +70,16 @@ class SoundcloudBaseIE(InfoExtractor):
|
||||||
'original': 0,
|
'original': 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_DEFAULT_FORMATS = ['http_aac', 'hls_aac', 'http_opus', 'hls_opus', 'http_mp3', 'hls_mp3']
|
||||||
|
|
||||||
|
@functools.cached_property
|
||||||
|
def _is_requested(self):
|
||||||
|
return re.compile(r'|'.join(set(
|
||||||
|
re.escape(pattern).replace(r'\*', r'.*') if pattern != 'default'
|
||||||
|
else '|'.join(map(re.escape, self._DEFAULT_FORMATS))
|
||||||
|
for pattern in self._configuration_arg('formats', ['default'], ie_key=SoundcloudIE)
|
||||||
|
))).fullmatch
|
||||||
|
|
||||||
def _store_client_id(self, client_id):
|
def _store_client_id(self, client_id):
|
||||||
self.cache.store('soundcloud', 'client_id', client_id)
|
self.cache.store('soundcloud', 'client_id', client_id)
|
||||||
|
|
||||||
|
@ -216,7 +228,7 @@ def _extract_info_dict(self, info, full_title=None, secret_token=None, extract_f
|
||||||
redirect_url = (self._download_json(download_url, track_id, fatal=False) or {}).get('redirectUri')
|
redirect_url = (self._download_json(download_url, track_id, fatal=False) or {}).get('redirectUri')
|
||||||
if redirect_url:
|
if redirect_url:
|
||||||
urlh = self._request_webpage(
|
urlh = self._request_webpage(
|
||||||
HEADRequest(redirect_url), track_id, fatal=False)
|
HEADRequest(redirect_url), track_id, 'Checking for original download format', fatal=False)
|
||||||
if urlh:
|
if urlh:
|
||||||
format_url = urlh.url
|
format_url = urlh.url
|
||||||
format_urls.add(format_url)
|
format_urls.add(format_url)
|
||||||
|
@ -258,7 +270,7 @@ def add_format(f, protocol, is_preview=False):
|
||||||
abr = f.get('abr')
|
abr = f.get('abr')
|
||||||
if abr:
|
if abr:
|
||||||
f['abr'] = int(abr)
|
f['abr'] = int(abr)
|
||||||
if protocol == 'hls':
|
if protocol in ('hls', 'hls-aes'):
|
||||||
protocol = 'm3u8' if ext == 'aac' else 'm3u8_native'
|
protocol = 'm3u8' if ext == 'aac' else 'm3u8_native'
|
||||||
else:
|
else:
|
||||||
protocol = 'http'
|
protocol = 'http'
|
||||||
|
@ -274,11 +286,32 @@ def add_format(f, protocol, is_preview=False):
|
||||||
if extract_flat:
|
if extract_flat:
|
||||||
break
|
break
|
||||||
format_url = t['url']
|
format_url = t['url']
|
||||||
stream = None
|
|
||||||
|
|
||||||
|
protocol = traverse_obj(t, ('format', 'protocol', {str}))
|
||||||
|
if protocol == 'progressive':
|
||||||
|
protocol = 'http'
|
||||||
|
if protocol != 'hls' and '/hls' in format_url:
|
||||||
|
protocol = 'hls'
|
||||||
|
if protocol == 'encrypted-hls' or '/encrypted-hls' in format_url:
|
||||||
|
protocol = 'hls-aes'
|
||||||
|
|
||||||
|
ext = None
|
||||||
|
if preset := traverse_obj(t, ('preset', {str_or_none})):
|
||||||
|
ext = preset.split('_')[0]
|
||||||
|
if ext not in KNOWN_EXTENSIONS:
|
||||||
|
ext = mimetype2ext(traverse_obj(t, ('format', 'mime_type', {str})))
|
||||||
|
|
||||||
|
identifier = join_nonempty(protocol, ext, delim='_')
|
||||||
|
if not self._is_requested(identifier):
|
||||||
|
self.write_debug(f'"{identifier}" is not a requested format, skipping')
|
||||||
|
continue
|
||||||
|
|
||||||
|
stream = None
|
||||||
for retry in self.RetryManager(fatal=False):
|
for retry in self.RetryManager(fatal=False):
|
||||||
try:
|
try:
|
||||||
stream = self._download_json(format_url, track_id, query=query, headers=self._HEADERS)
|
stream = self._download_json(
|
||||||
|
format_url, track_id, f'Downloading {identifier} format info JSON',
|
||||||
|
query=query, headers=self._HEADERS)
|
||||||
except ExtractorError as e:
|
except ExtractorError as e:
|
||||||
if isinstance(e.cause, HTTPError) and e.cause.status == 429:
|
if isinstance(e.cause, HTTPError) and e.cause.status == 429:
|
||||||
self.report_warning(
|
self.report_warning(
|
||||||
|
@ -289,27 +322,14 @@ def add_format(f, protocol, is_preview=False):
|
||||||
else:
|
else:
|
||||||
self.report_warning(e.msg)
|
self.report_warning(e.msg)
|
||||||
|
|
||||||
if not isinstance(stream, dict):
|
stream_url = traverse_obj(stream, ('url', {url_or_none}))
|
||||||
continue
|
|
||||||
stream_url = url_or_none(stream.get('url'))
|
|
||||||
if invalid_url(stream_url):
|
if invalid_url(stream_url):
|
||||||
continue
|
continue
|
||||||
format_urls.add(stream_url)
|
format_urls.add(stream_url)
|
||||||
stream_format = t.get('format') or {}
|
|
||||||
protocol = stream_format.get('protocol')
|
|
||||||
if protocol != 'hls' and '/hls' in format_url:
|
|
||||||
protocol = 'hls'
|
|
||||||
ext = None
|
|
||||||
preset = str_or_none(t.get('preset'))
|
|
||||||
if preset:
|
|
||||||
ext = preset.split('_')[0]
|
|
||||||
if ext not in KNOWN_EXTENSIONS:
|
|
||||||
ext = mimetype2ext(stream_format.get('mime_type'))
|
|
||||||
add_format({
|
add_format({
|
||||||
'url': stream_url,
|
'url': stream_url,
|
||||||
'ext': ext,
|
'ext': ext,
|
||||||
}, 'http' if protocol == 'progressive' else protocol,
|
}, protocol, t.get('snipped') or '/preview/' in format_url)
|
||||||
t.get('snipped') or '/preview/' in format_url)
|
|
||||||
|
|
||||||
for f in formats:
|
for f in formats:
|
||||||
f['vcodec'] = 'none'
|
f['vcodec'] = 'none'
|
||||||
|
|
Loading…
Reference in a new issue