]>
jfr.im git - yt-dlp.git/blob - yt_dlp/downloader/niconico.py
5 from . import get_suitable_downloader
6 from .common
import FileDownloader
7 from .external
import FFmpegFD
17 class NiconicoDmcFD(FileDownloader
):
18 """ Downloading niconico douga from DMC with heartbeat """
20 def real_download(self
, filename
, info_dict
):
21 from ..extractor
.niconico
import NiconicoIE
23 self
.to_screen('[%s] Downloading from DMC' % self
.FD_NAME
)
24 ie
= NiconicoIE(self
.ydl
)
25 info_dict
, heartbeat_info_dict
= ie
._get
_heartbeat
_info
(info_dict
)
27 fd
= get_suitable_downloader(info_dict
, params
=self
.params
)(self
.ydl
, self
.params
)
29 success
= download_complete
= False
31 heartbeat_lock
= threading
.Lock()
32 heartbeat_url
= heartbeat_info_dict
['url']
33 heartbeat_data
= heartbeat_info_dict
['data'].encode()
34 heartbeat_interval
= heartbeat_info_dict
.get('interval', 30)
36 request
= sanitized_Request(heartbeat_url
, heartbeat_data
)
40 self
.ydl
.urlopen(request
).read()
42 self
.to_screen('[%s] Heartbeat failed' % self
.FD_NAME
)
45 if not download_complete
:
46 timer
[0] = threading
.Timer(heartbeat_interval
, heartbeat
)
49 heartbeat_info_dict
['ping']()
50 self
.to_screen('[%s] Heartbeat with %d second interval ...' % (self
.FD_NAME
, heartbeat_interval
))
53 if type(fd
).__name
__ == 'HlsFD':
54 info_dict
.update(ie
._extract
_m
3u8_formats
(info_dict
['url'], info_dict
['id'])[0])
55 success
= fd
.real_download(filename
, info_dict
)
60 download_complete
= True
64 class NiconicoLiveFD(FileDownloader
):
65 """ Downloads niconico live without being stopped """
67 def real_download(self
, filename
, info_dict
):
68 video_id
= info_dict
['video_id']
69 ws_url
= info_dict
['url']
70 ws_extractor
= info_dict
['ws']
71 ws_origin_host
= info_dict
['origin']
72 cookies
= info_dict
.get('cookies')
73 live_quality
= info_dict
.get('live_quality', 'high')
74 live_latency
= info_dict
.get('live_latency', 'high')
75 dl
= FFmpegFD(self
.ydl
, self
.params
or {})
77 new_info_dict
= info_dict
.copy()
78 new_info_dict
.update({
82 def communicate_ws(reconnect
):
84 ws
= WebSocketsWrapper(ws_url
, {
85 'Cookies': str_or_none(cookies
) or '',
86 'Origin': f
'https://{ws_origin_host}',
88 'User-Agent': self
.params
['http_headers']['User-Agent'],
90 if self
.ydl
.params
.get('verbose', False):
91 self
.to_screen('[debug] Sending startWatching request')
93 'type': 'startWatching',
96 'quality': live_quality
,
97 'protocol': 'hls+fmp4',
98 'latency': live_latency
,
102 'protocol': 'webSocket',
115 data
= json
.loads(recv
)
116 if not data
or not isinstance(data
, dict):
118 if data
.get('type') == 'ping':
120 ws
.send(r
'{"type":"pong"}')
121 ws
.send(r
'{"type":"keepSeat"}')
122 elif data
.get('type') == 'disconnect':
123 self
.write_debug(data
)
125 elif data
.get('type') == 'error':
126 self
.write_debug(data
)
127 message
= try_get(data
, lambda x
: x
['body']['code'], str) or recv
128 return DownloadError(message
)
129 elif self
.ydl
.params
.get('verbose', False):
131 recv
= recv
[:100] + '...'
132 self
.to_screen('[debug] Server said: %s' % recv
)
138 ret
= communicate_ws(reconnect
)
141 except BaseException
as e
:
142 self
.to_screen('[%s] %s: Connection error occured, reconnecting after 10 seconds: %s' % ('niconico:live', video_id
, str_or_none(e
)))
148 thread
= threading
.Thread(target
=ws_main
, daemon
=True)
151 return dl
.download(filename
, new_info_dict
)