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

Code before:
            'age_limit': 0,
            'thumbnail': 'https://cdnv.detik.com/videoservice/AdminTV/2022/09/14/f15cae71d7b640c58e75b254ecbb1ce1-20220914071613-0s.jpg?w=400&q=80',
            'display_id': 'pakar-bicara-soal-tim-khusus-jokowi-dan-mereka-yang-pro-ke-bjorka',
            'upload_date': '20220914',
            'release_date': '20220914',
            'description': 'md5:5eb03225f7ee40207dd3a1e18a73f1ff',
            'timestamp': 1663139688,
            'duration': 213.0,
            'tags': ['hacker bjorka', 'bjorka', 'hacker bjorka bocorkan data rahasia presiden jokowi', 'jokowi'],
        }
    }]

    def _extract_from_webpage(self, url, webpage):
        display_id = url_basename(url)
        player_type, video_data = self._search_regex(
            r'<script\s*[^>]+src="https?://(aws)?cdn\.detik\.net\.id/(?P<type>flowplayer|detikVideo)[^>]+>\s*(?P<video_data>{[^}]+})',
            webpage, 'playerjs', group=('type', 'video_data'), default=(None, ''))

        json_ld_data = self._search_json_ld(webpage, display_id, default={})
        extra_info_dict = {}

        if not player_type:
            return

        elif player_type == 'flowplayer':
            video_json_data = self._parse_json(video_data.replace('\'', '"'), None)
            video_url = video_json_data['videoUrl']

            extra_info_dict = {
                'id': self._search_regex(r'identifier\s*:\s*\'([^\']+)', webpage, 'identifier'),
                'thumbnail': video_json_data.get('imageUrl'),
            }

        elif player_type == 'detikVideo':
            video_url = self._search_regex(
                r'videoUrl\s*:\s*[\'"]?([^"\']+)', video_data, 'videoUrl')
            extra_info_dict = {
                'id': self._html_search_meta(['video_id', 'dtk:video_id'], webpage),
                'thumbnail': self._search_regex(r'imageUrl\s*:\s*[\'"]?([^"\']+)', video_data, 'videoUrl'),
                'duration': int_or_none(self._html_search_meta('duration', webpage, fatal=False, default=None)),
                'release_timestamp': int_or_none(self._html_search_meta('dtk:publishdateunix', webpage, fatal=False, default=None), 1000),
                'timestamp': int_or_none(self._html_search_meta('dtk:createdateunix', webpage, fatal=False, default=None), 1000),
                'uploader': self._search_regex(
                    r'([^-]+)', self._html_search_meta('dtk:author', webpage, default='').strip(), 'uploader',
                    default=None)
            }

        formats, subtitles = self._extract_m3u8_formats_and_subtitles(video_url, display_id)
        self._sort_formats(formats)

        yield merge_dicts(json_ld_data, extra_info_dict, {

Review comment (suggestion):
```suggestion
            video_json_data = self._parse_json(video_data.replace('\'', '"'), display_id)
```

Code after:
            'age_limit': 0,
            'thumbnail': 'https://cdnv.detik.com/videoservice/AdminTV/2022/09/14/f15cae71d7b640c58e75b254ecbb1ce1-20220914071613-0s.jpg?w=400&q=80',
            'display_id': 'pakar-bicara-soal-tim-khusus-jokowi-dan-mereka-yang-pro-ke-bjorka',
            'upload_date': '20220914',
            'release_date': '20220914',
            'description': 'md5:5eb03225f7ee40207dd3a1e18a73f1ff',
            'timestamp': 1663139688,
            'duration': 213.0,
            'tags': ['hacker bjorka', 'bjorka', 'hacker bjorka bocorkan data rahasia presiden jokowi', 'jokowi'],
        }
    }]

    def _extract_from_webpage(self, url, webpage):
        display_id = url_basename(url)
        player_type, video_data = self._search_regex(
            r'<script\s*[^>]+src="https?://(aws)?cdn\.detik\.net\.id/(?P<type>flowplayer|detikVideo)[^>]+>\s*(?P<video_data>{[^}]+})',
            webpage, 'playerjs', group=('type', 'video_data'), default=(None, ''))

        json_ld_data = self._search_json_ld(webpage, display_id, default={})
        extra_info_dict = {}

        if not player_type:
            return

        elif player_type == 'flowplayer':
            video_json_data = self._parse_json(video_data.replace('\'', '"'), display_id)
            video_url = video_json_data['videoUrl']

            extra_info_dict = {
                'id': self._search_regex(r'identifier\s*:\s*\'([^\']+)', webpage, 'identifier'),
                'thumbnail': video_json_data.get('imageUrl'),
            }

        elif player_type == 'detikVideo':
            video_url = self._search_regex(
                r'videoUrl\s*:\s*[\'"]?([^"\']+)', video_data, 'videoUrl')
            extra_info_dict = {
                'id': self._html_search_meta(['video_id', 'dtk:video_id'], webpage),
                'thumbnail': self._search_regex(r'imageUrl\s*:\s*[\'"]?([^"\']+)', video_data, 'videoUrl'),
                'duration': int_or_none(self._html_search_meta('duration', webpage, fatal=False, default=None)),
                'release_timestamp': int_or_none(self._html_search_meta('dtk:publishdateunix', webpage, fatal=False, default=None), 1000),
                'timestamp': int_or_none(self._html_search_meta('dtk:createdateunix', webpage, fatal=False, default=None), 1000),
                'uploader': self._search_regex(
                    r'([^-]+)', self._html_search_meta('dtk:author', webpage, default='').strip(), 'uploader',
                    default=None)
            }

        formats, subtitles = self._extract_m3u8_formats_and_subtitles(video_url, display_id)
        self._sort_formats(formats)

        yield merge_dicts(json_ld_data, extra_info_dict, {