2 from __future__
import unicode_literals
6 from .common
import InfoExtractor
15 from ..compat
import compat_urllib_parse_urlencode
18 class VLiveIE(InfoExtractor
):
20 _VALID_URL
= r
'https?://(?:(?:www|m)\.)?vlive\.tv/video/(?P<id>[0-9]+)'
22 'url': 'http://www.vlive.tv/video/1326',
23 'md5': 'cc7314812855ce56de70a06a27314983',
27 'title': "[V LIVE] Girl's Day's Broadcast",
28 'creator': "Girl's Day",
32 'url': 'http://www.vlive.tv/video/16937',
36 'title': '[V LIVE] 첸백시 걍방',
39 'subtitles': 'mincount:12',
42 'skip_download': True,
46 def _real_extract(self
, url
):
47 video_id
= self
._match
_id
(url
)
49 webpage
= self
._download
_webpage
(
50 'http://www.vlive.tv/video/%s' % video_id
, video_id
)
52 VIDEO_PARAMS_RE
= r
'\bvlive\.video\.init\(([^)]+)'
53 VIDEO_PARAMS_FIELD
= 'video params'
55 params
= self
._parse
_json
(self
._search
_regex
(
56 VIDEO_PARAMS_RE
, webpage
, VIDEO_PARAMS_FIELD
, default
=''), video_id
,
57 transform_source
=lambda s
: '[' + s
+ ']', fatal
=False)
59 if not params
or len(params
) < 7:
60 params
= self
._search
_regex
(
61 VIDEO_PARAMS_RE
, webpage
, VIDEO_PARAMS_FIELD
)
62 params
= [p
.strip(r
'"') for p
in re
.split(r
'\s*,\s*', params
)]
64 status
, long_video_id
, key
= params
[2], params
[5], params
[6]
65 status
= remove_start(status
, 'PRODUCT_')
67 if status
== 'LIVE_ON_AIR' or status
== 'BIG_EVENT_ON_AIR':
68 return self
._live
(video_id
, webpage
)
69 elif status
== 'VOD_ON_AIR' or status
== 'BIG_EVENT_INTRO':
70 if long_video_id
and key
:
71 return self
._replay
(video_id
, webpage
, long_video_id
, key
)
73 status
= 'COMING_SOON'
75 if status
== 'LIVE_END':
76 raise ExtractorError('Uploading for replay. Please wait...',
78 elif status
== 'COMING_SOON':
79 raise ExtractorError('Coming soon!', expected
=True)
80 elif status
== 'CANCELED':
81 raise ExtractorError('We are sorry, '
82 'but the live broadcast has been canceled.',
85 raise ExtractorError('Unknown status %s' % status
)
87 def _get_common_fields(self
, webpage
):
88 title
= self
._og
_search
_title
(webpage
)
89 creator
= self
._html
_search
_regex
(
90 r
'<div[^>]+class="info_area"[^>]*>\s*<a\s+[^>]*>([^<]+)',
91 webpage
, 'creator', fatal
=False)
92 thumbnail
= self
._og
_search
_thumbnail
(webpage
)
96 'thumbnail': thumbnail
,
99 def _live(self
, video_id
, webpage
):
100 init_page
= self
._download
_webpage
(
101 'http://www.vlive.tv/video/init/view',
102 video_id
, note
='Downloading live webpage',
103 data
=urlencode_postdata({'videoSeq': video_id}
),
105 'Referer': 'http://www.vlive.tv/video/%s' % video_id
,
106 'Content-Type': 'application/x-www-form-urlencoded'
109 live_params
= self
._search
_regex
(
110 r
'"liveStreamInfo"\s*:\s*(".*"),',
111 init_page
, 'live stream info')
112 live_params
= self
._parse
_json
(live_params
, video_id
)
113 live_params
= self
._parse
_json
(live_params
, video_id
)
116 for vid
in live_params
.get('resolutions', []):
117 formats
.extend(self
._extract
_m
3u8_formats
(
118 vid
['cdnUrl'], video_id
, 'mp4',
119 m3u8_id
=vid
.get('name'),
120 fatal
=False, live
=True))
121 self
._sort
_formats
(formats
)
123 info
= self
._get
_common
_fields
(webpage
)
125 'title': self
._live
_title
(info
['title']),
132 def _replay(self
, video_id
, webpage
, long_video_id
, key
):
133 playinfo
= self
._download
_json
(
134 'http://global.apis.naver.com/rmcnmv/rmcnmv/vod_play_videoInfo.json?%s'
135 % compat_urllib_parse_urlencode({
136 'videoId': long_video_id
,
139 'doct': 'json', # document type (xml or json)
140 'cpt': 'vtt', # captions type (vtt or ttml)
144 'url': vid
['source'],
145 'format_id': vid
.get('encodingOption', {}).get('name'),
146 'abr': float_or_none(vid
.get('bitrate', {}).get('audio')),
147 'vbr': float_or_none(vid
.get('bitrate', {}).get('video')),
148 'width': int_or_none(vid
.get('encodingOption', {}).get('width')),
149 'height': int_or_none(vid
.get('encodingOption', {}).get('height')),
150 'filesize': int_or_none(vid
.get('size')),
151 } for vid
in playinfo
.get('videos', {}).get('list', []) if vid
.get('source')]
152 self
._sort
_formats
(formats
)
154 view_count
= int_or_none(playinfo
.get('meta', {}).get('count'))
157 for caption
in playinfo
.get('captions', {}).get('list', []):
158 lang
= dict_get(caption
, ('locale', 'language', 'country', 'label'))
159 if lang
and caption
.get('source'):
162 'url': caption
['source']}]
164 info
= self
._get
_common
_fields
(webpage
)
168 'view_count': view_count
,
169 'subtitles': subtitles
,