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

Code before:

        auth_token, area_id = self._auth_client()

        prog, station_program, ft, ft_str, to_str = self._find_program(video_id, station, vid_int)

        title = prog.find('title').text
        description = clean_html(prog.find('info').text)
        station_name = station_program.find('.//name').text

        formats = self._extract_formats(video_id, station, False, ft, vid_int, auth_token, area_id, {
            'start_at': ft_str,  # begin time of the radio
            'ft': ft_str,  # same as start_id
            'end_at': to_str,  # end time of the radio
            'to': to_str,  # same as end_at
            'seek': video_id,
        })

        return {
            'id': video_id,
            'title': title,
            'description': description,
            'uploader': station_name,
            'uploader_id': station,
            'timestamp': vid_int,
            'formats': formats,
            # we have to mark this live since they behave as if it's a live
            'is_live': True,
        }


class RadikoRadioIE(RadikoBaseIE):
    _VALID_URL = r'https?://(?:www\.)?radiko\.jp/#!/live/(?P<id>[A-Z0-9-]+)'

    _TESTS = [{
        # QRR (文化放送) station provides <desc>
        'url': 'https://radiko.jp/#!/live/QRR',
        'only_matching': True,
    }, {
        # FMT (TOKYO FM) station does not provide <desc>
        'url': 'https://radiko.jp/#!/live/FMT',
        'only_matching': True,
    }, {
        'url': 'https://radiko.jp/#!/live/JOAK-FM',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        station = self._match_id(url)
        self.report_warning('Downloader will not stop at the end of the program! Be careful.')

        auth_token, area_id = self._auth_client()

Review comment (suggestion):
wdym? it IS live unless I am mistaken. Note that live doesn't mean the video is being recorded and played back at real time; just that it is a livestream (eg: youtube premiers are considered live)

Code after:
        vid_int = unified_timestamp(video_id, False)

        auth_token, area_id = self._auth_client()

        prog, station_program, ft, radio_begin, radio_end = self._find_program(video_id, station, vid_int)

        title = prog.find('title').text
        description = clean_html(prog.find('info').text)
        station_name = station_program.find('.//name').text

        formats = self._extract_formats(
            video_id=video_id, station=station, is_onair=False,
            ft=ft, cursor=vid_int, auth_token=auth_token, area_id=area_id,
            query={
                'start_at': radio_begin,
                'ft': radio_begin,
                'end_at': radio_end,
                'to': radio_end,
                'seek': video_id,
            })

        return {
            'id': video_id,
            'title': title,
            'description': description,
            'uploader': station_name,
            'uploader_id': station,
            'timestamp': vid_int,
            'formats': formats,
            'is_live': True,
        }


class RadikoRadioIE(RadikoBaseIE):
    _VALID_URL = r'https?://(?:www\.)?radiko\.jp/#!/live/(?P<id>[A-Z0-9-]+)'

    _TESTS = [{
        # QRR (文化放送) station provides <desc>
        'url': 'https://radiko.jp/#!/live/QRR',
        'only_matching': True,
    }, {
        # FMT (TOKYO FM) station does not provide <desc>
        'url': 'https://radiko.jp/#!/live/FMT',
        'only_matching': True,
    }, {
        'url': 'https://radiko.jp/#!/live/JOAK-FM',
        'only_matching': True,
    }]

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