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

Code before:
import re

from .common import InfoExtractor, ExtractorError
from ..utils import (
    int_or_none,
    float_or_none,
    js_to_json,
    traverse_obj,
    urljoin,
)


class RTFVPlayBaseIE(InfoExtractor):
    _BASE_VALID_URL = r'https?://(?:www\.)?rtvcplay\.co'

    def _extract_player_config(self, webpage, video_id):
        return self._search_json(
            r'<script\b[^>]*>[^<]*(?:var|let|const)\s+config\s*=', re.sub(r'"\s*\+\s*"', '', webpage),
            'player_config', video_id, transform_source=js_to_json)

    def _extract_formats_and_subtitles_player_config(self, player_config, video_id):
        formats, subtitles = [], {}
        for source_type in traverse_obj(player_config, 'sources') or ():
            for media_source in traverse_obj(player_config, ('sources', source_type)) or ():
                if source_type == 'hls':
                    fmts, subs = self._extract_m3u8_formats_and_subtitles(
                        media_source.get('url'), video_id, 'mp4', fatal=False)
                    formats.extend(fmts)
                    self._merge_subtitles(subs, target=subtitles)
                else:
                    formats.append({
                        'url': media_source.get('url'),
                    })

        return formats, subtitles


class RTVCPlayIE(RTFVPlayBaseIE):
    _VALID_URL = RTFVPlayBaseIE._BASE_VALID_URL + r'/(?P<category>(?!embed)[^/]+)/(?:[^?#]+/)?(?P<id>[\w-]+)'

    _TESTS = [{
        'url': 'https://www.rtvcplay.co/en-vivo/canal-institucional',
        'info_dict': {
            'id': 'canal-institucional',
            'title': r're:^Canal Institucional',
            'description': 'md5:eff9e548394175928059320c006031ea',
            'thumbnail': r're:^https?://.*\.(?:jpg|png)',

Review comment (suggestion):
hm, so the `url` values look like this before `re.sub` and `js_to_json`:
```
url: "https://streaming.rtvc.gov.co/RTVCPlay-vod/smil:"+"497115" +".smil/playlist.m3u8"
```
I wonder if an improvement could be made to `js_to_json` to handle this

Code after:
import re

from .common import InfoExtractor, ExtractorError
from ..utils import (
    clean_html,
    determine_ext,
    int_or_none,
    float_or_none,
    js_to_json,
    mimetype2ext,
    traverse_obj,
    urljoin,
    url_or_none,
)


class RTVCPlayBaseIE(InfoExtractor):
    _BASE_VALID_URL = r'https?://(?:www\.)?rtvcplay\.co'

    def _extract_player_config(self, webpage, video_id):
        return self._search_json(
            r'<script\b[^>]*>[^<]*(?:var|let|const)\s+config\s*=', re.sub(r'"\s*\+\s*"', '', webpage),
            'player_config', video_id, transform_source=js_to_json)

    def _extract_formats_and_subtitles_player_config(self, player_config, video_id):
        formats, subtitles = [], {}
        for source in traverse_obj(player_config, ('sources', ..., lambda _, v: url_or_none(v['url']))):
            ext = mimetype2ext(source.get('mimetype'), default=determine_ext(source['url']))
            if ext == 'm3u8':
                fmts, subs = self._extract_m3u8_formats_and_subtitles(
                    source['url'], video_id, 'mp4', fatal=False)
                formats.extend(fmts)
                self._merge_subtitles(subs, target=subtitles)
            else:
                formats.append({
                    'url': source['url'],
                    'ext': ext,
                })

        return formats, subtitles


class RTVCPlayIE(RTVCPlayBaseIE):
    _VALID_URL = RTVCPlayBaseIE._BASE_VALID_URL + r'/(?P<category>(?!embed)[^/]+)/(?:[^?#]+/)?(?P<id>[\w-]+)'

    _TESTS = [{
        'url': 'https://www.rtvcplay.co/en-vivo/canal-institucional',