From 7a7b85c9014d96421e18aa7ea5f4c1bee5ceece0 Mon Sep 17 00:00:00 2001 From: doe1080 <98906116+doe1080@users.noreply.github.com> Date: Sun, 11 May 2025 07:46:28 +0900 Subject: [PATCH] [ie/niconico:live] Fix extractor (#13045) Authored by: doe1080 --- yt_dlp/extractor/niconico.py | 44 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/yt_dlp/extractor/niconico.py b/yt_dlp/extractor/niconico.py index 52ba6c417c..fc050c383b 100644 --- a/yt_dlp/extractor/niconico.py +++ b/yt_dlp/extractor/niconico.py @@ -16,6 +16,7 @@ determine_ext, float_or_none, int_or_none, + parse_bitrate, parse_duration, parse_iso8601, parse_qs, @@ -23,7 +24,6 @@ qualities, remove_start, str_or_none, - try_get, unescapeHTML, unified_timestamp, update_url_query, @@ -785,8 +785,6 @@ class NiconicoLiveIE(NiconicoBaseIE): 'only_matching': True, }] - _KNOWN_LATENCY = ('high', 'low') - def _real_extract(self, url): video_id = self._match_id(url) webpage, urlh = self._download_webpage_handle(f'https://live.nicovideo.jp/watch/{video_id}', video_id) @@ -802,22 +800,19 @@ def _real_extract(self, url): }) hostname = remove_start(urllib.parse.urlparse(urlh.url).hostname, 'sp.') - latency = try_get(self._configuration_arg('latency'), lambda x: x[0]) - if latency not in self._KNOWN_LATENCY: - latency = 'high' ws = self._request_webpage( Request(ws_url, headers={'Origin': f'https://{hostname}'}), video_id=video_id, note='Connecting to WebSocket server') - self.write_debug('[debug] Sending HLS server request') + self.write_debug('Sending HLS server request') ws.send(json.dumps({ 'type': 'startWatching', 'data': { 'stream': { 'quality': 'abr', - 'protocol': 'hls+fmp4', - 'latency': latency, + 'protocol': 'hls', + 'latency': 'high', 'accessRightMethod': 'single_cookie', 'chasePlay': False, }, @@ -881,18 +876,29 @@ def _real_extract(self, url): for cookie in cookies: self._set_cookie( cookie['domain'], cookie['name'], cookie['value'], - expire_time=unified_timestamp(cookie['expires']), path=cookie['path'], secure=cookie['secure']) + expire_time=unified_timestamp(cookie.get('expires')), path=cookie['path'], secure=cookie['secure']) + + fmt_common = { + 'live_latency': 'high', + 'origin': hostname, + 'protocol': 'niconico_live', + 'video_id': video_id, + 'ws': ws, + } + q_iter = (q for q in qualities[1:] if not q.startswith('audio_')) # ignore initial 'abr' + a_map = {96: 'audio_low', 192: 'audio_high'} formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4', live=True) - for fmt, q in zip(formats, reversed(qualities[1:])): - fmt.update({ - 'format_id': q, - 'protocol': 'niconico_live', - 'ws': ws, - 'video_id': video_id, - 'live_latency': latency, - 'origin': hostname, - }) + for fmt in formats: + if fmt.get('acodec') == 'none': + fmt['format_id'] = next(q_iter, fmt['format_id']) + elif fmt.get('vcodec') == 'none': + abr = parse_bitrate(fmt['url'].lower()) + fmt.update({ + 'abr': abr, + 'format_id': a_map.get(abr, fmt['format_id']), + }) + fmt.update(fmt_common) return { 'id': video_id,