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. "a7113722ec33f30fc898caee9242af2b82188a53" and "fca94ac5d63ed6578b5cd9c8129d97a8a713c39a" have entirely different histories.
a7113722ec
...
fca94ac5d6
@ -94,19 +94,12 @@ class HlsFD(FragmentFD):
|
|||||||
can_download, message = self.can_download(s, info_dict, self.params.get('allow_unplayable_formats')), None
|
can_download, message = self.can_download(s, info_dict, self.params.get('allow_unplayable_formats')), None
|
||||||
if can_download:
|
if can_download:
|
||||||
has_ffmpeg = FFmpegFD.available()
|
has_ffmpeg = FFmpegFD.available()
|
||||||
if not Cryptodome.AES and '#EXT-X-KEY:METHOD=AES-128' in s:
|
no_crypto = not Cryptodome.AES and '#EXT-X-KEY:METHOD=AES-128' in s
|
||||||
# Even if pycryptodomex isn't available, force HlsFD for m3u8s that won't work with ffmpeg
|
if no_crypto and has_ffmpeg:
|
||||||
ffmpeg_can_dl = not traverse_obj(info_dict, ((
|
can_download, message = False, 'The stream has AES-128 encryption and pycryptodomex is not available'
|
||||||
'extra_param_to_segment_url', 'extra_param_to_key_url',
|
elif no_crypto:
|
||||||
'hls_media_playlist_data', ('hls_aes', ('uri', 'key', 'iv')),
|
message = ('The stream has AES-128 encryption and neither ffmpeg nor pycryptodomex are available; '
|
||||||
), any))
|
'Decryption will be performed natively, but will be extremely slow')
|
||||||
message = 'The stream has AES-128 encryption and {} available'.format(
|
|
||||||
'neither ffmpeg nor pycryptodomex are' if ffmpeg_can_dl and not has_ffmpeg else
|
|
||||||
'pycryptodomex is not')
|
|
||||||
if has_ffmpeg and ffmpeg_can_dl:
|
|
||||||
can_download = False
|
|
||||||
else:
|
|
||||||
message += '; decryption will be performed natively, but will be extremely slow'
|
|
||||||
elif info_dict.get('extractor_key') == 'Generic' and re.search(r'(?m)#EXT-X-MEDIA-SEQUENCE:(?!0$)', s):
|
elif info_dict.get('extractor_key') == 'Generic' and re.search(r'(?m)#EXT-X-MEDIA-SEQUENCE:(?!0$)', s):
|
||||||
install_ffmpeg = '' if has_ffmpeg else 'install ffmpeg and '
|
install_ffmpeg = '' if has_ffmpeg else 'install ffmpeg and '
|
||||||
message = ('Live HLS streams are not supported by the native downloader. If this is a livestream, '
|
message = ('Live HLS streams are not supported by the native downloader. If this is a livestream, '
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import re
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..networking.exceptions import HTTPError
|
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
ExtractorError,
|
ExtractorError,
|
||||||
UserNotLive,
|
UserNotLive,
|
||||||
@ -189,7 +188,6 @@ class TwitchBaseIE(InfoExtractor):
|
|||||||
}] if thumbnail else None
|
}] if thumbnail else None
|
||||||
|
|
||||||
def _extract_twitch_m3u8_formats(self, path, video_id, token, signature, live_from_start=False):
|
def _extract_twitch_m3u8_formats(self, path, video_id, token, signature, live_from_start=False):
|
||||||
try:
|
|
||||||
formats = self._extract_m3u8_formats(
|
formats = self._extract_m3u8_formats(
|
||||||
f'{self._USHER_BASE}/{path}/{video_id}.m3u8', video_id, 'mp4', query={
|
f'{self._USHER_BASE}/{path}/{video_id}.m3u8', video_id, 'mp4', query={
|
||||||
'allow_source': 'true',
|
'allow_source': 'true',
|
||||||
@ -203,25 +201,6 @@ class TwitchBaseIE(InfoExtractor):
|
|||||||
'sig': signature,
|
'sig': signature,
|
||||||
'token': token,
|
'token': token,
|
||||||
})
|
})
|
||||||
except ExtractorError as e:
|
|
||||||
if (
|
|
||||||
not isinstance(e.cause, HTTPError)
|
|
||||||
or e.cause.status != 403
|
|
||||||
or e.cause.response.get_header('content-type') != 'application/json'
|
|
||||||
):
|
|
||||||
raise
|
|
||||||
|
|
||||||
error_info = traverse_obj(e.cause.response.read(), ({json.loads}, 0, {dict})) or {}
|
|
||||||
if error_info.get('error_code') in ('vod_manifest_restricted', 'unauthorized_entitlements'):
|
|
||||||
common_msg = 'access to this subscriber-only content'
|
|
||||||
if self._get_cookies('https://gql.twitch.tv').get('auth-token'):
|
|
||||||
raise ExtractorError(f'Your account does not have {common_msg}', expected=True)
|
|
||||||
self.raise_login_required(f'You must be logged into an account that has {common_msg}')
|
|
||||||
|
|
||||||
if error_msg := join_nonempty('error_code', 'error', from_dict=error_info, delim=': '):
|
|
||||||
raise ExtractorError(error_msg, expected=True)
|
|
||||||
raise
|
|
||||||
|
|
||||||
for fmt in formats:
|
for fmt in formats:
|
||||||
if fmt.get('vcodec') and fmt['vcodec'].startswith('av01'):
|
if fmt.get('vcodec') and fmt['vcodec'].startswith('av01'):
|
||||||
# mpegts does not yet have proper support for av1
|
# mpegts does not yet have proper support for av1
|
||||||
|
|||||||
@ -3978,9 +3978,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
def process_language(container, base_url, lang_code, sub_name, client_name, query):
|
def process_language(container, base_url, lang_code, sub_name, client_name, query):
|
||||||
lang_subs = container.setdefault(lang_code, [])
|
lang_subs = container.setdefault(lang_code, [])
|
||||||
for fmt in self._SUBTITLE_FORMATS:
|
for fmt in self._SUBTITLE_FORMATS:
|
||||||
# xosf=1 results in undesirable text position data for vtt, json3 & srv* subtitles
|
query = {**query, 'fmt': fmt}
|
||||||
# See: https://github.com/yt-dlp/yt-dlp/issues/13654
|
|
||||||
query = {**query, 'fmt': fmt, 'xosf': []}
|
|
||||||
lang_subs.append({
|
lang_subs.append({
|
||||||
'ext': fmt,
|
'ext': fmt,
|
||||||
'url': urljoin('https://www.youtube.com', update_url_query(base_url, query)),
|
'url': urljoin('https://www.youtube.com', update_url_query(base_url, query)),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user