aboutsummaryrefslogtreecommitdiffstats
path: root/yt_dlp/downloader/hls.py
diff options
context:
space:
mode:
Diffstat (limited to 'yt_dlp/downloader/hls.py')
-rw-r--r--yt_dlp/downloader/hls.py35
1 files changed, 20 insertions, 15 deletions
diff --git a/yt_dlp/downloader/hls.py b/yt_dlp/downloader/hls.py
index 29be6bdf9..77606b0ed 100644
--- a/yt_dlp/downloader/hls.py
+++ b/yt_dlp/downloader/hls.py
@@ -24,12 +24,16 @@ from ..utils import (
class HlsFD(FragmentFD):
- """ A limited implementation that does not require ffmpeg """
+ """
+ Download segments in a m3u8 manifest. External downloaders can take over
+ the fragment downloads by supporting the 'frag_urls' protocol and
+ re-defining 'supports_manifest' function
+ """
FD_NAME = 'hlsnative'
@staticmethod
- def can_download(manifest, info_dict, allow_unplayable_formats=False, real_downloader=None, with_crypto=can_decrypt_frag):
+ def can_download(manifest, info_dict, allow_unplayable_formats=False, with_crypto=can_decrypt_frag):
UNSUPPORTED_FEATURES = [
# r'#EXT-X-BYTERANGE', # playlists composed of byte ranges of media files [2]
@@ -53,16 +57,15 @@ class HlsFD(FragmentFD):
UNSUPPORTED_FEATURES += [
r'#EXT-X-KEY:METHOD=(?!NONE|AES-128)', # encrypted streams [1]
]
- if real_downloader:
- UNSUPPORTED_FEATURES += [
- r'#EXT-X-BYTERANGE', # playlists composed of byte ranges of media files [2]
- ]
- check_results = [not re.search(feature, manifest) for feature in UNSUPPORTED_FEATURES]
- is_aes128_enc = '#EXT-X-KEY:METHOD=AES-128' in manifest
- check_results.append(with_crypto or not is_aes128_enc)
- check_results.append(not (is_aes128_enc and r'#EXT-X-BYTERANGE' in manifest))
- check_results.append(not info_dict.get('is_live'))
- return all(check_results)
+
+ def check_results():
+ yield not info_dict.get('is_live')
+ is_aes128_enc = '#EXT-X-KEY:METHOD=AES-128' in manifest
+ yield with_crypto or not is_aes128_enc
+ yield not (is_aes128_enc and r'#EXT-X-BYTERANGE' in manifest)
+ for feature in UNSUPPORTED_FEATURES:
+ yield not re.search(feature, manifest)
+ return all(check_results())
def real_download(self, filename, info_dict):
man_url = info_dict['url']
@@ -72,9 +75,7 @@ class HlsFD(FragmentFD):
man_url = urlh.geturl()
s = urlh.read().decode('utf-8', 'ignore')
- real_downloader = _get_real_downloader(info_dict, 'frag_urls', self.params, None)
-
- if not self.can_download(s, info_dict, self.params.get('allow_unplayable_formats'), real_downloader):
+ if not self.can_download(s, info_dict, self.params.get('allow_unplayable_formats')):
if info_dict.get('extra_param_to_segment_url') or info_dict.get('_decryption_key_url'):
self.report_error('pycryptodome not found. Please install it.')
return False
@@ -89,6 +90,10 @@ class HlsFD(FragmentFD):
# fd.add_progress_hook(ph)
return fd.real_download(filename, info_dict)
+ real_downloader = _get_real_downloader(info_dict, 'frag_urls', self.params, None)
+ if real_downloader and not real_downloader.supports_manifest(s):
+ real_downloader = None
+
def is_ad_fragment_start(s):
return (s.startswith('#ANVATO-SEGMENT-INFO') and 'type=ad' in s
or s.startswith('#UPLYNK-SEGMENT') and s.endswith(',ad'))