Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/angel.py (Python)

Code before:
        'info_dict': {
            'id': '8dfb714d-bca5-4812-8125-24fb9514cd10',
            'ext': 'mp4',
            'title': 'The Chosen S1 E1: I Have Called You By Name',
            'description': 'Two brothers struggle with their tax debts to Rome while a woman in the Red Quarter wrestles with her demons.',
            'thumbnail': r're:^https?://images.angelstudios.com/.*\.jpeg$'
        }
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        json_ld = self._search_json_ld(webpage, video_id)

        formats, subtitles = self._extract_m3u8_formats_and_subtitles(
            json_ld.get('url'), video_id, m3u8_id='hls', note='Downloading HD m3u8 information',
            errnote='Unable to download HD m3u8 information')

        return {
            'id': video_id,
            'title': json_ld.get('title') or self._og_search_title or '',
            'description': json_ld.get('description') or self._og_search_description(webpage) or None,
            'thumbnails': [{
                # Second group has unnecessary data about transformations of the thumbnail
                'url': re.sub(r'^(.+/upload)(/.+)(/angel-app/.+)$', r'\1\3.jpeg', item.get('url'))
            } for item in json_ld.get('thumbnails') if url_or_none(item.get('url'))],
            'formats': formats,
            'subtitles': subtitles
        }


Review comment (suggestion):
```suggestion
                'url': re.sub(r'(/upload)/.+(/angel-app/.+)', r'\1\2.jpeg', item['url'])
```

Code after:
        'url': 'https://www.angel.com/watch/the-chosen/episode/8dfb714d-bca5-4812-8125-24fb9514cd10/season-1/episode-1/i-have-called-you-by-name',
        'md5': 'e4774bad0a5f0ad2e90d175cafdb797d',
        'info_dict': {
            'id': '8dfb714d-bca5-4812-8125-24fb9514cd10',
            'ext': 'mp4',
            'title': 'The Chosen Season 1, Episode 1: I Have Called You By Name',
            'description': 'md5:aadfb4827a94415de5ff6426e6dee3be',
            'thumbnail': r're:^https?://images.angelstudios.com/image/upload/angel-app/.*$',
            'duration': 3276.0
        }
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        json_ld = self._search_json_ld(webpage, video_id)

        formats, subtitles = self._extract_m3u8_formats_and_subtitles(
            json_ld.pop('url'), video_id, note='Downloading HD m3u8 information')

        info_dict = {
            'id': video_id,
            'title': self._og_search_title(webpage),
            'description': self._og_search_description(webpage),
            'formats': formats,
            'subtitles': subtitles
        }

        # Angel uses cloudinary in the background and supports image transformations.
        # We remove these transformations and return the source file
        base_thumbnail_url = url_or_none(self._og_search_thumbnail(webpage)) or json_ld.pop('thumbnails')
        if base_thumbnail_url:
            info_dict['thumbnail'] = re.sub(r'(/upload)/.+(/angel-app/.+)$', r'\1\2', base_thumbnail_url)

        return merge_dicts(info_dict, json_ld)