Repository: yt-dlp/yt-dlp
File: yt_dlp/downloader/hls.py (Python)

Code before:
                ad_frags += 1
                continue
            media_frags += 1

        ctx = {
            'filename': filename,
            'total_frags': media_frags,
            'ad_frags': ad_frags,
        }

        if real_downloader:
            self._prepare_external_frag_download(ctx)
        else:
            self._prepare_and_start_frag_download(ctx, info_dict)

        extra_state = ctx.setdefault('extra_state', {})

        format_index = info_dict.get('format_index')
        extra_query = None
        extra_param_to_segment_url = info_dict.get('extra_param_to_segment_url')
        if extra_param_to_segment_url:
            extra_query = urllib.parse.parse_qs(extra_param_to_segment_url)
        i = 0
        media_sequence = 0
        decrypt_info = {'METHOD': 'NONE'}
        external_aes_key = traverse_obj(info_dict, ('hls_aes', 'key', {str}))
        if external_aes_key:
            external_aes_key = binascii.unhexlify(remove_start(external_aes_key, '0x'))
            assert len(external_aes_key) in (16, 24, 32), 'Invalid length for HLS AES-128 key'
        external_aes_iv = traverse_obj(info_dict, ('hls_aes', 'iv', {str}))
        if external_aes_iv:
            external_aes_iv = binascii.unhexlify(remove_start(external_aes_iv, '0x').zfill(32))
        byte_range = {}
        discontinuity_count = 0
        frag_index = 0
        ad_frag_next = False
        for line in s.splitlines():
            line = line.strip()
            if line:
                if not line.startswith('#'):
                    if format_index and discontinuity_count != format_index:
                        continue
                    if ad_frag_next:
                        continue
                    frag_index += 1
                    if frag_index <= ctx['fragment_index']:
                        continue
                    frag_url = (
                        line
                        if re.match(r'^https?://', line)
                        else urljoin(man_url, line))

Review comment (refactor):
```suggestion
        external_aes_key = traverse_obj(info_dict, ('hls_aes', 'key'))
```
If the extractor sets non string value, it should error

Same below

Code after:
                ad_frags += 1
                continue
            media_frags += 1

        ctx = {
            'filename': filename,
            'total_frags': media_frags,
            'ad_frags': ad_frags,
        }

        if real_downloader:
            self._prepare_external_frag_download(ctx)
        else:
            self._prepare_and_start_frag_download(ctx, info_dict)

        extra_state = ctx.setdefault('extra_state', {})

        format_index = info_dict.get('format_index')
        extra_query = None
        extra_param_to_segment_url = info_dict.get('extra_param_to_segment_url')
        if extra_param_to_segment_url:
            extra_query = urllib.parse.parse_qs(extra_param_to_segment_url)
        i = 0
        media_sequence = 0
        decrypt_info = {'METHOD': 'NONE'}
        external_aes_key = traverse_obj(info_dict, ('hls_aes', 'key'))
        if external_aes_key:
            external_aes_key = binascii.unhexlify(remove_start(external_aes_key, '0x'))
            assert len(external_aes_key) in (16, 24, 32), 'Invalid length for HLS AES-128 key'
        external_aes_iv = traverse_obj(info_dict, ('hls_aes', 'iv'))
        if external_aes_iv:
            external_aes_iv = binascii.unhexlify(remove_start(external_aes_iv, '0x').zfill(32))
        byte_range = {}
        discontinuity_count = 0
        frag_index = 0
        ad_frag_next = False
        for line in s.splitlines():
            line = line.strip()
            if line:
                if not line.startswith('#'):
                    if format_index and discontinuity_count != format_index:
                        continue
                    if ad_frag_next:
                        continue
                    frag_index += 1
                    if frag_index <= ctx['fragment_index']:
                        continue
                    frag_url = urljoin(man_url, line)
                    if extra_query:
                        frag_url = update_url_query(frag_url, extra_query)