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

Code before:
                yield not re.search(feature, manifest)
        return all(check_results())

    def real_download(self, filename, info_dict):
        man_url = info_dict['url']
        self.to_screen('[%s] Downloading m3u8 manifest' % self.FD_NAME)

        urlh = self.ydl.urlopen(self._prepare_url(info_dict, man_url))
        man_url = urlh.geturl()
        s = urlh.read().decode('utf-8', 'ignore')

        can_download, message = self.can_download(s, info_dict, self.params.get('allow_unplayable_formats')), None
        if can_download and not compat_pycrypto_AES and '#EXT-X-KEY:METHOD=AES-128' in s:
            if FFmpegFD.available():
                can_download, message = False, 'The stream has AES-128 encryption and pycryptodomex is not available'
            else:
                message = ('The stream has AES-128 encryption and neither ffmpeg nor pycryptodomex are available; '
                           'Decryption will be performed natively, but will be extremely slow')
        if not can_download:
            # NOTE: '#' needs to be escaped since it's a comment character in multiline regex ('\#' doesn't work)
            has_drm = re.search(r'''(?x)(?:
                                [#]EXT-X-FAXS-CM:|                        # Adobe Flash Access
                                [#]EXT-X-(?:SESSION-)?KEY:.*?URI="skd://  # Apple FairPlay
                                )''', s)
            if has_drm and not self.params.get('allow_unplayable_formats'):
                self.report_error('This video is DRM protected')
                return False
            else:
                message = message or 'Unsupported features have been detected'
                fd = FFmpegFD(self.ydl, self.params)
                self.report_warning(f'{message}; extraction will be delegated to {fd.get_basename()}')
                return fd.real_download(filename, info_dict)
        elif message:
            self.report_warning(message)

        is_webvtt = info_dict['ext'] == 'vtt'
        if is_webvtt:
            real_downloader = None  # Packing the fragments is not currently supported for external downloader
        else:
            real_downloader = get_suitable_downloader(
                info_dict, self.params, None, protocol='m3u8_frag_urls', to_stdout=(filename == '-'))
        if real_downloader and not real_downloader.supports_manifest(s):
            real_downloader = None
        if real_downloader:
            self.to_screen(
                '[%s] Fragment downloads will be delegated to %s' % (self.FD_NAME, real_downloader.get_basename()))

        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'))


Review comment (suggestion):
```suggestion
                self.report_error(
                    'This video is DRM protected; Try selecting another format with --format or '
                    'add --check-formats to automatically fallback to the next best format')
```

Code after:
                yield not re.search(feature, manifest)
        return all(check_results())

    def real_download(self, filename, info_dict):
        man_url = info_dict['url']
        self.to_screen('[%s] Downloading m3u8 manifest' % self.FD_NAME)

        urlh = self.ydl.urlopen(self._prepare_url(info_dict, man_url))
        man_url = urlh.geturl()
        s = urlh.read().decode('utf-8', 'ignore')

        can_download, message = self.can_download(s, info_dict, self.params.get('allow_unplayable_formats')), None
        if can_download and not compat_pycrypto_AES and '#EXT-X-KEY:METHOD=AES-128' in s:
            if FFmpegFD.available():
                can_download, message = False, 'The stream has AES-128 encryption and pycryptodomex is not available'
            else:
                message = ('The stream has AES-128 encryption and neither ffmpeg nor pycryptodomex are available; '
                           'Decryption will be performed natively, but will be extremely slow')
        if not can_download:
            has_drm = re.search('|'.join([
                r'#EXT-X-FAXS-CM:',  # Adobe Flash Access
                r'#EXT-X-(?:SESSION-)?KEY:.*?URI="skd://',  # Apple FairPlay
            ]), s)
            if has_drm and not self.params.get('allow_unplayable_formats'):
                self.report_error(
                    'This video is DRM protected; Try selecting another format with --format or '
                    'add --check-formats to automatically fallback to the next best format')
                return False
            message = message or 'Unsupported features have been detected'
            fd = FFmpegFD(self.ydl, self.params)
            self.report_warning(f'{message}; extraction will be delegated to {fd.get_basename()}')
            return fd.real_download(filename, info_dict)
        elif message:
            self.report_warning(message)

        is_webvtt = info_dict['ext'] == 'vtt'
        if is_webvtt:
            real_downloader = None  # Packing the fragments is not currently supported for external downloader
        else:
            real_downloader = get_suitable_downloader(
                info_dict, self.params, None, protocol='m3u8_frag_urls', to_stdout=(filename == '-'))
        if real_downloader and not real_downloader.supports_manifest(s):
            real_downloader = None
        if real_downloader:
            self.to_screen(
                '[%s] Fragment downloads will be delegated to %s' % (self.FD_NAME, real_downloader.get_basename()))

        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'))