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

Code before:
    _VALID_URL = r'https?://(?:www\.)?tvw\.org/tvchannels/(?P<id>[^/?#]+)'
    _TESTS = [{
        'url': 'https://tvw.org/tvchannels/air/',
        'info_dict': {
            'id': 'TVWAIR',
            'ext': 'mp4',
            'display_id': 'air',
            'title': r're:^TVW Cable Channel Live Stream',
            'thumbnail': r're:^https?://.*\.(?:jpe?g|png)$',
            'live_status': 'is_live',
        },
    }, {
        'url': 'https://tvw.org/tvchannels/tvw2/',
        'info_dict': {
            'id': 'TVW2',
            'ext': 'mp4',
            'display_id': 'tvw2',
            'title': r're:^TVW-2 Broadcast Channel',
            'thumbnail': r're:^https?://.*\.(?:jpe?g|png)$',
            'live_status': 'is_live',
        },
    }]

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

        stream_url = self._html_search_regex(r"<iframe[\s]*id=\"invintus-persistent-stream-frame\"[^>]+src=[\"\'](?P<url>.+?)[\"\']", webpage, 'url')
        parsed_url = urllib.parse.urlparse(unescapeHTML(stream_url))
        parsed_querystring = urllib.parse.parse_qs(parsed_url.query)

        encoder_obj = json.loads(traverse_obj(parsed_querystring, ('encoder', 0)))

        video_id = encoder_obj.get('streamName')
        m3u8_url = encoder_obj.get('live247URI')

        formats = self._extract_m3u8_formats(m3u8_url, video_id, 'mp4', m3u8_id='hls', fatal=True)

        return {
            'id': video_id,
            'display_id': display_id,
            'formats': formats,
            'title': remove_end(self._og_search_title(webpage, default=None), ' - TVW'),
            'thumbnail': self._og_search_thumbnail(webpage, default=None),
            'is_live': True,
        }


Review comment (refactor):
I think I would just leave the id from the URL as the `video_id`. `streamName` does not seem like a better id to me. It also means if the stream name were ever to not be present the stream could still be extracted.
```suggestion
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
```

Code after:
                'is_live': ('eventStatus', {lambda x: x == 'live'}),
            }),
        }


class TvwTvChannelsIE(InfoExtractor):
    IE_NAME = 'tvw:tvchannels'
    _VALID_URL = r'https?://(?:www\.)?tvw\.org/tvchannels/(?P<id>[^/?#]+)'
    _TESTS = [{
        'url': 'https://tvw.org/tvchannels/air/',
        'info_dict': {
            'id': 'air',
            'ext': 'mp4',
            'title': r're:TVW Cable Channel Live Stream',
            'thumbnail': r're:https?://.+/.+\.(?:jpe?g|png)$',
            'live_status': 'is_live',
        },
    }, {
        'url': 'https://tvw.org/tvchannels/tvw2/',
        'info_dict': {
            'id': 'tvw2',
            'ext': 'mp4',
            'title': r're:TVW-2 Broadcast Channel',
            'thumbnail': r're:https?://.+/.+\.(?:jpe?g|png)$',
            'live_status': 'is_live',
        },
    }]

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

        m3u8_url = traverse_obj(webpage, (
            {find_element(id='invintus-persistent-stream-frame', html=True)}, {extract_attributes},
            'src', {parse_qs}, 'encoder', 0, {json.loads}, 'live247URI', {url_or_none}, {require('stream url')}))

        return {
            'id': video_id,
            'formats': self._extract_m3u8_formats(m3u8_url, video_id, 'mp4', m3u8_id='hls', live=True),
            'title': remove_end(self._og_search_title(webpage, default=None), ' - TVW'),
            'thumbnail': self._og_search_thumbnail(webpage, default=None),
            'is_live': True,
        }