code:
import re

from .common import InfoExtractor
from ..compat import (
    compat_urllib_parse_unquote,
    compat_urllib_parse_urlparse,
)
from ..utils import (
    ExtractorError,
    float_or_none,
    sanitized_Request,
    traverse_obj,
    urlencode_postdata,
    USER_AGENTS,
)

class CeskaTelevizeIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?ceskatelevize\.cz/(?:ivysilani|porady)/(?:[^/?#&]+/)*(?P<id>[^/#?]+)'
    _TESTS = [{
        'url': 'http://www.ceskatelevize.cz/ivysilani/10441294653-hyde-park-civilizace/215411058090502/bonus/20641-bonus-01-en',
        'info_dict': {
            'id': '61924494877028507',
            'ext': 'mp4',
            'title': 'Hyde Park Civilizace: Bonus 01 - En',
            'description': 'English Subtittles',
            'thumbnail': r're:^https?://.*\.jpg',
            'duration': 81.3,
        },
        'params': {
            # m3u8 download
            'skip_download': True,
        },
    }, {
        # live stream
        'url': 'http://www.ceskatelevize.cz/ivysilani/zive/ct4/',
        'info_dict': {
            'id': 402,
            'ext': 'mp4',
            'title': r're:^ČT Sport \d{4}-\d{2}-\d{2} \d{2}:\d{2}$',
            'is_live': True,
        },
        'params': {
            # m3u8 download
            'skip_download': True,
        },
        'skip': 'Georestricted to Czech Republic',
    }, {
        'url': 'http://www.ceskatelevize.cz/ivysilani/embed/iFramePlayer.php?hash=d6a3e1370d2e4fa76296b90bad4dfc19673b641e&IDEC=217 562 22150/0004&channelID=1&width=100%25',
        'only_matching': True,
    }, {
        # video with 18+ caution trailer
        'url': 'http://www.ceskatelevize.cz/porady/10520528904-queer/215562210900007-bogotart/',
        'info_dict': {
            'id': '215562210900007-bogotart',
            'title': 'Queer: Bogotart',
            'description': 'Hlavní město Kolumbie v doprovodu queer umělců. Vroucí svět plný vášně, sebevědomí, ale i násilí a bolesti. Připravil Peter Serge Butko',
        },
        'playlist': [{
            'info_dict': {
                'id': '61924494877311053',
                'ext': 'mp4',
                'title': 'Queer: Bogotart (Varování 18+)',
                'duration': 11.9,
            },
        }, {
            'info_dict': {
                'id': '61924494877068022',
                'ext': 'mp4',
                'title': 'Queer: Bogotart (Queer)',
                'thumbnail': r're:^https?://.*\.jpg',
                'duration': 1558.3,
            },
        }],
        'params': {
            # m3u8 download
            'skip_download': True,
        },
    }, {
        # iframe embed
        'url': 'http://www.ceskatelevize.cz/porady/10614999031-neviditelni/21251212048/',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        playlist_id = self._match_id(url)
        parsed_url = compat_urllib_parse_urlparse(url)
        webpage = self._download_webpage(url, playlist_id)
        site_name = self._og_search_property('site_name', webpage, fatal=False, default=None)
        playlist_title = self._og_search_title(webpage, default=None)
        if site_name and playlist_title:
            playlist_title = playlist_title.replace(f' — {site_name}', '', 1)
        playlist_description = self._og_search_description(webpage, default=None)
        if playlist_description:
            playlist_description = playlist_description.replace('\xa0', ' ')

        if parsed_url.path.startswith('/porady/'):
            next_data = self._search_nextjs_data(webpage, playlist_id)
            idec = traverse_obj(next_data, ('props', 'pageProps', 'data', ('show', 'mediaMeta'), 'idec'), get_all=False)
            if not idec:
                raise ExtractorError('Failed to find IDEC id')
            iframe_hash = self._download_webpage('https://www.ceskatelevize.cz/v-api/iframe-hash/', playlist_id)
            webpage = self._download_webpage('https://www.ceskatelevize.cz/ivysilani/embed/iFramePlayer.php', playlist_id,
                                             query={'hash': iframe_hash, 'origin': 'iVysilani', 'autoStart': 'true', 'IDEC': idec})

        NOT_AVAILABLE_STRING = 'This content is not available at your territory due to limited copyright.'
        if '%s</p>' % NOT_AVAILABLE_STRING in webpage:
            raise ExtractorError(NOT_AVAILABLE_STRING, expected=True)

        type_ = None
        episode_id = None

        playlist = self._parse_json(
            self._search_regex(
                r'getPlaylistUrl\(\[({.+?})\]', webpage, 'playlist',
                default='{}'), playlist_id)
        if playlist:
            type_ = playlist.get('type')
            episode_id = playlist.get('id')

        if not type_:
            type_ = self._html_search_regex(
                r'getPlaylistUrl\(\[\{"type":"(.+?)","id":".+?"\}\],',
                webpage, 'type')
        if not episode_id:
            episode_id = self._html_search_regex(
                r'getPlaylistUrl\(\[\{"type":".+?","id":"(.+?)"\}\],',
                webpage, 'episode_id')

        data = {
            'playlist[0][type]': type_,
            'playlist[0][id]': episode_id,
            'requestUrl': parsed_url.path,
            'requestSource': 'iVysilani',
        }

        entries = []

        for user_agent in (None, USER_AGENTS['Safari']):
            req = sanitized_Request(
                'https://www.ceskatelevize.cz/ivysilani/ajax/get-client-playlist/',
                data=urlencode_postdata(data))

            req.add_header('Content-type', 'application/x-www-form-urlencoded')
            req.add_header('x-addr', '127.0.0.1')
            req.add_header('X-Requested-With', 'XMLHttpRequest')
            if user_agent:
                req.add_header('User-Agent', user_agent)
            req.add_header('Referer', url)

            playlistpage = self._download_json(req, playlist_id, fatal=False)

            if not playlistpage:
                continue

            playlist_url = playlistpage['url']
            if playlist_url == 'error_region':
                raise ExtractorError(NOT_AVAILABLE_STRING, expected=True)

            req = sanitized_Request(compat_urllib_parse_unquote(playlist_url))
            req.add_header('Referer', url)

            playlist = self._download_json(req, playlist_id, fatal=False)
            if not playlist:
                continue

            playlist = playlist.get('playlist')
            if not isinstance(playlist, list):
                continue

            playlist_len = len(playlist)

            for num, item in enumerate(playlist):
                is_live = item.get('type') == 'LIVE'
                formats = []
                for format_id, stream_url in item.get('streamUrls', {}).items():
                    stream_url = stream_url.replace('https://', 'http://')
                    if 'playerType=flash' in stream_url:
                        stream_formats = self._extract_m3u8_formats(
                            stream_url, playlist_id, 'mp4', 'm3u8_native',
                            m3u8_id='hls-%s' % format_id, fatal=False)
                    else:
                        stream_formats = self._extract_mpd_formats(
                            stream_url, playlist_id,
                            mpd_id='dash-%s' % format_id, fatal=False)
                    if 'drmOnly=true' in stream_url:
                        for f in stream_formats:
                            f['has_drm'] = True
                    # See https://github.com/ytdl-org/youtube-dl/issues/12119#issuecomment-280037031
                    if format_id == 'audioDescription':
                        for f in stream_formats:
                            f['source_preference'] = -10
                    formats.extend(stream_formats)

                if user_agent and len(entries) == playlist_len:
                    entries[num]['formats'].extend(formats)
                    continue

                item_id = item.get('id') or item['assetId']
                title = item['title']

                duration = float_or_none(item.get('duration'))
                thumbnail = item.get('previewImageUrl')

                subtitles = {}
                if item.get('type') == 'VOD':
                    subs = item.get('subtitles')
                    if subs:
                        subtitles = self.extract_subtitles(episode_id, subs)

                if playlist_len == 1:
                    final_title = playlist_title or title
                else:
                    final_title = '%s (%s)' % (playlist_title, title)

                entries.append({
                    'id': item_id,
                    'title': final_title,
                    'description': playlist_description if playlist_len == 1 else None,
                    'thumbnail': thumbnail,
                    'duration': duration,
                    'formats': formats,
                    'subtitles': subtitles,
                    'is_live': is_live,
                })

        for e in entries:
            self._sort_formats(e['formats'])

        return self.playlist_result(entries, playlist_id, playlist_title, playlist_description)

    def _get_subtitles(self, episode_id, subs):
        original_subtitles = self._download_webpage(
            subs[0]['url'], episode_id, 'Downloading subtitles')
        srt_subs = self._fix_subtitles(original_subtitles)
        return {
            'cs': [{
                'ext': 'srt',
                'data': srt_subs,
            }]
        }

    @staticmethod
    def _fix_subtitles(subtitles):
        """ Convert millisecond-based subtitles to SRT """

        def _msectotimecode(msec):
            """ Helper utility to convert milliseconds to timecode """
            components = []
            for divider in [1000, 60, 60, 100]:
                components.append(msec % divider)
                msec //= divider
            return '{3:02}:{2:02}:{1:02},{0:03}'.format(*components)

        def _fix_subtitle(subtitle):
            for line in subtitle.splitlines():
                m = re.match(r'^\s*([0-9]+);\s*([0-9]+)\s+([0-9]+)\s*$', line)
                if m:
                    yield m.group(1)
                    start, stop = (_msectotimecode(int(t)) for t in m.groups()[1:])
                    yield '{0} --> {1}'.format(start, stop)
                else:
                    yield line

        return '\r\n'.join(_fix_subtitle(subtitles))


code:
from .common import InfoExtractor
from ..utils import (
    try_get,
    unified_timestamp,
)

class CGTNIE(InfoExtractor):
    _VALID_URL = r'https?://news\.cgtn\.com/news/[0-9]{4}-[0-9]{2}-[0-9]{2}/[a-zA-Z0-9-]+-(?P<id>[a-zA-Z0-9-]+)/index\.html'
    _TESTS = [
        {
            'url': 'https://news.cgtn.com/news/2021-03-09/Up-and-Out-of-Poverty-Ep-1-A-solemn-promise-YuOUaOzGQU/index.html',
            'info_dict': {
                'id': 'YuOUaOzGQU',
                'ext': 'mp4',
                'title': 'Up and Out of Poverty Ep. 1: A solemn promise',
                'thumbnail': r're:^https?://.*\.jpg$',
                'timestamp': 1615295940,
                'upload_date': '20210309',
            },
            'params': {
                'skip_download': True
            }
        }, {
            'url': 'https://news.cgtn.com/news/2021-06-06/China-Indonesia-vow-to-further-deepen-maritime-cooperation-10REvJCewCY/index.html',
            'info_dict': {
                'id': '10REvJCewCY',
                'ext': 'mp4',
                'title': 'China, Indonesia vow to further deepen maritime cooperation',
                'thumbnail': r're:^https?://.*\.png$',
                'description': 'China and Indonesia vowed to upgrade their cooperation into the maritime sector and also for political security, economy, and cultural and people-to-people exchanges.',
                'author': 'CGTN',
                'category': 'China',
                'timestamp': 1622950200,
                'upload_date': '20210606',
            },
            'params': {
                'skip_download': False
            }
        }
    ]

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

        download_url = self._html_search_regex(r'data-video ="(?P<url>.+m3u8)"', webpage, 'download_url')
        datetime_str = self._html_search_regex(r'\s*(.+?)\s*', webpage, 'datetime_str', fatal=False)

        return {
            'id': video_id,
            'title': self._og_search_title(webpage),
            'description': self._og_search_description(webpage, default=None),
            'thumbnail': self._og_search_thumbnail(webpage),
            'formats': self._extract_m3u8_formats(download_url, video_id, 'mp4', 'm3u8_native', m3u8_id='hls'),
            'category': self._html_search_regex(r'\s*(.+?)\s*',
                                                webpage, 'category', fatal=False),
            'author': self._html_search_regex(r'
\s*(.+?)\s*
',
                                              webpage, 'author', default=None, fatal=False),
            'timestamp': try_get(unified_timestamp(datetime_str), lambda x: x - 8 * 3600),
        }

repo_name: Lesmiscore/ytdl


code:
import re

from .common import InfoExtractor
from ..utils import (
    clean_html,
    int_or_none,
    parse_iso8601,
    qualities,
    unescapeHTML,
)

class Channel9IE(InfoExtractor):
    IE_DESC = 'Channel 9'
    IE_NAME = 'channel9'
    _VALID_URL = r'https?://(?:www\.)?(?:channel9\.msdn\.com|s\.ch9\.ms)/(?P<contentpath>.+?)(?P<rss>/RSS)?/?(?:[?#&]|$)'
    _EMBED_REGEX = [r'<iframe[^>]+src=["\'](?P<url>https?://channel9\.msdn\.com/(?:[^/]+/)+)player\b']

    _TESTS = [{
        'url': 'http://channel9.msdn.com/Events/TechEd/Australia/2013/KOS002',
        'md5': '32083d4eaf1946db6d454313f44510ca',
        'info_dict': {
            'id': '6c413323-383a-49dc-88f9-a22800cab024',
            'ext': 'wmv',
            'title': 'Developer Kick-Off Session: Stuff We Love',
            'description': 'md5:b80bf9355a503c193aff7ec6cd5a7731',
            'duration': 4576,
            'thumbnail': r're:https?://.*\.jpg',
            'timestamp': 1377717420,
            'upload_date': '20130828',
            'session_code': 'KOS002',
            'session_room': 'Arena 1A',
            'session_speakers': 'count:5',
        },
    }, {
        'url': 'http://channel9.msdn.com/posts/Self-service-BI-with-Power-BI-nuclear-testing',
        'md5': 'dcf983ee6acd2088e7188c3cf79b46bc',
        'info_dict': {
            'id': 'fe8e435f-bb93-4e01-8e97-a28c01887024',
            'ext': 'wmv',
            'title': 'Self-service BI with Power BI - nuclear testing',
            'description': 'md5:2d17fec927fc91e9e17783b3ecc88f54',
            'duration': 1540,
            'thumbnail': r're:https?://.*\.jpg',
            'timestamp': 1386381991,
            'upload_date': '20131207',
            'authors': ['Mike Wilmot'],
        },
    }, {
        # low quality mp4 is best
        'url': 'https://channel9.msdn.com/Events/CPP/CppCon-2015/Ranges-for-the-Standard-Library',
        'info_dict': {
            'id': '33ad69d2-6a4e-4172-83a1-a523013dec76',
            'ext': 'mp4',
            'title': 'Ranges for the Standard Library',
            'description': 'md5:9895e0a9fd80822d2f01c454b8f4a372',
            'duration': 5646,
            'thumbnail': r're:https?://.*\.jpg',
            'upload_date': '20150930',
            'timestamp': 1443640735,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'https://channel9.msdn.com/Events/DEVintersection/DEVintersection-2016/RSS',
        'info_dict': {
            'id': 'Events/DEVintersection/DEVintersection-2016',
            'title': 'DEVintersection 2016 Orlando Sessions',
        },
        'playlist_mincount': 14,
    }, {
        'url': 'https://channel9.msdn.com/Niners/Splendid22/Queue/76acff796e8f411184b008028e0d492b/RSS',
        'only_matching': True,
    }, {
        'url': 'https://channel9.msdn.com/Events/Speakers/scott-hanselman/RSS?UrlSafeName=scott-hanselman',
        'only_matching': True,
    }]

    _RSS_URL = 'http://channel9.msdn.com/%s/RSS'

    def _extract_list(self, video_id, rss_url=None):
        if not rss_url:
            rss_url = self._RSS_URL % video_id
        rss = self._download_xml(rss_url, video_id, 'Downloading RSS')
        entries = [self.url_result(session_url.text, 'Channel9')
                   for session_url in rss.findall('./channel/item/link')]
        title_text = rss.find('./channel/title').text
        return self.playlist_result(entries, video_id, title_text)

    def _real_extract(self, url):
        content_path, rss = self._match_valid_url(url).groups()

        if rss:
            return self._extract_list(content_path, url)

        webpage = self._download_webpage(
            url, content_path, 'Downloading web page')

        episode_data = self._search_regex(
            r"data-episode='([^']+)'", webpage, 'episode data', default=None)
        if episode_data:
            episode_data = self._parse_json(unescapeHTML(
                episode_data), content_path)
            content_id = episode_data['contentId']
            is_session = '/Sessions(' in episode_data['api']
            content_url = 'https://channel9.msdn.com/odata' + episode_data['api'] + '?$select=Captions,CommentCount,MediaLengthInSeconds,PublishedDate,Rating,RatingCount,Title,VideoMP4High,VideoMP4Low,VideoMP4Medium,VideoPlayerPreviewImage,VideoWMV,VideoWMVHQ,Views,'
            if is_session:
                content_url += 'Code,Description,Room,Slides,Speakers,ZipFile&$expand=Speakers'
            else:
                content_url += 'Authors,Body&$expand=Authors'
            content_data = self._download_json(content_url, content_id)
            title = content_data['Title']

            QUALITIES = (
                'mp3',
                'wmv', 'mp4',
                'wmv-low', 'mp4-low',
                'wmv-mid', 'mp4-mid',
                'wmv-high', 'mp4-high',
            )

            quality_key = qualities(QUALITIES)

            def quality(quality_id, format_url):
                return (len(QUALITIES) if '_Source.' in format_url
                        else quality_key(quality_id))

            formats = []
            urls = set()

            SITE_QUALITIES = {
                'MP3': 'mp3',
                'MP4': 'mp4',
                'Low Quality WMV': 'wmv-low',
                'Low Quality MP4': 'mp4-low',
                'Mid Quality WMV': 'wmv-mid',
                'Mid Quality MP4': 'mp4-mid',
                'High Quality WMV': 'wmv-high',
                'High Quality MP4': 'mp4-high',
            }

            formats_select = self._search_regex(
                r'(?s)<select[^>]+name=["\']format[^>]+>(.+?)</select', webpage,
                'formats select', default=None)
            if formats_select:
                for mobj in re.finditer(
                        r'<option\b[^>]+\bvalue=(["\'])(?P<url>(?:(?!\1).)+)\1[^>]*>\s*(?P<format>[^<]+?)\s*<',
                        formats_select):
                    format_url = mobj.group('url')
                    if format_url in urls:
                        continue
                    urls.add(format_url)
                    format_id = mobj.group('format')
                    quality_id = SITE_QUALITIES.get(format_id, format_id)
                    formats.append({
                        'url': format_url,
                        'format_id': quality_id,
                        'quality': quality(quality_id, format_url),
                        'vcodec': 'none' if quality_id == 'mp3' else None,
                    })

            API_QUALITIES = {
                'VideoMP4Low': 'mp4-low',
                'VideoWMV': 'wmv-mid',
                'VideoMP4Medium': 'mp4-mid',
                'VideoMP4High': 'mp4-high',
                'VideoWMVHQ': 'wmv-hq',
            }

            for format_id, q in API_QUALITIES.items():
                q_url = content_data.get(format_id)
                if not q_url or q_url in urls:
                    continue
                urls.add(q_url)
                formats.append({
                    'url': q_url,
                    'format_id': q,
                    'quality': quality(q, q_url),
                })

            slides = content_data.get('Slides')
            zip_file = content_data.get('ZipFile')

            if not formats and not slides and not zip_file:
                self.raise_no_formats(
                    'None of recording, slides or zip are available for %s' % content_path)
            self._sort_formats(formats)

            subtitles = {}
            for caption in content_data.get('Captions', []):
                caption_url = caption.get('Url')
                if not caption_url:
                    continue
                subtitles.setdefault(caption.get('Language', 'en'), []).append({
                    'url': caption_url,
                    'ext': 'vtt',
                })

            common = {
                'id': content_id,
                'title': title,
                'description': clean_html(content_data.get('Description') or content_data.get('Body')),
                'thumbnail': content_data.get('VideoPlayerPreviewImage'),
                'duration': int_or_none(content_data.get('MediaLengthInSeconds')),
                'timestamp': parse_iso8601(content_data.get('PublishedDate')),
                'avg_rating': int_or_none(content_data.get('Rating')),
                'rating_count': int_or_none(content_data.get('RatingCount')),
                'view_count': int_or_none(content_data.get('Views')),
                'comment_count': int_or_none(content_data.get('CommentCount')),
                'subtitles': subtitles,
            }
            if is_session:
                speakers = []
                for s in content_data.get('Speakers', []):
                    speaker_name = s.get('FullName')
                    if not speaker_name:
                        continue
                    speakers.append(speaker_name)

                common.update({
                    'session_code': content_data.get('Code'),
                    'session_room': content_data.get('Room'),
                    'session_speakers': speakers,
                })
            else:
                authors = []
                for a in content_data.get('Authors', []):
                    author_name = a.get('DisplayName')
                    if not author_name:
                        continue
                    authors.append(author_name)
                common['authors'] = authors

            contents = []

            if slides:
                d = common.copy()
                d.update({'title': title + '-Slides', 'url': slides})
                contents.append(d)

            if zip_file:
                d = common.copy()
                d.update({'title': title + '-Zip', 'url': zip_file})
                contents.append(d)

            if formats:
                d = common.copy()
                d.update({'title': title, 'formats': formats})
                contents.append(d)
            return self.playlist_result(contents)
        else:
            return self._extract_list(content_path)


code:
from .common import InfoExtractor
from ..utils import remove_end

class CharlieRoseIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?charlierose\.com/(?:video|episode)(?:s|/player)/(?P<id>\d+)'
    _TESTS = [{
        'url': 'https://charlierose.com/videos/27996',
        'md5': 'fda41d49e67d4ce7c2411fd2c4702e09',
        'info_dict': {
            'id': '27996',
            'ext': 'mp4',
            'title': 'Remembering Zaha Hadid',
            'thumbnail': r're:^https?://.*\.jpg\?\d+',
            'description': 'We revisit past conversations with Zaha Hadid, in memory of the world renowned Iraqi architect.',
            'subtitles': {
                'en': [{
                    'ext': 'vtt',
                }],
            },
        },
    }, {
        'url': 'https://charlierose.com/videos/27996',
        'only_matching': True,
    }, {
        'url': 'https://charlierose.com/episodes/30887?autoplay=true',
        'only_matching': True,
    }]

    _PLAYER_BASE = 'https://charlierose.com/video/player/%s'

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

        title = remove_end(self._og_search_title(webpage), ' - Charlie Rose')

        info_dict = self._parse_html5_media_entries(
            self._PLAYER_BASE % video_id, webpage, video_id,
            m3u8_entry_protocol='m3u8_native')[0]

        self._sort_formats(info_dict['formats'])
        self._remove_duplicate_formats(info_dict['formats'])

        info_dict.update({
            'id': video_id,
            'title': title,
            'thumbnail': self._og_search_thumbnail(webpage),
            'description': self._og_search_description(webpage),
        })

        return info_dict


code:
import re

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    lowercase_escape,
    url_or_none,
)

class ChaturbateIE(InfoExtractor):
    _VALID_URL = r'https?://(?:[^/]+\.)?chaturbate\.com/(?:fullvideo/?\?.*?\bb=)?(?P<id>[^/?&#]+)'
    _TESTS = [{
        'url': 'https://www.chaturbate.com/siswet19/',
        'info_dict': {
            'id': 'siswet19',
            'ext': 'mp4',
            'title': 're:^siswet19 [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
            'age_limit': 18,
            'is_live': True,
        },
        'params': {
            'skip_download': True,
        },
        'skip': 'Room is offline',
    }, {
        'url': 'https://chaturbate.com/fullvideo/?b=caylin',
        'only_matching': True,
    }, {
        'url': 'https://en.chaturbate.com/siswet19/',
        'only_matching': True,
    }]

    _ROOM_OFFLINE = 'Room is currently offline'

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

        webpage = self._download_webpage(
            'https://chaturbate.com/%s/' % video_id, video_id,
            headers=self.geo_verification_headers())

        found_m3u8_urls = []

        data = self._parse_json(
            self._search_regex(
                r'initialRoomDossier\s*=\s*(["\'])(?P<value>(?:(?!\1).)+)\1',
                webpage, 'data', default='{}', group='value'),
            video_id, transform_source=lowercase_escape, fatal=False)
        if data:
            m3u8_url = url_or_none(data.get('hls_source'))
            if m3u8_url:
                found_m3u8_urls.append(m3u8_url)

        if not found_m3u8_urls:
            for m in re.finditer(
                    r'(\\u002[27])(?P<url>http.+?\.m3u8.*?)\1', webpage):
                found_m3u8_urls.append(lowercase_escape(m.group('url')))

        if not found_m3u8_urls:
            for m in re.finditer(
                    r'(["\'])(?P<url>http.+?\.m3u8.*?)\1', webpage):
                found_m3u8_urls.append(m.group('url'))

        m3u8_urls = []
        for found_m3u8_url in found_m3u8_urls:
            m3u8_fast_url, m3u8_no_fast_url = found_m3u8_url, found_m3u8_url.replace('_fast', '')
            for m3u8_url in (m3u8_fast_url, m3u8_no_fast_url):
                if m3u8_url not in m3u8_urls:
                    m3u8_urls.append(m3u8_url)

        if not m3u8_urls:
            error = self._search_regex(
                [r']+class=(["\'])desc_span\1[^>]*>(?P<error>[^<]+)',
                 r'
]+id=(["\'])defchat\1[^>]*>\s*
(?P<error>[^<]+)<'],
                webpage, 'error', group='error', default=None)
            if not error:
                if any(p in webpage for p in (
                        self._ROOM_OFFLINE, 'offline_tipping', 'tip_offline')):
                    error = self._ROOM_OFFLINE
            if error:
                raise ExtractorError(error, expected=True)
            raise ExtractorError('Unable to find stream URL')

        formats = []
        for m3u8_url in m3u8_urls:
            for known_id in ('fast', 'slow'):
                if '_%s' % known_id in m3u8_url:
                    m3u8_id = known_id
                    break
            else:
                m3u8_id = None
            formats.extend(self._extract_m3u8_formats(
                m3u8_url, video_id, ext='mp4',
                # ffmpeg skips segments for fast m3u8
                preference=-10 if m3u8_id == 'fast' else None,
                m3u8_id=m3u8_id, fatal=False, live=True))
        self._sort_formats(formats)

        return {
            'id': video_id,
            'title': video_id,
            'thumbnail': 'https://roomimg.stream.highwebmedia.com/ri/%s.jpg' % video_id,
            'age_limit': self._rta_search(webpage),
            'is_live': True,
            'formats': formats,
        }


code:
import json

from .common import InfoExtractor
from .youtube import YoutubeIE
from ..compat import compat_b64decode
from ..utils import (
    clean_html,
    ExtractorError
)

class ChilloutzoneIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?chilloutzone\.net/video/(?P<id>[\w|-]+)\.html'
    _TESTS = [{
        'url': 'http://www.chilloutzone.net/video/enemene-meck-alle-katzen-weg.html',
        'md5': 'a76f3457e813ea0037e5244f509e66d1',
        'info_dict': {
            'id': 'enemene-meck-alle-katzen-weg',
            'ext': 'mp4',
            'title': 'Enemene Meck - Alle Katzen weg',
            'description': 'Ist das der Umkehrschluss des Niesenden Panda-Babys?',
        },
    }, {
        'note': 'Video hosted at YouTube',
        'url': 'http://www.chilloutzone.net/video/eine-sekunde-bevor.html',
        'info_dict': {
            'id': '1YVQaAgHyRU',
            'ext': 'mp4',
            'title': '16 Photos Taken 1 Second Before Disaster',
            'description': 'md5:58a8fcf6a459fe0a08f54140f0ad1814',
            'uploader': 'BuzzFeedVideo',
            'uploader_id': 'BuzzFeedVideo',
            'upload_date': '20131105',
        },
    }, {
        'note': 'Video hosted at Vimeo',
        'url': 'http://www.chilloutzone.net/video/icon-blending.html',
        'md5': '2645c678b8dc4fefcc0e1b60db18dac1',
        'info_dict': {
            'id': '85523671',
            'ext': 'mp4',
            'title': 'The Sunday Times - Icons',
            'description': 're:(?s)^Watch the making of - makingoficons.com.{300,}',
            'uploader': 'Us',
            'uploader_id': 'usfilms',
            'upload_date': '20140131'
        },
    }]

    def _real_extract(self, url):
        mobj = self._match_valid_url(url)
        video_id = mobj.group('id')

        webpage = self._download_webpage(url, video_id)

        base64_video_info = self._html_search_regex(
            r'var cozVidData = "(.+?)";', webpage, 'video data')
        decoded_video_info = compat_b64decode(base64_video_info).decode('utf-8')
        video_info_dict = json.loads(decoded_video_info)

        # get video information from dict
        video_url = video_info_dict['mediaUrl']
        description = clean_html(video_info_dict.get('description'))
        title = video_info_dict['title']
        native_platform = video_info_dict['nativePlatform']
        native_video_id = video_info_dict['nativeVideoId']
        source_priority = video_info_dict['sourcePriority']

        # If nativePlatform is None a fallback mechanism is used (i.e. youtube embed)
        if native_platform is None:
            youtube_url = YoutubeIE._extract_url(webpage)
            if youtube_url:
                return self.url_result(youtube_url, ie=YoutubeIE.ie_key())

        # Non Fallback: Decide to use native source (e.g. youtube or vimeo) or
        # the own CDN
        if source_priority == 'native':
            if native_platform == 'youtube':
                return self.url_result(native_video_id, ie='Youtube')
            if native_platform == 'vimeo':
                return self.url_result(
                    'http://vimeo.com/' + native_video_id, ie='Vimeo')

        if not video_url:
            raise ExtractorError('No video found')

        return {
            'id': video_id,
            'url': video_url,
            'ext': 'mp4',
            'title': title,
            'description': description,
        }


code:
import itertools
import json
import urllib.parse

from .common import InfoExtractor
from ..utils import (
    ExtractorError,
    clean_html,
    int_or_none,
    str_to_int,
    url_or_none,
)

class ChingariBaseIE(InfoExtractor):
    def _get_post(self, id, post_data):
        media_data = post_data['mediaLocation']
        base_url = media_data['base']
        author_data = post_data.get('authorData', {})
        song_data = post_data.get('song', {})  # revist this in future for differentiating b/w 'art' and 'author'

        formats = [{
            'format_id': frmt,
            'width': str_to_int(frmt[1:]),
            'url': base_url + frmt_path,
        } for frmt, frmt_path in media_data.get('transcoded', {}).items()]

        if media_data.get('path'):
            formats.append({
                'format_id': 'original',
                'format_note': 'Direct video.',
                'url': base_url + '/apipublic' + media_data['path'],
                'quality': 10,
            })
        self._sort_formats(formats)
        timestamp = str_to_int(post_data.get('created_at'))
        if timestamp:
            timestamp = int_or_none(timestamp, 1000)

        thumbnail, uploader_url = None, None
        if media_data.get('thumbnail'):
            thumbnail = base_url + media_data.get('thumbnail')
        if author_data.get('username'):
            uploader_url = 'https://chingari.io/' + author_data.get('username')

        return {
            'id': id,
            'extractor_key': ChingariIE.ie_key(),
            'extractor': 'Chingari',
            'title': urllib.parse.unquote_plus(clean_html(post_data.get('caption'))),
            'description': urllib.parse.unquote_plus(clean_html(post_data.get('caption'))),
            'duration': media_data.get('duration'),
            'thumbnail': url_or_none(thumbnail),
            'like_count': post_data.get('likeCount'),
            'view_count': post_data.get('viewsCount'),
            'comment_count': post_data.get('commentCount'),
            'repost_count': post_data.get('shareCount'),
            'timestamp': timestamp,
            'uploader_id': post_data.get('userId') or author_data.get('_id'),
            'uploader': author_data.get('name'),
            'uploader_url': url_or_none(uploader_url),
            'track': song_data.get('title'),
            'artist': song_data.get('author'),
            'formats': formats,
        }

class ChingariIE(ChingariBaseIE):
    _VALID_URL = r'https?://(?:www\.)?chingari\.io/share/post\?id=(?P<id>[^&/#?]+)'
    _TESTS = [{
        'url': 'https://chingari.io/share/post?id=612f8f4ce1dc57090e8a7beb',
        'info_dict': {
            'id': '612f8f4ce1dc57090e8a7beb',
            'ext': 'mp4',
            'title': 'Happy birthday Srila Prabhupada',
            'description': 'md5:c7080ebfdfeb06016e638c286d6bc3fa',
            'duration': 0,
            'thumbnail': 'https://media.chingari.io/uploads/c41d30e2-06b6-4e3b-9b4b-edbb929cec06-1630506826911/thumbnail/198f993f-ce87-4623-82c6-cd071bd6d4f4-1630506828016.jpg',
            'like_count': int,
            'view_count': int,
            'comment_count': int,
            'repost_count': int,
            'timestamp': 1630506828,
            'upload_date': '20210901',
            'uploader_id': '5f0403982c8bd344f4813f8c',
            'uploader': 'ISKCON,Inc.',
            'uploader_url': 'https://chingari.io/iskcon,inc',
            'track': None,
            'artist': None,
        },
        'params': {'skip_download': True}
    }]

    def _real_extract(self, url):
        id = self._match_id(url)
        post_json = self._download_json(f'https://api.chingari.io/post/post_details/{id}', id)
        if post_json['code'] != 200:
            raise ExtractorError(post_json['message'], expected=True)
        post_data = post_json['data']
        return self._get_post(id, post_data)

class ChingariUserIE(ChingariBaseIE):
    _VALID_URL = r'https?://(?:www\.)?chingari\.io/(?!share/post)(?P<id>[^/?]+)'
    _TESTS = [{
        'url': 'https://chingari.io/dada1023',
        'info_dict': {
            'id': 'dada1023',
        },
        'params': {'playlistend': 3},
        'playlist': [{
            'url': 'https://chingari.io/share/post?id=614781f3ade60b3a0bfff42a',
            'info_dict': {
                'id': '614781f3ade60b3a0bfff42a',
                'ext': 'mp4',
                'title': '#chingaribappa ',
                'description': 'md5:d1df21d84088770468fa63afe3b17857',
                'duration': 7,
                'thumbnail': 'https://media.chingari.io/uploads/346d86d4-abb2-474e-a164-ffccf2bbcb72-1632076273717/thumbnail/b0b3aac2-2b86-4dd1-909d-9ed6e57cf77c-1632076275552.jpg',
                'like_count': int,
                'view_count': int,
                'comment_count': int,
                'repost_count': int,
                'timestamp': 1632076275,
                'upload_date': '20210919',
                'uploader_id': '5efc4b12cca35c3d1794c2d3',
                'uploader': 'dada (girish) dhawale',
                'uploader_url': 'https://chingari.io/dada1023',
                'track': None,
                'artist': None
            },
            'params': {'skip_download': True}
        }, {
            'url': 'https://chingari.io/share/post?id=6146b132bcbf860959e12cba',
            'info_dict': {
                'id': '6146b132bcbf860959e12cba',
                'ext': 'mp4',
                'title': 'Tactor harvesting',
                'description': 'md5:8403f12dce68828b77ecee7eb7e887b7',
                'duration': 59.3,
                'thumbnail': 'https://media.chingari.io/uploads/b353ca70-7a87-400d-93a6-fa561afaec86-1632022814584/thumbnail/c09302e3-2043-41b1-a2fe-77d97e5bd676-1632022834260.jpg',
                'like_count': int,
                'view_count': int,
                'comment_count': int,
                'repost_count': int,
                'timestamp': 1632022834,
                'upload_date': '20210919',
                'uploader_id': '5efc4b12cca35c3d1794c2d3',
                'uploader': 'dada (girish) dhawale',
                'uploader_url': 'https://chingari.io/dada1023',
                'track': None,
                'artist': None
            },
            'params': {'skip_download': True}
        }, {
            'url': 'https://chingari.io/share/post?id=6145651b74cb030a64c40b82',
            'info_dict': {
                'id': '6145651b74cb030a64c40b82',
                'ext': 'mp4',
                'title': '#odiabhajan ',
                'description': 'md5:687ea36835b9276cf2af90f25e7654cb',
                'duration': 56.67,
                'thumbnail': 'https://media.chingari.io/uploads/6cbf216b-babc-4cce-87fe-ceaac8d706ac-1631937782708/thumbnail/8855754f-6669-48ce-b269-8cc0699ed6da-1631937819522.jpg',
                'like_count': int,
                'view_count': int,
                'comment_count': int,
                'repost_count': int,
                'timestamp': 1631937819,
                'upload_date': '20210918',
                'uploader_id': '5efc4b12cca35c3d1794c2d3',
                'uploader': 'dada (girish) dhawale',
                'uploader_url': 'https://chingari.io/dada1023',
                'track': None,
                'artist': None
            },
            'params': {'skip_download': True}
        }],
    }, {
        'url': 'https://chingari.io/iskcon%2Cinc',
        'playlist_mincount': 1025,
        'info_dict': {
            'id': 'iskcon%2Cinc',
        },
    }]

    def _entries(self, id):
        skip = 0
        has_more = True
        for page in itertools.count():
            posts = self._download_json('https://api.chingari.io/users/getPosts', id,
                                        data=json.dumps({'userId': id, 'ownerId': id, 'skip': skip, 'limit': 20}).encode(),
                                        headers={'content-type': 'application/json;charset=UTF-8'},
                                        note='Downloading page %s' % page)
            for post in posts.get('data', []):
                post_data = post['post']
                yield self._get_post(post_data['_id'], post_data)
            skip += 20
            has_more = posts['hasMoreData']
            if not has_more:
                break

    def _real_extract(self, url):
        alt_id = self._match_id(url)
        post_json = self._download_json(f'https://api.chingari.io/user/{alt_id}', alt_id)
        if post_json['code'] != 200:
            raise ExtractorError(post_json['message'], expected=True)
        id = post_json['data']['_id']
        return self.playlist_result(self._entries(id), playlist_id=alt_id)


code:
import re

from .common import InfoExtractor
from ..compat import compat_b64decode
from ..utils import parse_duration

class ChirbitIE(InfoExtractor):
    IE_NAME = 'chirbit'
    _VALID_URL = r'https?://(?:www\.)?chirb\.it/(?:(?:wp|pl)/|fb_chirbit_player\.swf\?key=)?(?P<id>[\da-zA-Z]+)'
    _TESTS = [{
        'url': 'http://chirb.it/be2abG',
        'info_dict': {
            'id': 'be2abG',
            'ext': 'mp3',
            'title': 'md5:f542ea253f5255240be4da375c6a5d7e',
            'description': 'md5:f24a4e22a71763e32da5fed59e47c770',
            'duration': 306,
            'uploader': 'Gerryaudio',
        },
        'params': {
            'skip_download': True,
        }
    }, {
        'url': 'https://chirb.it/fb_chirbit_player.swf?key=PrIPv5',
        'only_matching': True,
    }, {
        'url': 'https://chirb.it/wp/MN58c2',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        audio_id = self._match_id(url)

        webpage = self._download_webpage(
            'http://chirb.it/%s' % audio_id, audio_id)

        data_fd = self._search_regex(
            r'data-fd=(["\'])(?P<url>(?:(?!\1).)+)\1',
            webpage, 'data fd', group='url')

        # Reverse engineered from https://chirb.it/js/chirbit.player.js (look
        # for soundURL)
        audio_url = compat_b64decode(data_fd[::-1]).decode('utf-8')

        title = self._search_regex(
            r'class=["\']chirbit-title["\'][^>]*>([^<]+)', webpage, 'title')
        description = self._search_regex(
            r'
Description
\s*
]*>([^<]+)
',
            webpage, 'description', default=None)
        duration = parse_duration(self._search_regex(
            r'class=["\']c-length["\'][^>]*>([^<]+)',
            webpage, 'duration', fatal=False))
        uploader = self._search_regex(
            r'id=["\']chirbit-username["\'][^>]*>([^<]+)',
            webpage, 'uploader', fatal=False)

        return {
            'id': audio_id,
            'url': audio_url,
            'title': title,
            'description': description,
            'duration': duration,
            'uploader': uploader,
        }

class ChirbitProfileIE(InfoExtractor):
    IE_NAME = 'chirbit:profile'
    _VALID_URL = r'https?://(?:www\.)?chirbit\.com/(?:rss/)?(?P<id>[^/]+)'
    _TEST = {
        'url': 'http://chirbit.com/ScarletBeauty',
        'info_dict': {
            'id': 'ScarletBeauty',
        },
        'playlist_mincount': 3,
    }

    def _real_extract(self, url):
        profile_id = self._match_id(url)

        webpage = self._download_webpage(url, profile_id)

        entries = [
            self.url_result(self._proto_relative_url('//chirb.it/' + video_id))
            for _, video_id in re.findall(r'<input[^>]+id=([\'"])copy-btn-(?P<id>[0-9a-zA-Z]+)\1', webpage)]

        return self.playlist_result(entries, profile_id)


code:
from .common import InfoExtractor
from ..utils import (
    unified_strdate,
    xpath_text,
)

class CinchcastIE(InfoExtractor):
    _VALID_URL = r'https?://player\.cinchcast\.com/.*?(?:assetId|show_id)=(?P<id>[0-9]+)'
    _EMBED_REGEX = [r'<iframe[^>]+?src=(["\'])(?P<url>https?://player\.cinchcast\.com/.+?)\1']

    _TESTS = [{
        'url': 'http://player.cinchcast.com/?show_id=5258197&platformId=1&assetType=single',
        'info_dict': {
            'id': '5258197',
            'ext': 'mp3',
            'title': 'Train Your Brain to Up Your Game with Coach Mandy',
            'upload_date': '20130816',
        },
    }, {
        # Actual test is run in generic, look for undergroundwellness
        'url': 'http://player.cinchcast.com/?platformId=1&assetType=single&assetId=7141703',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        doc = self._download_xml(
            'http://www.blogtalkradio.com/playerasset/mrss?assetType=single&assetId=%s' % video_id,
            video_id)

        item = doc.find('.//item')
        title = xpath_text(item, './title', fatal=True)
        date_str = xpath_text(
            item, './{http://developer.longtailvideo.com/trac/}date')
        upload_date = unified_strdate(date_str, day_first=False)
        # duration is present but wrong
        formats = [{
            'format_id': 'main',
            'url': item.find('./{http://search.yahoo.com/mrss/}content').attrib['url'],
        }]
        backup_url = xpath_text(
            item, './{http://developer.longtailvideo.com/trac/}backupContent')
        if backup_url:
            formats.append({
                'preference': 2,  # seems to be more reliable
                'format_id': 'backup',
                'url': backup_url,
            })
        self._sort_formats(formats)

        return {
            'id': video_id,
            'title': title,
            'upload_date': upload_date,
            'formats': formats,
        }


code:
from .hbo import HBOBaseIE

class CinemaxIE(HBOBaseIE):
    _VALID_URL = r'https?://(?:www\.)?cinemax\.com/(?P<path>[^/]+/video/[0-9a-z-]+-(?P<id>\d+))'
    _TESTS = [{
        'url': 'https://www.cinemax.com/warrior/video/s1-ep-1-recap-20126903',
        'md5': '82e0734bba8aa7ef526c9dd00cf35a05',
        'info_dict': {
            'id': '20126903',
            'ext': 'mp4',
            'title': 'S1 Ep 1: Recap',
        },
        'expected_warnings': ['Unknown MIME type application/mp4 in DASH manifest'],
    }, {
        'url': 'https://www.cinemax.com/warrior/video/s1-ep-1-recap-20126903.embed',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        path, video_id = self._match_valid_url(url).groups()
        info = self._extract_info('https://www.cinemax.com/%s.xml' % path, video_id)
        info['id'] = video_id
        return info


code:
import itertools

from .common import InfoExtractor
from ..utils import (
    clean_html,
    float_or_none,
    int_or_none,
    parse_qs,
    try_get,
    urlencode_postdata,
)

class CiscoLiveBaseIE(InfoExtractor):
    # These appear to be constant across all Cisco Live presentations
    # and are not tied to any user session or event
    RAINFOCUS_API_URL = 'https://events.rainfocus.com/api/%s'
    RAINFOCUS_API_PROFILE_ID = 'Na3vqYdAlJFSxhYTYQGuMbpafMqftalz'
    RAINFOCUS_WIDGET_ID = 'n6l4Lo05R8fiy3RpUBm447dZN8uNWoye'
    BRIGHTCOVE_URL_TEMPLATE = 'http://players.brightcove.net/5647924234001/SyK2FdqjM_default/index.html?videoId=%s'

    HEADERS = {
        'Origin': 'https://ciscolive.cisco.com',
        'rfApiProfileId': RAINFOCUS_API_PROFILE_ID,
        'rfWidgetId': RAINFOCUS_WIDGET_ID,
    }

    def _call_api(self, ep, rf_id, query, referrer, note=None):
        headers = self.HEADERS.copy()
        headers['Referer'] = referrer
        return self._download_json(
            self.RAINFOCUS_API_URL % ep, rf_id, note=note,
            data=urlencode_postdata(query), headers=headers)

    def _parse_rf_item(self, rf_item):
        event_name = rf_item.get('eventName')
        title = rf_item['title']
        description = clean_html(rf_item.get('abstract'))
        presenter_name = try_get(rf_item, lambda x: x['participants'][0]['fullName'])
        bc_id = rf_item['videos'][0]['url']
        bc_url = self.BRIGHTCOVE_URL_TEMPLATE % bc_id
        duration = float_or_none(try_get(rf_item, lambda x: x['times'][0]['length']))
        location = try_get(rf_item, lambda x: x['times'][0]['room'])

        if duration:
            duration = duration * 60

        return {
            '_type': 'url_transparent',
            'url': bc_url,
            'ie_key': 'BrightcoveNew',
            'title': title,
            'description': description,
            'duration': duration,
            'creator': presenter_name,
            'location': location,
            'series': event_name,
        }

class CiscoLiveSessionIE(CiscoLiveBaseIE):
    _VALID_URL = r'https?://(?:www\.)?ciscolive(?:\.cisco)?\.com/[^#]*#/session/(?P<id>[^/?&]+)'
    _TESTS = [{
        'url': 'https://ciscolive.cisco.com/on-demand-library/?#/session/1423353499155001FoSs',
        'md5': 'c98acf395ed9c9f766941c70f5352e22',
        'info_dict': {
            'id': '5803694304001',
            'ext': 'mp4',
            'title': '13 Smart Automations to Monitor Your Cisco IOS Network',
            'description': 'md5:ec4a436019e09a918dec17714803f7cc',
            'timestamp': 1530305395,
            'upload_date': '20180629',
            'uploader_id': '5647924234001',
            'location': '16B Mezz.',
        },
    }, {
        'url': 'https://www.ciscolive.com/global/on-demand-library.html?search.event=ciscoliveemea2019#/session/15361595531500013WOU',
        'only_matching': True,
    }, {
        'url': 'https://www.ciscolive.com/global/on-demand-library.html?#/session/1490051371645001kNaS',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        rf_id = self._match_id(url)
        rf_result = self._call_api('session', rf_id, {'id': rf_id}, url)
        return self._parse_rf_item(rf_result['items'][0])

class CiscoLiveSearchIE(CiscoLiveBaseIE):
    _VALID_URL = r'https?://(?:www\.)?ciscolive(?:\.cisco)?\.com/(?:global/)?on-demand-library(?:\.html|/)'
    _TESTS = [{
        'url': 'https://ciscolive.cisco.com/on-demand-library/?search.event=ciscoliveus2018&search.technicallevel=scpsSkillLevel_aintroductory&search.focus=scpsSessionFocus_designAndDeployment#/',
        'info_dict': {
            'title': 'Search query',
        },
        'playlist_count': 5,
    }, {
        'url': 'https://ciscolive.cisco.com/on-demand-library/?search.technology=scpsTechnology_applicationDevelopment&search.technology=scpsTechnology_ipv6&search.focus=scpsSessionFocus_troubleshootingTroubleshooting#/',
        'only_matching': True,
    }, {
        'url': 'https://www.ciscolive.com/global/on-demand-library.html?search.technicallevel=scpsSkillLevel_aintroductory&search.event=ciscoliveemea2019&search.technology=scpsTechnology_dataCenter&search.focus=scpsSessionFocus_bestPractices#/',
        'only_matching': True,
    }]

    @classmethod
    def suitable(cls, url):
        return False if CiscoLiveSessionIE.suitable(url) else super(CiscoLiveSearchIE, cls).suitable(url)

    @staticmethod
    def _check_bc_id_exists(rf_item):
        return int_or_none(try_get(rf_item, lambda x: x['videos'][0]['url'])) is not None

    def _entries(self, query, url):
        query['size'] = 50
        query['from'] = 0
        for page_num in itertools.count(1):
            results = self._call_api(
                'search', None, query, url,
                'Downloading search JSON page %d' % page_num)
            sl = try_get(results, lambda x: x['sectionList'][0], dict)
            if sl:
                results = sl
            items = results.get('items')
            if not items or not isinstance(items, list):
                break
            for item in items:
                if not isinstance(item, dict):
                    continue
                if not self._check_bc_id_exists(item):
                    continue
                yield self._parse_rf_item(item)
            size = int_or_none(results.get('size'))
            if size is not None:
                query['size'] = size
            total = int_or_none(results.get('total'))
            if total is not None and query['from'] + query['size'] > total:
                break
            query['from'] += query['size']

    def _real_extract(self, url):
        query = parse_qs(url)
        query['type'] = 'session'
        return self.playlist_result(
            self._entries(query, url), playlist_title='Search query')


code:
from .common import InfoExtractor
from ..utils import (
    int_or_none,
    try_get,
    unified_timestamp,
)

class CiscoWebexIE(InfoExtractor):
    IE_NAME = 'ciscowebex'
    IE_DESC = 'Cisco Webex'
    _VALID_URL = r'''(?x)
                    (?P<url>https?://(?P<subdomain>[^/#?]*)\.webex\.com/(?:
                        (?P<siteurl_1>[^/#?]*)/(?:ldr|lsr).php\?(?:[^#]*&)*RCID=(?P<rcid>[0-9a-f]{32})|
                        (?:recordingservice|webappng)/sites/(?P<siteurl_2>[^/#?]*)/recording/(?:playback/|play/)?(?P<id>[0-9a-f]{32})
                    ))'''

    _TESTS = [{
        'url': 'https://demosubdomain.webex.com/demositeurl/ldr.php?RCID=e58e803bc0f766bb5f6376d2e86adb5b',
        'only_matching': True,
    }, {
        'url': 'http://demosubdomain.webex.com/demositeurl/lsr.php?RCID=bc04b4a7b5ea2cc3a493d5ae6aaff5d7',
        'only_matching': True,
    }, {
        'url': 'https://demosubdomain.webex.com/recordingservice/sites/demositeurl/recording/88e7a42f7b19f5b423c54754aecc2ce9/playback',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        mobj = self._match_valid_url(url)
        rcid = mobj.group('rcid')
        if rcid:
            webpage = self._download_webpage(url, None, note='Getting video ID')
            url = self._search_regex(self._VALID_URL, webpage, 'redirection url', group='url')
        url = self._request_webpage(url, None, note='Resolving final URL').geturl()
        mobj = self._match_valid_url(url)
        subdomain = mobj.group('subdomain')
        siteurl = mobj.group('siteurl_1') or mobj.group('siteurl_2')
        video_id = mobj.group('id')

        stream = self._download_json(
            'https://%s.webex.com/webappng/api/v1/recordings/%s/stream' % (subdomain, video_id),
            video_id, fatal=False, query={'siteurl': siteurl})
        if not stream:
            self.raise_login_required(method='cookies')

        video_id = stream.get('recordUUID') or video_id

        formats = [{
            'format_id': 'video',
            'url': stream['fallbackPlaySrc'],
            'ext': 'mp4',
            'vcodec': 'avc1.640028',
            'acodec': 'mp4a.40.2',
        }]
        if stream.get('preventDownload') is False:
            mp4url = try_get(stream, lambda x: x['downloadRecordingInfo']['downloadInfo']['mp4URL'])
            if mp4url:
                formats.append({
                    'format_id': 'video',
                    'url': mp4url,
                    'ext': 'mp4',
                    'vcodec': 'avc1.640028',
                    'acodec': 'mp4a.40.2',
                })
            audiourl = try_get(stream, lambda x: x['downloadRecordingInfo']['downloadInfo']['audioURL'])
            if audiourl:
                formats.append({
                    'format_id': 'audio',
                    'url': audiourl,
                    'ext': 'mp3',
                    'vcodec': 'none',
                    'acodec': 'mp3',
                })
        self._sort_formats(formats)

        return {
            'id': video_id,
            'title': stream['recordName'],
            'description': stream.get('description'),
            'uploader': stream.get('ownerDisplayName'),
            'uploader_id': stream.get('ownerUserName') or stream.get('ownerId'),  # mail or id
            'timestamp': unified_timestamp(stream.get('createTime')),
            'duration': int_or_none(stream.get('duration'), 1000),
            'webpage_url': 'https://%s.webex.com/recordingservice/sites/%s/recording/playback/%s' % (subdomain, siteurl, video_id),
            'formats': formats,
        }


code:
from .common import InfoExtractor
from ..utils import (
    determine_ext,
    unescapeHTML,
)

class CJSWIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?cjsw\.com/program/(?P<program>[^/]+)/episode/(?P<id>\d+)'
    _TESTS = [{
        'url': 'http://cjsw.com/program/freshly-squeezed/episode/20170620',
        'md5': 'cee14d40f1e9433632c56e3d14977120',
        'info_dict': {
            'id': '91d9f016-a2e7-46c5-8dcb-7cbcd7437c41',
            'ext': 'mp3',
            'title': 'Freshly Squeezed – Episode June 20, 2017',
            'description': 'md5:c967d63366c3898a80d0c7b0ff337202',
            'series': 'Freshly Squeezed',
            'episode_id': '20170620',
        },
    }, {
        # no description
        'url': 'http://cjsw.com/program/road-pops/episode/20170707/',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        mobj = self._match_valid_url(url)
        program, episode_id = mobj.group('program', 'id')
        audio_id = '%s/%s' % (program, episode_id)

        webpage = self._download_webpage(url, episode_id)

        title = unescapeHTML(self._search_regex(
            (r'<h1[^>]+class=["\']episode-header__title["\'][^>]*>(?P<title>[^<]+)',
             r'data-audio-title=(["\'])(?P<title>(?:(?!\1).)+)\1'),
            webpage, 'title', group='title'))

        audio_url = self._search_regex(
            r'<button[^>]+data-audio-src=(["\'])(?P<url>(?:(?!\1).)+)\1',
            webpage, 'audio url', group='url')

        audio_id = self._search_regex(
            r'/([\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12})\.mp3',
            audio_url, 'audio id', default=audio_id)

        formats = [{
            'url': audio_url,
            'ext': determine_ext(audio_url, 'mp3'),
            'vcodec': 'none',
        }]

        description = self._html_search_regex(
            r'<p>(?P<description>.+?)</p>', webpage, 'description',
            default=None)
        series = self._search_regex(
            r'data-showname=(["\'])(?P<name>(?:(?!\1).)+)\1', webpage,
            'series', default=program, group='name')

        return {
            'id': audio_id,
            'title': title,
            'description': description,
            'formats': formats,
            'series': series,
            'episode_id': episode_id,
        }


code:
from .common import InfoExtractor
from ..utils import (
    int_or_none,
    url_or_none,
)

class CliphunterIE(InfoExtractor):
    IE_NAME = 'cliphunter'

    _VALID_URL = r'''(?x)https?://(?:www\.)?cliphunter\.com/w/
        (?P<id>[0-9]+)/
        (?P<seo>.+?)(?:$|[#\?])
    '''
    _TESTS = [{
        'url': 'http://www.cliphunter.com/w/1012420/Fun_Jynx_Maze_solo',
        'md5': 'b7c9bbd4eb3a226ab91093714dcaa480',
        'info_dict': {
            'id': '1012420',
            'ext': 'flv',
            'title': 'Fun Jynx Maze solo',
            'thumbnail': r're:^https?://.*\.jpg$',
            'age_limit': 18,
        },
        'skip': 'Video gone',
    }, {
        'url': 'http://www.cliphunter.com/w/2019449/ShesNew__My_booty_girlfriend_Victoria_Paradices_pussy_filled_with_jizz',
        'md5': '55a723c67bfc6da6b0cfa00d55da8a27',
        'info_dict': {
            'id': '2019449',
            'ext': 'mp4',
            'title': 'ShesNew - My booty girlfriend, Victoria Paradice\'s pussy filled with jizz',
            'thumbnail': r're:^https?://.*\.jpg$',
            'age_limit': 18,
        },
    }]

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

        video_title = self._search_regex(
            r'mediaTitle = "([^"]+)"', webpage, 'title')

        gexo_files = self._parse_json(
            self._search_regex(
                r'var\s+gexoFiles\s*=\s*({.+?});', webpage, 'gexo files'),
            video_id)

        formats = []
        for format_id, f in gexo_files.items():
            video_url = url_or_none(f.get('url'))
            if not video_url:
                continue
            fmt = f.get('fmt')
            height = f.get('h')
            format_id = '%s_%sp' % (fmt, height) if fmt and height else format_id
            formats.append({
                'url': video_url,
                'format_id': format_id,
                'width': int_or_none(f.get('w')),
                'height': int_or_none(height),
                'tbr': int_or_none(f.get('br')),
            })
        self._sort_formats(formats)

        thumbnail = self._search_regex(
            r"var\s+mov_thumb\s*=\s*'([^']+)';",
            webpage, 'thumbnail', fatal=False)

        return {
            'id': video_id,
            'title': video_title,
            'formats': formats,
            'age_limit': self._rta_search(webpage),
            'thumbnail': thumbnail,
        }


code:
from .common import InfoExtractor
from ..utils import (
    parse_iso8601,
    qualities,
)

import re

class ClippitIE(InfoExtractor):

    _VALID_URL = r'https?://(?:www\.)?clippituser\.tv/c/(?P<id>[a-z]+)'
    _TEST = {
        'url': 'https://www.clippituser.tv/c/evmgm',
        'md5': '963ae7a59a2ec4572ab8bf2f2d2c5f09',
        'info_dict': {
            'id': 'evmgm',
            'ext': 'mp4',
            'title': 'Bye bye Brutus. #BattleBots  - Clippit',
            'uploader': 'lizllove',
            'uploader_url': 'https://www.clippituser.tv/p/lizllove',
            'timestamp': 1472183818,
            'upload_date': '20160826',
            'description': 'BattleBots | ABC',
            'thumbnail': r're:^https?://.*\.jpg$',
        }
    }

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

        title = self._html_search_regex(r'<title.*>(.+?)</title>', webpage, 'title')

        FORMATS = ('sd', 'hd')
        quality = qualities(FORMATS)
        formats = []
        for format_id in FORMATS:
            url = self._html_search_regex(r'data-%s-file="(.+?)"' % format_id,
                                          webpage, 'url', fatal=False)
            if not url:
                continue
            match = re.search(r'/(?P<height>\d+)\.mp4', url)
            formats.append({
                'url': url,
                'format_id': format_id,
                'quality': quality(format_id),
                'height': int(match.group('height')) if match else None,
            })

        uploader = self._html_search_regex(r'class="username".*>\s+(.+?)\n',
                                           webpage, 'uploader', fatal=False)
        uploader_url = ('https://www.clippituser.tv/p/' + uploader
                        if uploader else None)

        timestamp = self._html_search_regex(r'datetime="(.+?)"',
                                            webpage, 'date', fatal=False)
        thumbnail = self._html_search_regex(r'data-image="(.+?)"',
                                            webpage, 'thumbnail', fatal=False)

        return {
            'id': video_id,
            'title': title,
            'formats': formats,
            'uploader': uploader,
            'uploader_url': uploader_url,
            'timestamp': parse_iso8601(timestamp),
            'description': self._og_search_description(webpage),
            'thumbnail': thumbnail,
        }


code:
from .onet import OnetBaseIE

class ClipRsIE(OnetBaseIE):
    _VALID_URL = r'https?://(?:www\.)?clip\.rs/(?P<id>[^/]+)/\d+'
    _TEST = {
        'url': 'http://www.clip.rs/premijera-frajle-predstavljaju-novi-spot-za-pesmu-moli-me-moli/3732',
        'md5': 'c412d57815ba07b56f9edc7b5d6a14e5',
        'info_dict': {
            'id': '1488842.1399140381',
            'ext': 'mp4',
            'title': 'PREMIJERA Frajle predstavljaju novi spot za pesmu Moli me, moli',
            'description': 'md5:56ce2c3b4ab31c5a2e0b17cb9a453026',
            'duration': 229,
            'timestamp': 1459850243,
            'upload_date': '20160405',
        }
    }

    def _real_extract(self, url):
        display_id = self._match_id(url)

        webpage = self._download_webpage(url, display_id)

        mvp_id = self._search_mvp_id(webpage)

        info_dict = self._extract_from_id(mvp_id, webpage)
        info_dict['display_id'] = display_id

        return info_dict


code:
from .common import InfoExtractor
from ..utils import (
    find_xpath_attr,
    fix_xml_ampersands
)

class ClipsyndicateIE(InfoExtractor):
    _VALID_URL = r'https?://(?:chic|www)\.clipsyndicate\.com/video/play(list/\d+)?/(?P<id>\d+)'

    _TESTS = [{
        'url': 'http://www.clipsyndicate.com/video/play/4629301/brick_briscoe',
        'md5': '4d7d549451bad625e0ff3d7bd56d776c',
        'info_dict': {
            'id': '4629301',
            'ext': 'mp4',
            'title': 'Brick Briscoe',
            'duration': 612,
            'thumbnail': r're:^https?://.+\.jpg',
        },
    }, {
        'url': 'http://chic.clipsyndicate.com/video/play/5844117/shark_attack',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        js_player = self._download_webpage(
            'http://eplayer.clipsyndicate.com/embed/player.js?va_id=%s' % video_id,
            video_id, 'Downlaoding player')
        # it includes a required token
        flvars = self._search_regex(r'flvars: "(.*?)"', js_player, 'flvars')

        pdoc = self._download_xml(
            'http://eplayer.clipsyndicate.com/osmf/playlist?%s' % flvars,
            video_id, 'Downloading video info',
            transform_source=fix_xml_ampersands)

        track_doc = pdoc.find('trackList/track')

        def find_param(name):
            node = find_xpath_attr(track_doc, './/param', 'name', name)
            if node is not None:
                return node.attrib['value']

        return {
            'id': video_id,
            'title': find_param('title'),
            'url': track_doc.find('location').text,
            'thumbnail': find_param('thumbnail'),
            'duration': int(find_param('duration')),
        }


code:
import re

from .common import InfoExtractor

class CloserToTruthIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?closertotruth\.com/(?:[^/]+/)*(?P<id>[^/?#&]+)'
    _TESTS = [{
        'url': 'http://closertotruth.com/series/solutions-the-mind-body-problem#video-3688',
        'info_dict': {
            'id': '0_zof1ktre',
            'display_id': 'solutions-the-mind-body-problem',
            'ext': 'mov',
            'title': 'Solutions to the Mind-Body Problem?',
            'upload_date': '20140221',
            'timestamp': 1392956007,
            'uploader_id': 'CTTXML'
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'http://closertotruth.com/episodes/how-do-brains-work',
        'info_dict': {
            'id': '0_iuxai6g6',
            'display_id': 'how-do-brains-work',
            'ext': 'mov',
            'title': 'How do Brains Work?',
            'upload_date': '20140221',
            'timestamp': 1392956024,
            'uploader_id': 'CTTXML'
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'http://closertotruth.com/interviews/1725',
        'info_dict': {
            'id': '1725',
            'title': 'AyaFr-002',
        },
        'playlist_mincount': 2,
    }]

    def _real_extract(self, url):
        display_id = self._match_id(url)

        webpage = self._download_webpage(url, display_id)

        partner_id = self._search_regex(
            r'<script[^>]+src=["\'].*?\b(?:partner_id|p)/(\d+)',
            webpage, 'kaltura partner_id')

        title = self._html_extract_title(webpage, 'video title')

        select = self._search_regex(
            r'(?s)<select[^>]+id="select-version"[^>]*>(.+?)</select>',
            webpage, 'select version', default=None)
        if select:
            entry_ids = set()
            entries = []
            for mobj in re.finditer(
                    r'<option[^>]+value=(["\'])(?P<id>[0-9a-z_]+)(?:#.+?)?\1[^>]*>(?P<title>[^<]+)',
                    webpage):
                entry_id = mobj.group('id')
                if entry_id in entry_ids:
                    continue
                entry_ids.add(entry_id)
                entries.append({
                    '_type': 'url_transparent',
                    'url': 'kaltura:%s:%s' % (partner_id, entry_id),
                    'ie_key': 'Kaltura',
                    'title': mobj.group('title'),
                })
            if entries:
                return self.playlist_result(entries, display_id, title)

        entry_id = self._search_regex(
            r'<a[^>]+id=(["\'])embed-kaltura\1[^>]+data-kaltura=(["\'])(?P<id>[0-9a-z_]+)\2',
            webpage, 'kaltura entry_id', group='id')

        return {
            '_type': 'url_transparent',
            'display_id': display_id,
            'url': 'kaltura:%s:%s' % (partner_id, entry_id),
            'ie_key': 'Kaltura',
            'title': title
        }


code:
import base64

from .common import InfoExtractor

class CloudflareStreamIE(InfoExtractor):
    _DOMAIN_RE = r'(?:cloudflarestream\.com|(?:videodelivery|bytehighway)\.net)'
    _EMBED_RE = r'embed\.%s/embed/[^/]+\.js\?.*?\bvideo=' % _DOMAIN_RE
    _ID_RE = r'[\da-f]{32}|[\w-]+\.[\w-]+\.[\w-]+'
    _VALID_URL = r'''(?x)
                    https?://
                        (?:
                            (?:watch\.)?%s/|
                            %s
                        )
                        (?P<id>%s)
                    ''' % (_DOMAIN_RE, _EMBED_RE, _ID_RE)
    _EMBED_REGEX = [fr'<script[^>]+\bsrc=(["\'])(?P<url>(?:https?:)?//{_EMBED_RE}(?:{_ID_RE}).*?)\1']
    _TESTS = [{
        'url': 'https://embed.cloudflarestream.com/embed/we4g.fla9.latest.js?video=31c9291ab41fac05471db4e73aa11717',
        'info_dict': {
            'id': '31c9291ab41fac05471db4e73aa11717',
            'ext': 'mp4',
            'title': '31c9291ab41fac05471db4e73aa11717',
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'https://watch.cloudflarestream.com/9df17203414fd1db3e3ed74abbe936c1',
        'only_matching': True,
    }, {
        'url': 'https://cloudflarestream.com/31c9291ab41fac05471db4e73aa11717/manifest/video.mpd',
        'only_matching': True,
    }, {
        'url': 'https://embed.videodelivery.net/embed/r4xu.fla9.latest.js?video=81d80727f3022488598f68d323c1ad5e',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        domain = 'bytehighway.net' if 'bytehighway.net/' in url else 'videodelivery.net'
        base_url = 'https://%s/%s/' % (domain, video_id)
        if '.' in video_id:
            video_id = self._parse_json(base64.urlsafe_b64decode(
                video_id.split('.')[1] + '==='), video_id)['sub']
        manifest_base_url = base_url + 'manifest/video.'

        formats = self._extract_m3u8_formats(
            manifest_base_url + 'm3u8', video_id, 'mp4',
            'm3u8_native', m3u8_id='hls', fatal=False)
        formats.extend(self._extract_mpd_formats(
            manifest_base_url + 'mpd', video_id, mpd_id='dash', fatal=False))
        self._sort_formats(formats)

        return {
            'id': video_id,
            'title': video_id,
            'thumbnail': base_url + 'thumbnails/thumbnail.jpg',
            'formats': formats,
        }


code:
from .common import InfoExtractor
from ..utils import (
    str_to_int,
    unified_strdate,
)

class CloudyIE(InfoExtractor):
    _IE_DESC = 'cloudy.ec'
    _VALID_URL = r'https?://(?:www\.)?cloudy\.ec/(?:v/|embed\.php\?.*?\bid=)(?P<id>[A-Za-z0-9]+)'
    _TESTS = [{
        'url': 'https://www.cloudy.ec/v/af511e2527aac',
        'md5': '29832b05028ead1b58be86bf319397ca',
        'info_dict': {
            'id': 'af511e2527aac',
            'ext': 'mp4',
            'title': 'Funny Cats and Animals Compilation june 2013',
            'upload_date': '20130913',
            'view_count': int,
        }
    }, {
        'url': 'http://www.cloudy.ec/embed.php?autoplay=1&id=af511e2527aac',
        'only_matching': True,
    }]

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

        webpage = self._download_webpage(
            'https://www.cloudy.ec/embed.php', video_id, query={
                'id': video_id,
                'playerPage': 1,
                'autoplay': 1,
            })

        info = self._parse_html5_media_entries(url, webpage, video_id)[0]

        webpage = self._download_webpage(
            'https://www.cloudy.ec/v/%s' % video_id, video_id, fatal=False)

        if webpage:
            info.update({
                'title': self._search_regex(
                    r'<h\d[^>]*>([^<]+)<', webpage, 'title'),
                'upload_date': unified_strdate(self._search_regex(
                    r'>Published at (\d{4}-\d{1,2}-\d{1,2})', webpage,
                    'upload date', fatal=False)),
                'view_count': str_to_int(self._search_regex(
                    r'([\d,.]+) views<', webpage, 'view count', fatal=False)),
            })

        if not info.get('title'):
            info['title'] = video_id

        info['id'] = video_id

        return info


code:
from .common import InfoExtractor
from ..utils import (
    clean_html,
    qualities,
)

class ClubicIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?clubic\.com/video/(?:[^/]+/)*video.*-(?P<id>[0-9]+)\.html'

    _TESTS = [{
        'url': 'http://www.clubic.com/video/clubic-week/video-clubic-week-2-0-le-fbi-se-lance-dans-la-photo-d-identite-448474.html',
        'md5': '1592b694ba586036efac1776b0b43cd3',
        'info_dict': {
            'id': '448474',
            'ext': 'mp4',
            'title': 'Clubic Week 2.0 : le FBI se lance dans la photo d\u0092identité',
            'description': 're:Gueule de bois chez Nokia. Le constructeur a indiqué cette.*',
            'thumbnail': r're:^http://img\.clubic\.com/.*\.jpg$',
        }
    }, {
        'url': 'http://www.clubic.com/video/video-clubic-week-2-0-apple-iphone-6s-et-plus-mais-surtout-le-pencil-469792.html',
        'only_matching': True,
    }]

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

        player_url = 'http://player.m6web.fr/v1/player/clubic/%s.html' % video_id
        player_page = self._download_webpage(player_url, video_id)

        config = self._parse_json(self._search_regex(
            r'(?m)M6\.Player\.config\s*=\s*(\{.+?\});$', player_page,
            'configuration'), video_id)

        video_info = config['videoInfo']
        sources = config['sources']
        quality_order = qualities(['sd', 'hq'])

        formats = [{
            'format_id': src['streamQuality'],
            'url': src['src'],
            'quality': quality_order(src['streamQuality']),
        } for src in sources]
        self._sort_formats(formats)

        return {
            'id': video_id,
            'title': video_info['title'],
            'formats': formats,
            'description': clean_html(video_info.get('description')),
            'thumbnail': config.get('poster'),
        }


code:
from .common import InfoExtractor
from ..utils import (
    float_or_none,
    parse_qs,
    unified_timestamp,
)

class ClypIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?clyp\.it/(?P<id>[a-z0-9]+)'
    _TESTS = [{
        'url': 'https://clyp.it/ojz2wfah',
        'md5': '1d4961036c41247ecfdcc439c0cddcbb',
        'info_dict': {
            'id': 'ojz2wfah',
            'ext': 'mp3',
            'title': 'Krisson80 - bits wip wip',
            'description': '#Krisson80BitsWipWip #chiptune\n#wip',
            'duration': 263.21,
            'timestamp': 1443515251,
            'upload_date': '20150929',
        },
    }, {
        'url': 'https://clyp.it/b04p1odi?token=b0078e077e15835845c528a44417719d',
        'info_dict': {
            'id': 'b04p1odi',
            'ext': 'mp3',
            'title': 'GJ! (Reward Edit)',
            'description': 'Metal Resistance (THE ONE edition)',
            'duration': 177.789,
            'timestamp': 1528241278,
            'upload_date': '20180605',
        },
        'params': {
            'skip_download': True,
        },
    }]

    def _real_extract(self, url):
        audio_id = self._match_id(url)

        qs = parse_qs(url)
        token = qs.get('token', [None])[0]

        query = {}
        if token:
            query['token'] = token

        metadata = self._download_json(
            'https://api.clyp.it/%s' % audio_id, audio_id, query=query)

        formats = []
        for secure in ('', 'Secure'):
            for ext in ('Ogg', 'Mp3'):
                format_id = '%s%s' % (secure, ext)
                format_url = metadata.get('%sUrl' % format_id)
                if format_url:
                    formats.append({
                        'url': format_url,
                        'format_id': format_id,
                        'vcodec': 'none',
                    })
        self._sort_formats(formats)

        title = metadata['Title']
        description = metadata.get('Description')
        duration = float_or_none(metadata.get('Duration'))
        timestamp = unified_timestamp(metadata.get('DateCreated'))

        return {
            'id': audio_id,
            'title': title,
            'description': description,
            'duration': duration,
            'timestamp': timestamp,
            'formats': formats,
        }


code:
from .mtv import MTVIE

# TODO Remove - Reason: Outdated Site

class CMTIE(MTVIE):
    IE_NAME = 'cmt.com'
    _VALID_URL = r'https?://(?:www\.)?cmt\.com/(?:videos|shows|(?:full-)?episodes|video-clips)/(?P<id>[^/]+)'

    _TESTS = [{
        'url': 'http://www.cmt.com/videos/garth-brooks/989124/the-call-featuring-trisha-yearwood.jhtml#artist=30061',
        'md5': 'e6b7ef3c4c45bbfae88061799bbba6c2',
        'info_dict': {
            'id': '989124',
            'ext': 'mp4',
            'title': 'Garth Brooks - "The Call (featuring Trisha Yearwood)"',
            'description': 'Blame It All On My Roots',
        },
        'skip': 'Video not available',
    }, {
        'url': 'http://www.cmt.com/videos/misc/1504699/still-the-king-ep-109-in-3-minutes.jhtml#id=1739908',
        'md5': 'e61a801ca4a183a466c08bd98dccbb1c',
        'info_dict': {
            'id': '1504699',
            'ext': 'mp4',
            'title': 'Still The King Ep. 109 in 3 Minutes',
            'description': 'Relive or catch up with Still The King by watching this recap of season 1, episode 9.',
            'timestamp': 1469421000.0,
            'upload_date': '20160725',
        },
    }, {
        'url': 'http://www.cmt.com/shows/party-down-south/party-down-south-ep-407-gone-girl/1738172/playlist/#id=1738172',
        'only_matching': True,
    }, {
        'url': 'http://www.cmt.com/full-episodes/537qb3/nashville-the-wayfaring-stranger-season-5-ep-501',
        'only_matching': True,
    }, {
        'url': 'http://www.cmt.com/video-clips/t9e4ci/nashville-juliette-in-2-minutes',
        'only_matching': True,
    }]

    def _extract_mgid(self, webpage, url):
        mgid = self._search_regex(
            r'MTVN\.VIDEO\.contentUri\s*=\s*([\'"])(?P<mgid>.+?)\1',
            webpage, 'mgid', group='mgid', default=None)
        if not mgid:
            mgid = self._extract_triforce_mgid(webpage)
        return mgid

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        mgid = self._extract_mgid(webpage, url)
        return self.url_result('http://media.mtvnservices.com/embed/%s' % mgid)


code:
from .common import InfoExtractor
from ..utils import smuggle_url

class CNBCIE(InfoExtractor):
    _VALID_URL = r'https?://video\.cnbc\.com/gallery/\?video=(?P<id>[0-9]+)'
    _TEST = {
        'url': 'http://video.cnbc.com/gallery/?video=3000503714',
        'info_dict': {
            'id': '3000503714',
            'ext': 'mp4',
            'title': 'Fighting zombies is big business',
            'description': 'md5:0c100d8e1a7947bd2feec9a5550e519e',
            'timestamp': 1459332000,
            'upload_date': '20160330',
            'uploader': 'NBCU-CNBC',
        },
        'params': {
            # m3u8 download
            'skip_download': True,
        },
    }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        return {
            '_type': 'url_transparent',
            'ie_key': 'ThePlatform',
            'url': smuggle_url(
                'http://link.theplatform.com/s/gZWlPC/media/guid/2408950221/%s?mbr=true&manifest=m3u' % video_id,
                {'force_smil_url': True}),
            'id': video_id,
        }

class CNBCVideoIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?cnbc\.com(?P<path>/video/(?:[^/]+/)+(?P<id>[^./?#&]+)\.html)'
    _TEST = {
        'url': 'https://www.cnbc.com/video/2018/07/19/trump-i-dont-necessarily-agree-with-raising-rates.html',
        'info_dict': {
            'id': '7000031301',
            'ext': 'mp4',
            'title': "Trump: I don't necessarily agree with raising rates",
            'description': 'md5:878d8f0b4ebb5bb1dda3514b91b49de3',
            'timestamp': 1531958400,
            'upload_date': '20180719',
            'uploader': 'NBCU-CNBC',
        },
        'params': {
            'skip_download': True,
        },
    }

    def _real_extract(self, url):
        path, display_id = self._match_valid_url(url).groups()
        video_id = self._download_json(
            'https://webql-redesign.cnbcfm.com/graphql', display_id, query={
                'query': '''{
  page(path: "%s") {
    vcpsId
  }
}''' % path,
            })['data']['page']['vcpsId']
        return self.url_result(
            'http://video.cnbc.com/gallery/?video=%d' % video_id,
            CNBCIE.ie_key())


code:
from .common import InfoExtractor
from .turner import TurnerBaseIE
from ..utils import url_basename

class CNNIE(TurnerBaseIE):
    _VALID_URL = r'''(?x)https?://(?:(?P<sub_domain>edition|www|money)\.)?cnn\.com/(?:video/(?:data/.+?|\?)/)?videos?/
        (?P<path>.+?/(?P<title>[^/]+?)(?:\.(?:[a-z\-]+)|(?=&)))'''

    _TESTS = [{
        'url': 'http://edition.cnn.com/video/?/video/sports/2013/06/09/nadal-1-on-1.cnn',
        'md5': '3e6121ea48df7e2259fe73a0628605c4',
        'info_dict': {
            'id': 'sports/2013/06/09/nadal-1-on-1.cnn',
            'ext': 'mp4',
            'title': 'Nadal wins 8th French Open title',
            'description': 'World Sport\'s Amanda Davies chats with 2013 French Open champion Rafael Nadal.',
            'duration': 135,
            'upload_date': '20130609',
        },
        'expected_warnings': ['Failed to download m3u8 information'],
    }, {
        'url': 'http://edition.cnn.com/video/?/video/us/2013/08/21/sot-student-gives-epic-speech.georgia-institute-of-technology&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+rss%2Fcnn_topstories+%28RSS%3A+Top+Stories%29',
        'md5': 'b5cc60c60a3477d185af8f19a2a26f4e',
        'info_dict': {
            'id': 'us/2013/08/21/sot-student-gives-epic-speech.georgia-institute-of-technology',
            'ext': 'mp4',
            'title': "Student's epic speech stuns new freshmen",
            'description': "A Georgia Tech student welcomes the incoming freshmen with an epic speech backed by music from \"2001: A Space Odyssey.\"",
            'upload_date': '20130821',
        },
        'expected_warnings': ['Failed to download m3u8 information'],
    }, {
        'url': 'http://www.cnn.com/video/data/2.0/video/living/2014/12/22/growing-america-nashville-salemtown-board-episode-1.hln.html',
        'md5': 'f14d02ebd264df951feb2400e2c25a1b',
        'info_dict': {
            'id': 'living/2014/12/22/growing-america-nashville-salemtown-board-episode-1.hln',
            'ext': 'mp4',
            'title': 'Nashville Ep. 1: Hand crafted skateboards',
            'description': 'md5:e7223a503315c9f150acac52e76de086',
            'upload_date': '20141222',
        },
        'expected_warnings': ['Failed to download m3u8 information'],
    }, {
        'url': 'http://money.cnn.com/video/news/2016/08/19/netflix-stunning-stats.cnnmoney/index.html',
        'md5': '52a515dc1b0f001cd82e4ceda32be9d1',
        'info_dict': {
            'id': '/video/news/2016/08/19/netflix-stunning-stats.cnnmoney',
            'ext': 'mp4',
            'title': '5 stunning stats about Netflix',
            'description': 'Did you know that Netflix has more than 80 million members? Here are five facts about the online video distributor that you probably didn\'t know.',
            'upload_date': '20160819',
        },
        'params': {
            # m3u8 download
            'skip_download': True,
        },
    }, {
        'url': 'http://cnn.com/video/?/video/politics/2015/03/27/pkg-arizona-senator-church-attendance-mandatory.ktvk',
        'only_matching': True,
    }, {
        'url': 'http://cnn.com/video/?/video/us/2015/04/06/dnt-baker-refuses-anti-gay-order.wkmg',
        'only_matching': True,
    }, {
        'url': 'http://edition.cnn.com/videos/arts/2016/04/21/olympic-games-cultural-a-z-brazil.cnn',
        'only_matching': True,
    }]

    _CONFIG = {
        # http://edition.cnn.com/.element/apps/cvp/3.0/cfg/spider/cnn/expansion/config.xml
        'edition': {
            'data_src': 'http://edition.cnn.com/video/data/3.0/video/%s/index.xml',
            'media_src': 'http://pmd.cdn.turner.com/cnn/big',
        },
        # http://money.cnn.com/.element/apps/cvp2/cfg/config.xml
        'money': {
            'data_src': 'http://money.cnn.com/video/data/4.0/video/%s.xml',
            'media_src': 'http://ht3.cdn.turner.com/money/big',
        },
    }

    def _extract_timestamp(self, video_data):
        # TODO: fix timestamp extraction
        return None

    def _real_extract(self, url):
        sub_domain, path, page_title = self._match_valid_url(url).groups()
        if sub_domain not in ('money', 'edition'):
            sub_domain = 'edition'
        config = self._CONFIG[sub_domain]
        return self._extract_cvp_info(
            config['data_src'] % path, page_title, {
                'default': {
                    'media_src': config['media_src'],
                },
                'f4m': {
                    'host': 'cnn-vh.akamaihd.net',
                },
            })

class CNNBlogsIE(InfoExtractor):
    _VALID_URL = r'https?://[^\.]+\.blogs\.cnn\.com/.+'
    _TEST = {
        'url': 'http://reliablesources.blogs.cnn.com/2014/02/09/criminalizing-journalism/',
        'md5': '3e56f97b0b6ffb4b79f4ea0749551084',
        'info_dict': {
            'id': 'bestoftv/2014/02/09/criminalizing-journalism.cnn',
            'ext': 'mp4',
            'title': 'Criminalizing journalism?',
            'description': 'Glenn Greenwald responds to comments made this week on Capitol Hill that journalists could be criminal accessories.',
            'upload_date': '20140209',
        },
        'expected_warnings': ['Failed to download m3u8 information'],
        'add_ie': ['CNN'],
    }

    def _real_extract(self, url):
        webpage = self._download_webpage(url, url_basename(url))
        cnn_url = self._html_search_regex(r'data-url="(.+?)"', webpage, 'cnn url')
        return self.url_result(cnn_url, CNNIE.ie_key())

class CNNArticleIE(InfoExtractor):
    _VALID_URL = r'https?://(?:(?:edition|www)\.)?cnn\.com/(?!videos?/)'
    _TEST = {
        'url': 'http://www.cnn.com/2014/12/21/politics/obama-north-koreas-hack-not-war-but-cyber-vandalism/',
        'md5': '689034c2a3d9c6dc4aa72d65a81efd01',
        'info_dict': {
            'id': 'bestoftv/2014/12/21/ip-north-korea-obama.cnn',
            'ext': 'mp4',
            'title': 'Obama: Cyberattack not an act of war',
            'description': 'md5:0a802a40d2376f60e6b04c8d5bcebc4b',
            'upload_date': '20141221',
        },
        'expected_warnings': ['Failed to download m3u8 information'],
        'add_ie': ['CNN'],
    }

    def _real_extract(self, url):
        webpage = self._download_webpage(url, url_basename(url))
        cnn_url = self._html_search_regex(r"video:\s*'([^']+)'", webpage, 'cnn url')
        return self.url_result('http://cnn.com/video/?/video/' + cnn_url, CNNIE.ie_key())


code:
from .mtv import MTVServicesInfoExtractor

class ComedyCentralIE(MTVServicesInfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?cc\.com/(?:episodes|video(?:-clips)?|collection-playlist)/(?P<id>[0-9a-z]{6})'
    _FEED_URL = 'http://comedycentral.com/feeds/mrss/'

    _TESTS = [{
        'url': 'http://www.cc.com/video-clips/5ke9v2/the-daily-show-with-trevor-noah-doc-rivers-and-steve-ballmer---the-nba-player-strike',
        'md5': 'b8acb347177c680ff18a292aa2166f80',
        'info_dict': {
            'id': '89ccc86e-1b02-4f83-b0c9-1d9592ecd025',
            'ext': 'mp4',
            'title': 'The Daily Show with Trevor Noah|August 28, 2020|25|25149|Doc Rivers and Steve Ballmer - The NBA Player Strike',
            'description': 'md5:5334307c433892b85f4f5e5ac9ef7498',
            'timestamp': 1598670000,
            'upload_date': '20200829',
        },
    }, {
        'url': 'http://www.cc.com/episodes/pnzzci/drawn-together--american-idol--parody-clip-show-season-3-ep-314',
        'only_matching': True,
    }, {
        'url': 'https://www.cc.com/video/k3sdvm/the-daily-show-with-jon-stewart-exclusive-the-fourth-estate',
        'only_matching': True,
    }, {
        'url': 'https://www.cc.com/collection-playlist/cosnej/stand-up-specials/t6vtjb',
        'only_matching': True,
    }]

class ComedyCentralTVIE(MTVServicesInfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?comedycentral\.tv/folgen/(?P<id>[0-9a-z]{6})'
    _TESTS = [{
        'url': 'https://www.comedycentral.tv/folgen/pxdpec/josh-investigates-klimawandel-staffel-1-ep-1',
        'info_dict': {
            'id': '15907dc3-ec3c-11e8-a442-0e40cf2fc285',
            'ext': 'mp4',
            'title': 'Josh Investigates',
            'description': 'Steht uns das Ende der Welt bevor?',
        },
    }]
    _FEED_URL = 'http://feeds.mtvnservices.com/od/feed/intl-mrss-player-feed'
    _GEO_COUNTRIES = ['DE']

    def _get_feed_query(self, uri):
        return {
            'accountOverride': 'intl.mtvi.com',
            'arcEp': 'web.cc.tv',
            'ep': 'b9032c3a',
            'imageEp': 'web.cc.tv',
            'mgid': uri,
        }