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

Code before:
            'series': '트롤리',
            'episode': '이거 다 거짓말이야',
            'episode_number': 15,
        },
    }, {
        'url': 'https://programs.sbs.co.kr/enter/fourman/vod/69625/22000508948',
        'md5': '41e8ae4cc6c8424f4e4d76661a4becbf',
        'info_dict': {
            'id': '22000508948',
            'ext': 'mp4',
            'title': '[다시보기] 신발 벗고 돌싱포맨 104회',
            'description': 'md5:c6a247383c4dd661e4b956bf4d3b586e',
            'thumbnail': 'https://img2.sbs.co.kr/img/sbs_cms/WE/2023/08/30/2vb1693355446261-1280-720.jpg',
            'release_timestamp': 1693342800,
            'release_date': '20230829',
            'view_count': int,
            'like_count': int,
            'duration': 7036,
            'age_limit': 15,
            'series': '신발 벗고 돌싱포맨',
            'episode': '돌싱포맨 저격수들 등장!',
            'episode_number': 104,
        },
    }]

    def request_details(self, video_id, rscuse=''):
        return self._download_json(
            f'https://api.play.sbs.co.kr/1.0/sbs_vodall/{video_id}', video_id,
            note=f'Downloading m3u8 information {rscuse}',
            query={
                'platform': 'pcweb',
                'protocol': 'download',
                'absolute_show': 'Y',
                'service': 'program',
                'ssl': 'Y',
                'rscuse': rscuse,
            })

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

        details = self.request_details(video_id)
        source = traverse_obj(details, ('vod', 'source', 'mediasource'))

        formats = []
        for stream in traverse_obj(details, ('vod', 'source', 'mediasourcelist'), default=[source]):
            if not stream.get('mediaurl'):
                alt_details = self.request_details(video_id, rscuse=stream.get('mediarscuse'))
                new_source = traverse_obj(alt_details, ('vod', 'source', 'mediasource'))
                if new_source.get('mediarscuse') == source.get('mediarscuse') or not new_source.get('mediaurl'):
                    continue

Review comment (suggestion):
`_call_api` is the convention
```suggestion
    def _call_api(self, video_id, rscuse=''):
```

Code after:
            'series': '트롤리',
            'episode': '이거 다 거짓말이야',
            'episode_number': 15,
        },
    }, {
        'url': 'https://programs.sbs.co.kr/enter/fourman/vod/69625/22000508948',
        'md5': '41e8ae4cc6c8424f4e4d76661a4becbf',
        'info_dict': {
            'id': '22000508948',
            'ext': 'mp4',
            'title': '[다시보기] 신발 벗고 돌싱포맨 104회',
            'description': 'md5:c6a247383c4dd661e4b956bf4d3b586e',
            'thumbnail': 'https://img2.sbs.co.kr/img/sbs_cms/WE/2023/08/30/2vb1693355446261-1280-720.jpg',
            'release_timestamp': 1693342800,
            'release_date': '20230829',
            'view_count': int,
            'like_count': int,
            'duration': 7036,
            'age_limit': 15,
            'series': '신발 벗고 돌싱포맨',
            'episode': '돌싱포맨 저격수들 등장!',
            'episode_number': 104,
        },
    }]

    def _call_api(self, video_id, rscuse=''):
        return self._download_json(
            f'https://api.play.sbs.co.kr/1.0/sbs_vodall/{video_id}', video_id,
            note=f'Downloading m3u8 information {rscuse}',
            query={
                'platform': 'pcweb',
                'protocol': 'download',
                'absolute_show': 'Y',
                'service': 'program',
                'ssl': 'Y',
                'rscuse': rscuse,
            })

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

        details = self._call_api(video_id)
        source = traverse_obj(details, ('vod', 'source', 'mediasource', {dict})) or {}

        formats = []
        for stream in traverse_obj(details, (
            'vod', 'source', 'mediasourcelist', lambda _, v: v['mediaurl'] or v['mediarscuse']
        ), default=[source]):
            if not stream.get('mediaurl'):
                new_source = traverse_obj(
                    self._call_api(video_id, rscuse=stream['mediarscuse']),