]>
jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/trovo.py
2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
15 class TrovoBaseIE(InfoExtractor
):
16 _VALID_URL_BASE
= r
'https?://(?:www\.)?trovo\.live/'
18 def _extract_streamer_info(self
, data
):
19 streamer_info
= data
.get('streamerInfo') or {}
20 username
= streamer_info
.get('userName')
22 'uploader': streamer_info
.get('nickName'),
23 'uploader_id': str_or_none(streamer_info
.get('uid')),
24 'uploader_url': 'https://trovo.live/' + username
if username
else None,
28 class TrovoIE(TrovoBaseIE
):
29 _VALID_URL
= TrovoBaseIE
._VALID
_URL
_BASE
+ r
'(?!(?:clip|video)/)(?P<id>[^/?&#]+)'
31 def _real_extract(self
, url
):
32 username
= self
._match
_id
(url
)
33 live_info
= self
._download
_json
(
34 'https://gql.trovo.live/', username
, query
={
36 getLiveInfo(params: {userName: "%s"}) {
54 })['data']['getLiveInfo']
55 if live_info
.get('isLive') == 0:
56 raise ExtractorError('%s is offline' % username
, expected
=True)
57 program_info
= live_info
['programInfo']
58 program_id
= program_info
['id']
59 title
= self
._live
_title
(program_info
['title'])
62 for stream_info
in (program_info
.get('streamInfo') or []):
63 play_url
= stream_info
.get('playUrl')
66 format_id
= stream_info
.get('desc')
68 'format_id': format_id
,
69 'height': int_or_none(format_id
[:-1]) if format_id
else None,
72 self
._sort
_formats
(formats
)
78 'thumbnail': program_info
.get('coverUrl'),
81 info
.update(self
._extract
_streamer
_info
(live_info
))
85 class TrovoVodIE(TrovoBaseIE
):
86 _VALID_URL
= TrovoBaseIE
._VALID
_URL
_BASE
+ r
'(?:clip|video)/(?P<id>[^/?&#]+)'
88 'url': 'https://trovo.live/video/ltv-100095501_100095501_1609596043',
90 'id': 'ltv-100095501_100095501_1609596043',
92 'title': 'Spontaner 12 Stunden Stream! - Ok Boomer!',
94 'timestamp': 1609640305,
95 'upload_date': '20210103',
96 'uploader_id': '100095501',
100 'comment_count': int,
101 'comments': 'mincount:8',
102 'categories': ['Grand Theft Auto V'],
105 'url': 'https://trovo.live/clip/lc-5285890810184026005',
106 'only_matching': True,
109 def _real_extract(self
, url
):
110 vid
= self
._match
_id
(url
)
111 resp
= self
._download
_json
(
112 'https://gql.trovo.live/', vid
, data
=json
.dumps([{
114 batchGetVodDetailInfo(params: {vids: ["%s"]}) {
120 getCommentList(params: {appInfo: {postID: "%s"}, pageSize: 1000000000, preview: {}}) {
133 }]).encode(), headers
={
134 'Content-Type': 'application/json',
136 vod_detail_info
= resp
[0]['data']['batchGetVodDetailInfo']['VodDetailInfos'][vid
]
137 vod_info
= vod_detail_info
['vodInfo']
138 title
= vod_info
['title']
140 language
= vod_info
.get('languageName')
142 for play_info
in (vod_info
.get('playInfos') or []):
143 play_url
= play_info
.get('playUrl')
146 format_id
= play_info
.get('desc')
149 'filesize': int_or_none(play_info
.get('fileSize')),
150 'format_id': format_id
,
151 'height': int_or_none(format_id
[:-1]) if format_id
else None,
152 'language': language
,
153 'protocol': 'm3u8_native',
154 'tbr': int_or_none(play_info
.get('bitrate')),
157 self
._sort
_formats
(formats
)
159 category
= vod_info
.get('categoryName')
160 get_count
= lambda x
: int_or_none(vod_info
.get(x
+ 'Num'))
162 comment_list
= try_get(resp
, lambda x
: x
[1]['data']['getCommentList']['commentList'], list) or []
164 for comment
in comment_list
:
165 content
= comment
.get('content')
168 author
= comment
.get('author') or {}
169 parent
= comment
.get('parentID')
171 'author': author
.get('nickName'),
172 'author_id': str_or_none(author
.get('uid')),
173 'id': str_or_none(comment
.get('commentID')),
175 'timestamp': int_or_none(comment
.get('createdAt')),
176 'parent': 'root' if parent
== 0 else str_or_none(parent
),
183 'thumbnail': vod_info
.get('coverUrl'),
184 'timestamp': int_or_none(vod_info
.get('publishTs')),
185 'duration': int_or_none(vod_info
.get('duration')),
186 'view_count': get_count('watch'),
187 'like_count': get_count('like'),
188 'comment_count': get_count('comment'),
189 'comments': comments
,
190 'categories': [category
] if category
else None,
192 info
.update(self
._extract
_streamer
_info
(vod_detail_info
))