mirror of
https://github.com/yt-dlp/yt-dlp
synced 2025-01-15 03:41:33 +01:00
[ie/niconico] Support "--load-info-json" by saving WebSocket url
aka "--load-info". Don't save a Response object to info JSON. Just create a new WebSocket connection during the download. Due to Niconico's logic, the manifest m3u8 url will be unusable soon if there is no active WebSocket connection, so the reconnection will give us a valid manifest m3u8, unless the WebSocket url has already expired.
This commit is contained in:
parent
972a2d51ad
commit
d9a6507fe6
2 changed files with 34 additions and 34 deletions
|
@ -79,33 +79,33 @@ class NiconicoLiveFD(FragmentFD):
|
|||
|
||||
video_id = info_dict['id']
|
||||
live_latency = info_dict['downloader_options']['live_latency']
|
||||
self.ws = info_dict['downloader_options']['ws']
|
||||
ws_url = info_dict['downloader_options']['ws_url']
|
||||
|
||||
self.ws = None
|
||||
|
||||
self.m3u8_lock = threading.Event()
|
||||
self.m3u8_url = info_dict['manifest_url']
|
||||
self.m3u8_lock.set()
|
||||
self.m3u8_url = None
|
||||
|
||||
def communicate_ws(reconnect):
|
||||
if reconnect:
|
||||
self.ws = self.ydl.urlopen(Request(self.ws.url, headers=info_dict.get('http_headers')))
|
||||
if self.ydl.params.get('verbose', False):
|
||||
self.to_screen('[debug] Sending startWatching request')
|
||||
self.ws.send(json.dumps({
|
||||
'type': 'startWatching',
|
||||
'data': {
|
||||
'stream': {
|
||||
'quality': 'abr',
|
||||
'protocol': 'hls',
|
||||
'latency': live_latency,
|
||||
'chasePlay': False
|
||||
},
|
||||
'room': {
|
||||
'protocol': 'webSocket',
|
||||
'commentable': True
|
||||
},
|
||||
'reconnect': True,
|
||||
}
|
||||
}))
|
||||
def communicate_ws():
|
||||
self.ws = self.ydl.urlopen(Request(ws_url, headers=info_dict.get('http_headers')))
|
||||
if self.ydl.params.get('verbose', False):
|
||||
self.to_screen('[debug] Sending startWatching request')
|
||||
self.ws.send(json.dumps({
|
||||
'type': 'startWatching',
|
||||
'data': {
|
||||
'stream': {
|
||||
'quality': 'abr',
|
||||
'protocol': 'hls',
|
||||
'latency': live_latency,
|
||||
'chasePlay': False
|
||||
},
|
||||
'room': {
|
||||
'protocol': 'webSocket',
|
||||
'commentable': True
|
||||
},
|
||||
'reconnect': True,
|
||||
}
|
||||
}))
|
||||
with self.ws:
|
||||
while True:
|
||||
recv = self.ws.recv()
|
||||
|
@ -136,10 +136,9 @@ class NiconicoLiveFD(FragmentFD):
|
|||
stopped = threading.Event()
|
||||
|
||||
def ws_main():
|
||||
reconnect = False
|
||||
while not stopped.is_set():
|
||||
try:
|
||||
communicate_ws(reconnect)
|
||||
communicate_ws()
|
||||
break # Disconnected
|
||||
except BaseException as e: # Including TransportError
|
||||
if stopped.is_set():
|
||||
|
@ -150,8 +149,6 @@ class NiconicoLiveFD(FragmentFD):
|
|||
self.to_screen('[%s] %s: Connection error occured, reconnecting after %d seconds: %s' % ('niconico:live', video_id, self._WEBSOCKET_RECONNECT_DELAY, str_or_none(e)))
|
||||
time.sleep(self._WEBSOCKET_RECONNECT_DELAY)
|
||||
|
||||
reconnect = True
|
||||
|
||||
self.m3u8_lock.set() # Release possible locks
|
||||
|
||||
thread = threading.Thread(target=ws_main, daemon=True)
|
||||
|
|
|
@ -956,7 +956,10 @@ class NiconicoLiveIE(InfoExtractor):
|
|||
|
||||
_KNOWN_LATENCY = ('high', 'low')
|
||||
|
||||
def _yield_formats(self, ws, video_id, latency, is_live):
|
||||
def _yield_formats(self, ws_url, headers, latency, video_id, is_live):
|
||||
ws = self._request_webpage(
|
||||
Request(ws_url, headers=headers), video_id, note='Connecting to WebSocket server')
|
||||
|
||||
self.write_debug('[debug] Sending HLS server request')
|
||||
ws.send(json.dumps({
|
||||
'type': 'startWatching',
|
||||
|
@ -998,6 +1001,8 @@ class NiconicoLiveIE(InfoExtractor):
|
|||
recv = recv[:100] + '...'
|
||||
self.write_debug('Server said: %s' % recv)
|
||||
|
||||
ws.close()
|
||||
|
||||
formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4', live=is_live)
|
||||
for fmt, q in zip(formats, reversed(qualities[1:])):
|
||||
fmt.update({
|
||||
|
@ -1014,14 +1019,11 @@ class NiconicoLiveIE(InfoExtractor):
|
|||
embedded_data = self._parse_json(unescapeHTML(self._search_regex(
|
||||
r'<script\s+id="embedded-data"\s*data-props="(.+?)"', webpage, 'embedded data')), video_id)
|
||||
|
||||
ws = None
|
||||
ws_url = traverse_obj(embedded_data, ('site', 'relive', 'webSocketUrl'))
|
||||
if ws_url:
|
||||
ws_url = update_url_query(ws_url, {
|
||||
'frontend_id': traverse_obj(embedded_data, ('site', 'frontendId')) or '9',
|
||||
})
|
||||
ws = self._request_webpage(
|
||||
Request(ws_url, headers=headers), video_id, note='Connecting to WebSocket server')
|
||||
else:
|
||||
self.raise_no_formats('The live hasn\'t started yet or already ended.', expected=True)
|
||||
|
||||
|
@ -1074,10 +1076,11 @@ class NiconicoLiveIE(InfoExtractor):
|
|||
'timestamp': int_or_none(traverse_obj(embedded_data, ('program', 'openTime'))),
|
||||
'live_status': live_status,
|
||||
'thumbnails': thumbnails,
|
||||
'formats': [*self._yield_formats(ws, video_id, latency, live_status == 'is_live')] if ws else None,
|
||||
'formats': [*self._yield_formats(
|
||||
ws_url, headers, latency, video_id, live_status == 'is_live')] if ws_url else None,
|
||||
'http_headers': headers,
|
||||
'downloader_options': {
|
||||
'live_latency': latency,
|
||||
'ws': ws,
|
||||
'ws_url': ws_url,
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue