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

Code before:
            'uploader': 'TBS',
            'uploader_id': 'tbs',
            'duration': 2761,
            'thumbnail': 'md5:76882f287053dfec6a5adffad70ff1e3',
            'categories': ['エンタメ', '水曜日のダウンタウン', 'ダウンタウン', '浜田雅功', '松本人志', '水ダウ', 'バラエティ', '動画'],
            'cast': ['浜田\u3000雅功', '千原\u3000ジュニア', 'くっきー！（野性爆弾）', '田中\u3000卓志', '菊地\u3000亜美', '池田\u3000美優', '服部\u3000潤'],
            'genres': ['variety'],
            'series': '水曜日のダウンタウン',
            'series_id': '14694',
            'episode': '次世代リアクション王発掘トーナメント',
            'episode_number': 335,
            'episode_id': '14694_2090934_1000117476',
            'timestamp': 1749547434,
            'upload_date': '20250610',
            'release_timestamp': 1749646802,
            'release_date': '20250611',
            'modified_timestamp': 1749647146,
            'modified_date': '20250611',
            'live_status': 'not_live',
        },
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        meta = self._window_app(webpage, 'episode', video_id)
        episode = traverse_obj(meta, ('falcorCache', 'catalog', 'episode', video_id, 'value'))

        return {
            **self._extract_from_streaks_api(
                'tbs', f'ref:{video_id}', headers={'Referer': 'https://cu.tbs.co.jp/'}),
            **traverse_obj(episode, {
                'title': ('title', ..., 'value', {str}, any),
                'cast': ('credit', ..., 'name', ..., 'value', {str}, any, {lambda x: x.split(',')}, filter),
                'categories': ('keywords', ..., {str}, filter, all, filter),
                'description': ('description', ..., 'value', {clean_html}, any),
                'duration': ('tv_episode_info', 'duration', {int_or_none}),
                'episode': ('title', lambda _, v: not v.get('is_phonetic'), 'value', {str}, any),
                'episode_id': ('content_id', {str}),
                'episode_number': ('tv_episode_info', 'episode_number', {int_or_none}),
                'genres': ('genre', ..., {str}, filter, all, filter),
                'release_timestamp': ('pub_date', {unified_timestamp}),
                'series': ('custom_data', 'program_name', {str}),
                'tags': ('tags', ..., {str}, filter, all, filter),
                'thumbnail': ('artwork', ..., 'url', {url_or_none}, any),
                'timestamp': ('created_at', {unified_timestamp}),
                'uploader': ('tv_show_info', 'networks', ..., {str}, any),
            }),
            **traverse_obj(episode, ('tv_episode_info', {
                'duration': ('duration', {int_or_none}),
                'episode_number': ('episode_number', {int_or_none}),

Review comment (suggestion):
```suggestion
        meta = self._window_app(webpage, 'episode', video_id, fatal=False)
```

Code after:
            'uploader': 'TBS',
            'uploader_id': 'tbs',
            'duration': 2752,
            'thumbnail': 'md5:d8855c8c292683c95a84cafdb42300bc',
            'categories': ['エンタメ', '水曜日のダウンタウン', 'ダウンタウン', '浜田雅功', '松本人志', '水ダウ', '動画', 'バラエティ'],
            'cast': ['浜田 雅功', '藤本 敏史', 'ビビる 大木', '千原 ジュニア', '横澤 夏子', 'せいや', 'あの', '服部 潤'],
            'genres': ['variety'],
            'series': '水曜日のダウンタウン',
            'series_id': '14694',
            'episode': 'クロちゃん、寝て起きたら川のほとりにいてその向こう岸に亡くなった父親がいたら死の淵にいるかと思う説 ほか',
            'episode_number': 341,
            'episode_id': '14694_2094162_1000123656',
            'timestamp': 1753778992,
            'upload_date': '20250729',
            'release_timestamp': 1753880402,
            'release_date': '20250730',
            'modified_timestamp': 1753880741,
            'modified_date': '20250730',
            'live_status': 'not_live',
        },
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        meta = self._search_window_app_json(webpage, 'episode', video_id, fatal=False)
        episode = traverse_obj(meta, ('falcorCache', 'catalog', 'episode', video_id, 'value'))

        return {
            **self._extract_from_streaks_api(
                'tbs', f'ref:{video_id}', headers={'Origin': 'https://cu.tbs.co.jp'}),
            **traverse_obj(episode, {
                'title': ('title', ..., 'value', {str}, any),
                'cast': (
                    'credit', ..., 'name', ..., 'value', {clean_html}, any,
                    {lambda x: x.split(',')}, ..., {str.strip}, filter, all, filter),
                'categories': ('keywords', ..., {str}, filter, all, filter),
                'description': ('description', ..., 'value', {clean_html}, any),
                'duration': ('tv_episode_info', 'duration', {int_or_none}),
                'episode': ('title', lambda _, v: not v.get('is_phonetic'), 'value', {str}, any),
                'episode_id': ('content_id', {str}),
                'episode_number': ('tv_episode_info', 'episode_number', {int_or_none}),
                'genres': ('genre', ..., {str}, filter, all, filter),
                'release_timestamp': ('pub_date', {unified_timestamp}),
                'series': ('custom_data', 'program_name', {str}),
                'tags': ('tags', ..., {str}, filter, all, filter),
                'thumbnail': ('artwork', ..., 'url', {url_or_none}, any),
                'timestamp': ('created_at', {unified_timestamp}),
                'uploader': ('tv_show_info', 'networks', ..., {str}, any),
            }),
            **traverse_obj(episode, ('tv_episode_info', {