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

Code before:
        {
            # Original source: http://www.uscourts.gov/cameras-courts/state-washington-vs-donald-j-trump-et-al
            'url': 'https://player.piksel.com/v/v80kqp41',
            'md5': '753ddcd8cc8e4fa2dda4b7be0e77744d',
            'info_dict': {
                'id': 'v80kqp41',
                'ext': 'mp4',
                'title': 'WAW- State of Washington vs. Donald J. Trump, et al',
                'description': 'State of Washington vs. Donald J. Trump, et al, Case Number 17-CV-00141-JLR, TRO Hearing, Civil Rights Case, 02/3/2017, 1:00 PM (PST), Seattle Federal Courthouse, Seattle, WA, Judge James L. Robart presiding.',
                'timestamp': 1486171129,
                'upload_date': '20170204'
            }
        },
        {
            # https://www3.nhk.or.jp/nhkworld/en/ondemand/video/2019240/
            'url': 'http://player.piksel.com/v/refid/nhkworld/prefid/nw_vod_v_en_2019_240_20190823233000_02_1566873477',
            'only_matching': True,
        }
    ]

    def _call_api(self, app_token, resource, display_id, query, host='https://player.piksel.com', fatal=True):
        url = urljoin(host, '/ws/ws_%s/api/%s/mode/json/apiv/5' % (resource, app_token))
        response = self._download_json(url, display_id, query=query, fatal=fatal)
        response = traverse_obj(response, 'response', expected_type=dict) or {}
        failure = try_get(response, lambda x: x['failure']['reason'])
        if failure:
            if fatal:
                raise ExtractorError(failure, expected=True)
            self.report_warning(failure)
        return response

    def _real_extract(self, url):
        ref_id, display_id = self._match_valid_url(url).groups()
        webpage = self._download_webpage(url, display_id)
        app_token = self._search_regex([
            r'clientAPI\s*:\s*"([^"]+)"',
            r'data-de-api-key\s*=\s*"([^"]+)"'
        ], webpage, 'app token')
        query = {'refid': ref_id, 'prefid': display_id} if ref_id else {'v': display_id}
        program = self._call_api(
            app_token, 'program', display_id, query, url)['WsProgramResponse']['program']
        video_id = program['uuid']
        video_data = program['asset']
        title = video_data['title']
        asset_type = dict_get(video_data, ['assetType', 'asset_type'])

        formats = []

        def process_asset_file(asset_file):
            if not asset_file:
                return

Review comment (bug):
```suggestion
        url = urljoin(host, f'/ws/ws_{resource}/api/{app_token}/mode/json/apiv/5')
        response = traverse_obj(
            self._download_json(url, display_id, query=query, fatal=fatal), ('response', {dict})) or {}
        failure = traverse_obj(response, ('failure', 'reason')) if response else 'Empty response from API'
        if failure:
```

Code after:
        {
            # Original source: http://www.uscourts.gov/cameras-courts/state-washington-vs-donald-j-trump-et-al
            'url': 'https://player.piksel.com/v/v80kqp41',
            'md5': '753ddcd8cc8e4fa2dda4b7be0e77744d',
            'info_dict': {
                'id': 'v80kqp41',
                'ext': 'mp4',
                'title': 'WAW- State of Washington vs. Donald J. Trump, et al',
                'description': 'State of Washington vs. Donald J. Trump, et al, Case Number 17-CV-00141-JLR, TRO Hearing, Civil Rights Case, 02/3/2017, 1:00 PM (PST), Seattle Federal Courthouse, Seattle, WA, Judge James L. Robart presiding.',
                'timestamp': 1486171129,
                'upload_date': '20170204'
            }
        },
        {
            # https://www3.nhk.or.jp/nhkworld/en/ondemand/video/2019240/
            'url': 'http://player.piksel.com/v/refid/nhkworld/prefid/nw_vod_v_en_2019_240_20190823233000_02_1566873477',
            'only_matching': True,
        }
    ]

    def _call_api(self, app_token, resource, display_id, query, host='https://player.piksel.com', fatal=True):
        url = urljoin(host, f'/ws/ws_{resource}/api/{app_token}/mode/json/apiv/5')
        response = traverse_obj(
            self._download_json(url, display_id, query=query, fatal=fatal), ('response', {dict})) or {}
        failure = traverse_obj(response, ('failure', 'reason')) if response else 'Empty response from API'
        if failure:
            if fatal:
                raise ExtractorError(failure, expected=True)
            self.report_warning(failure)
        return response

    def _real_extract(self, url):
        ref_id, display_id = self._match_valid_url(url).groups()
        webpage = self._download_webpage(url, display_id)
        app_token = self._search_regex([
            r'clientAPI\s*:\s*"([^"]+)"',
            r'data-de-api-key\s*=\s*"([^"]+)"'
        ], webpage, 'app token')
        query = {'refid': ref_id, 'prefid': display_id} if ref_id else {'v': display_id}
        program = self._call_api(
            app_token, 'program', display_id, query, url)['WsProgramResponse']['program']
        video_id = program['uuid']
        video_data = program['asset']
        title = video_data['title']
        asset_type = dict_get(video_data, ['assetType', 'asset_type'])

        formats = []

        def process_asset_file(asset_file):
            if not asset_file:
                return