-from __future__ import unicode_literals
-
import random
import re
+import urllib.parse
from .common import InfoExtractor
-from ..compat import (
- compat_str,
- compat_urlparse,
-)
from ..utils import (
- encode_data_uri,
ExtractorError,
- int_or_none,
+ encode_data_uri,
float_or_none,
+ int_or_none,
+ join_nonempty,
mimetype2ext,
str_or_none,
)
class UstreamIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?(?:ustream\.tv|video\.ibm\.com)/(?P<type>recorded|embed|embed/recorded)/(?P<id>\d+)'
IE_NAME = 'ustream'
+ _EMBED_REGEX = [r'<iframe[^>]+?src=(["\'])(?P<url>https?://(?:www\.)?(?:ustream\.tv|video\.ibm\.com)/embed/.+?)\1']
_TESTS = [{
'url': 'http://www.ustream.tv/recorded/20274954',
'md5': '088f151799e8f572f84eb62f17d73e5c',
'only_matching': True,
}]
- @staticmethod
- def _extract_url(webpage):
- mobj = re.search(
- r'<iframe[^>]+?src=(["\'])(?P<url>https?://(?:www\.)?(?:ustream\.tv|video\.ibm\.com)/embed/.+?)\1', webpage)
- if mobj is not None:
- return mobj.group('url')
-
def _get_stream_info(self, url, video_id, app_id_ver, extra_note=None):
def num_to_hex(n):
return hex(n)[2:]
extra_note = ''
conn_info = self._download_json(
- 'http://r%d-1-%s-recorded-lp-live.ums.ustream.tv/1/ustream' % (rnd(1e8), video_id),
+ f'http://r{rnd(1e8)}-1-{video_id}-recorded-lp-live.ums.ustream.tv/1/ustream',
video_id, note='Downloading connection info' + extra_note,
query={
'type': 'viewer',
'appId': app_id_ver[0],
'appVersion': app_id_ver[1],
- 'rsid': '%s:%s' % (num_to_hex(rnd(1e8)), num_to_hex(rnd(1e8))),
- 'rpin': '_rpin.%d' % rnd(1e15),
+ 'rsid': f'{num_to_hex(rnd(1e8))}:{num_to_hex(rnd(1e8))}',
+ 'rpin': f'_rpin.{rnd(1e15)}',
'referrer': url,
'media': video_id,
'application': 'recorded',
connection_id = conn_info[0]['args'][0]['connectionId']
return self._download_json(
- 'http://%s/1/ustream?connectionId=%s' % (host, connection_id),
+ f'http://{host}/1/ustream?connectionId={connection_id}',
video_id, note='Downloading stream info' + extra_note)
def _get_streams(self, url, video_id, app_id_ver):
for trial_count in range(3):
stream_info = self._get_stream_info(
url, video_id, app_id_ver,
- extra_note=' (try %d)' % (trial_count + 1) if trial_count > 0 else '')
+ extra_note=f' (try {trial_count + 1})' if trial_count > 0 else '')
if 'stream' in stream_info[0]['args'][0]:
return stream_info[0]['args'][0]['stream']
return []
def _parse_segmented_mp4(self, dash_stream_info):
def resolve_dash_template(template, idx, chunk_hash):
- return template.replace('%', compat_str(idx), 1).replace('%', chunk_hash)
+ return template.replace('%', str(idx), 1).replace('%', chunk_hash)
formats = []
for stream in dash_stream_info['streams']:
provider = dash_stream_info['providers'][0]
fragments = [{
'url': resolve_dash_template(
- provider['url'] + stream['initUrl'], 0, dash_stream_info['hashes']['0'])
+ provider['url'] + stream['initUrl'], 0, dash_stream_info['hashes']['0']),
}]
for idx in range(dash_stream_info['videoLength'] // dash_stream_info['chunkTime']):
fragments.append({
'url': resolve_dash_template(
provider['url'] + stream['segmentUrl'], idx,
- dash_stream_info['hashes'][compat_str(idx // 10 * 10)])
+ dash_stream_info['hashes'][str(idx // 10 * 10)]),
})
content_type = stream['contentType']
kind = content_type.split('/')[0]
f = {
- 'format_id': '-'.join(filter(None, [
- 'dash', kind, str_or_none(stream.get('bitrate'))])),
+ 'format_id': join_nonempty(
+ 'dash', kind, str_or_none(stream.get('bitrate'))),
'protocol': 'http_dash_segments',
# TODO: generate a MPD doc for external players?
'url': encode_data_uri(b'<MPD/>', 'text/xml'),
r'ustream\.vars\.offAirContentVideoIds=([^;]+);', webpage,
'content video IDs'), video_id)
return self.playlist_result(
- map(lambda u: self.url_result('http://www.ustream.tv/recorded/' + u, 'Ustream'), content_video_ids),
+ (self.url_result('http://www.ustream.tv/recorded/' + u, 'Ustream') for u in content_video_ids),
video_id)
params = self._download_json(
- 'https://api.ustream.tv/videos/%s.json' % video_id, video_id)
+ f'https://api.ustream.tv/videos/{video_id}.json', video_id)
error = params.get('error')
if error:
raise ExtractorError(
- '%s returned error: %s' % (self.IE_NAME, error), expected=True)
+ f'{self.IE_NAME} returned error: {error}', expected=True)
video = params['video']
formats.extend(self._parse_segmented_mp4(dash_streams))
'''
- self._sort_formats(formats)
-
description = video.get('description')
timestamp = int_or_none(video.get('created_at'))
duration = float_or_none(video.get('length'))
channel_id = self._html_search_meta('ustream:channel_id', webpage)
BASE = 'http://www.ustream.tv'
- next_url = '/ajax/socialstream/videos/%s/1.json' % channel_id
+ next_url = f'/ajax/socialstream/videos/{channel_id}/1.json'
video_ids = []
while next_url:
reply = self._download_json(
- compat_urlparse.urljoin(BASE, next_url), display_id,
- note='Downloading video information (next: %d)' % (len(video_ids) + 1))
+ urllib.parse.urljoin(BASE, next_url), display_id,
+ note=f'Downloading video information (next: {len(video_ids) + 1})')
video_ids.extend(re.findall(r'data-content-id="(\d.*)"', reply['data']))
next_url = reply['nextUrl']