1 from __future__
import unicode_literals
3 from .common
import InfoExtractor
12 class MirrativBaseIE(InfoExtractor
):
13 def assert_error(self
, response
):
14 error_message
= traverse_obj(response
, ('status', 'error'))
16 raise ExtractorError('Mirrativ says: %s' % error_message
, expected
=True)
19 class MirrativIE(MirrativBaseIE
):
21 _VALID_URL
= r
'https?://(?:www\.)?mirrativ\.com/live/(?P<id>[^/?#&]+)'
22 LIVE_API_URL
= 'https://www.mirrativ.com/api/live/live?live_id=%s'
25 'url': 'https://mirrativ.com/live/POxyuG1KmW2982lqlDTuPw',
26 'only_matching': True,
29 def _real_extract(self
, url
):
30 video_id
= self
._match
_id
(url
)
31 webpage
= self
._download
_webpage
('https://www.mirrativ.com/live/%s' % video_id
, video_id
)
32 live_response
= self
._download
_json
(self
.LIVE_API_URL
% video_id
, video_id
)
33 self
.assert_error(live_response
)
35 hls_url
= dict_get(live_response
, ('archive_url_hls', 'streaming_url_hls'))
36 is_live
= bool(live_response
.get('is_live'))
37 was_live
= bool(live_response
.get('is_archive'))
39 raise ExtractorError('Neither archive nor live is available.', expected
=True)
41 formats
= self
._extract
_m
3u8_formats
(
43 ext
='mp4', entry_protocol
='m3u8_native',
44 m3u8_id
='hls', live
=is_live
)
45 rtmp_url
= live_response
.get('streaming_url_edge')
47 keys_to_copy
= ('width', 'height', 'vcodec', 'acodec', 'tbr')
54 fmt
.update({k: traverse_obj(formats, (0, k)) for k in keys_to_copy}
)
56 self
._sort
_formats
(formats
)
58 title
= self
._og
_search
_title
(webpage
, default
=None) or self
._search
_regex
(
59 r
'<title>\s*(.+?) - Mirrativ\s*</title>', webpage
) or live_response
.get('title')
60 description
= live_response
.get('description')
61 thumbnail
= live_response
.get('image_url')
63 duration
= try_get(live_response
, lambda x
: x
['ended_at'] - x
['started_at'])
64 view_count
= live_response
.get('total_viewer_num')
65 release_timestamp
= live_response
.get('started_at')
66 timestamp
= live_response
.get('created_at')
68 owner
= live_response
.get('owner', {})
69 uploader
= owner
.get('name')
70 uploader_id
= owner
.get('user_id')
76 'description': description
,
78 'thumbnail': thumbnail
,
80 'uploader_id': uploader_id
,
82 'view_count': view_count
,
83 'release_timestamp': release_timestamp
,
84 'timestamp': timestamp
,
89 class MirrativUserIE(MirrativBaseIE
):
90 IE_NAME
= 'mirrativ:user'
91 _VALID_URL
= r
'https?://(?:www\.)?mirrativ\.com/user/(?P<id>\d+)'
92 LIVE_HISTORY_API_URL
= 'https://www.mirrativ.com/api/live/live_history?user_id=%s&page=%d'
93 USER_INFO_API_URL
= 'https://www.mirrativ.com/api/user/profile?user_id=%s'
96 # Live archive is available up to 3 days
97 # see: https://helpfeel.com/mirrativ/%E9%8C%B2%E7%94%BB-5e26d3ad7b59ef0017fb49ac (Japanese)
98 'url': 'https://www.mirrativ.com/user/110943130',
99 'note': 'multiple archives available',
100 'only_matching': True,
103 def _entries(self
, user_id
):
105 while page
is not None:
106 api_response
= self
._download
_json
(
107 self
.LIVE_HISTORY_API_URL
% (user_id
, page
), user_id
,
108 note
='Downloading page %d' % page
)
109 self
.assert_error(api_response
)
110 lives
= api_response
.get('lives')
114 if not live
.get('is_archive') and not live
.get('is_live'):
115 # neither archive nor live is available, so skip it
116 # or the service will ban your IP address for a while
118 live_id
= live
.get('live_id')
119 url
= 'https://www.mirrativ.com/live/%s' % live_id
120 yield self
.url_result(url
, video_id
=live_id
, video_title
=live
.get('title'))
121 page
= api_response
.get('next_page')
123 def _real_extract(self
, url
):
124 user_id
= self
._match
_id
(url
)
125 user_info
= self
._download
_json
(
126 self
.USER_INFO_API_URL
% user_id
, user_id
,
127 note
='Downloading user info', fatal
=False)
128 self
.assert_error(user_info
)
130 uploader
= user_info
.get('name')
131 description
= user_info
.get('description')
133 entries
= self
._entries
(user_id
)
134 return self
.playlist_result(entries
, user_id
, uploader
, description
)