def test_http_stream(self): url = "http://test.se/stream" stream = HTTPStream(self.session, url, headers={"User-Agent": "Test"}) self.assertEqual( {"type": "http", "url": url, "method": "GET", "body": None, "headers": { "User-Agent": "Test", "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "keep-alive", }}, stream.__json__() )
def _get_http_streams(self, info): name = QUALITY_MAP.get(info["_quality"], "vod") urls = info["_stream"] if not isinstance(info["_stream"], list): urls = [urls] for url in urls: stream = HTTPStream(self.session, url) yield name, stream
def _get_clips(self): try: (self.author, self.title, self.category, streams) = self.api.clips(self.clip_name) except (PluginError, TypeError): return for quality, stream in streams: yield quality, HTTPStream(self.session, stream)
def _get_streams(self): headers = {'User-Agent': CHROME} if 'web-tv-live' in self.url: live = True else: live = False self.url = self.url.replace('episodeinner', 'episodes').replace('showID', 'show') res = self.session.http.get(self.url, headers=headers) if live: tags = list(itertags(res.text, 'script')) tag = [i for i in tags if 'm3u8' in i.text][0].text m3u8 = re.search(r'''["'](http.+?\.m3u8)['"]''', tag) if m3u8: m3u8 = m3u8.group(1) else: raise NoStreamsError('Ant1 CY Broadcast is currently disabled') else: eid = dict(parse_qsl(urlparse(self.url).query))['episodeID'] tags = [ i for i in list(itertags(res.text, 'a')) if eid in i.attributes.get('data-innerurl', '') ] tag = tags[0].attributes.get('data-video') m3u8 = re.search(r""(http.+?master\.m3u8)"", tag).group(1) stream = self.session.http.get(self._api_url.format(m3u8), headers=headers).text headers.update({"Referer": self.url}) try: parse_hls = bool(strtobool(self.get_option('parse_hls'))) except AttributeError: parse_hls = True if parse_hls: return HLSStream.parse_variant_playlist(self.session, stream, headers=headers) else: return dict( stream=HTTPStream(self.session, stream, headers=headers))
def _get_vod_stream(self): """ Find the VOD video url :return: video url """ res = self.session.http.get(self.url) video_urls = self._re_vod.findall(res.text) if len(video_urls): return dict(vod=HTTPStream(self.session, video_urls[0]))
def _get_streams(self): match = _url_re.match(self.url) subdomain = match.group("subdomain") http.verify = False http.mount('https://', HTTPAdapter(max_retries=99)) if subdomain == 'v': vid = match.group("vid") headers = { "User-Agent": useragents.ANDROID, "X-Requested-With": "XMLHttpRequest" } res = http.get(VAPI_URL.format(vid), headers=headers) room = http.json(res, schema=_vapi_schema) yield "source", HLSStream(self.session, room["video_url"]) return #Thanks to @ximellon for providing method. channel = match.group("channel") http.headers.update({'User-Agent': useragents.CHROME}) try: channel = int(channel) except ValueError: channel = http.get(self.url, schema=_room_id_schema) if channel is None: channel = http.get(self.url, schema=_room_id_alt_schema) ts = int(time.time() / 60) sign = hashlib.md5(("{0}{1}{2}".format(channel, WAPI_SECRET, ts)).encode("utf-8")).hexdigest() res = http.get(WAPI_URL.format(channel, ts, sign)) room = http.json(res, schema=_room_schema) if not room: self.logger.info("Not a valid room url.") return if room["show_status"] != SHOW_STATUS_ONLINE: self.logger.info("Stream currently unavailable.") return did = uuid.uuid4().hex.upper() sign = stupidMD5(("{0}{1}{2}{3}".format(channel, did, LAPI_SECRET, ts))) rate = [0, 2, 1] quality = ['source', 'medium', 'low'] for i in range(0, 3, 1): room = self._get_room_json(channel, rate[i], ts, did ,sign) url = "{room[rtmp_url]}/{room[rtmp_live]}".format(room=room) if 'rtmp:' in url: stream = RTMPStream(self.session, { "rtmp": url, "live": True }) yield quality[i], stream else: yield quality[i], HTTPStream(self.session, url)
def _get_clips(self): quality_options = self.api.clip_status(self.channel, self.clip_name, schema=_quality_options_schema) streams = {} for quality_option in quality_options: streams[quality_option["quality"]] = HTTPStream( self.session, quality_option["source"]) return streams
def _get_streams(self): streams = [] content_id = self._get_content_id() if content_id: log.debug(f"Found content with id: {content_id}") stream_data = self.zclient.get_cdn_list(content_id, schema=self.cdn_schema) quality_map = None for stream in stream_data: for url in stream["urls"]: if ".m3u8" in url: try: streams.extend( HLSStream.parse_variant_playlist( self.session, url).items()) except (IOError, OSError) as err: log.error(str(err)) elif ((url.endswith("mp4") or url.endswith("mov") or url.endswith("avi")) and self.session.http.head( url, raise_for_status=False).status_code == 200): if quality_map is None: # only make the request when it is necessary quality_map = self._get_quality_map(content_id) # rename the HTTP sources to match the HLS sources quality = quality_map.get(stream["quality"], stream["quality"]) streams.append((quality, HTTPStream(self.session, url))) subtitles = None if self.get_option("mux_subtitles"): subtitles = self._get_subtitles(content_id) if subtitles: substreams = {} for i, subtitle in enumerate(subtitles): substreams[subtitle["lang"]] = HTTPStream( self.session, subtitle["src"]) for q, s in streams: yield q, MuxedStream(self.session, s, subtitles=substreams) else: for s in streams: yield s
def _create_playlist_streams(self, videos): start_offset = int(videos.get("start_offset", 0)) stop_offset = int(videos.get("end_offset", 0)) streams = {} for quality, chunks in videos.get("chunks").items(): if not chunks: if videos.get("restrictions", {}).get(quality) == "chansub": log.warning("The quality '{0}' is not available since it requires a subscription.".format(quality)) continue # Rename 'live' to 'source' if quality == "live": quality = "source" chunks_filtered = list(filter(lambda c: c["url"], chunks)) if len(chunks) != len(chunks_filtered): log.warning("The video '{0}' contains invalid chunks. There will be missing data.".format(quality)) chunks = chunks_filtered chunks_duration = sum(c.get("length") for c in chunks) # If it's a full broadcast we just use all the chunks if start_offset == 0 and chunks_duration == stop_offset: # No need to use the FLV concat if it's just one chunk if len(chunks) == 1: url = chunks[0].get("url") stream = HTTPStream(self.session, url) else: chunks = [HTTPStream(self.session, c.get("url")) for c in chunks] stream = FLVPlaylist(self.session, chunks, duration=chunks_duration) else: try: stream = self._create_video_clip(chunks, start_offset, stop_offset) except StreamError as err: log.error("Error while creating video '{0}': {1}".format(quality, err)) continue streams[quality] = stream return streams
def _get_streams(self): is_live = False self.video_id = self._find_video_id(self.url) log.debug("Using video ID: {0}", self.video_id) info = self._get_stream_info(self.video_id) if info and info.get("status") == "fail": log.error("Could not get video info: {0}".format( info.get("reason"))) return elif not info: log.error("Could not get video info") return if info.get("livestream") == '1' or info.get("live_playback") == '1' \ or info.get("player_response", {}).get("videoDetails", {}).get("isLive") == True: log.debug("This video is live.") is_live = True formats = info.get("fmt_list") streams = {} protected = False for stream_info in info.get("url_encoded_fmt_stream_map", []): if stream_info.get("s"): protected = True continue stream = HTTPStream(self.session, stream_info["url"]) name = formats.get(stream_info["itag"]) or stream_info["quality"] if stream_info.get("stereo3d"): name += "_3d" streams[name] = stream if not is_live: streams, protected = self._create_adaptive_streams( info, streams, protected) hls_playlist = info.get("hlsvp") or info.get( "player_response", {}).get("streamingData", {}).get("hlsManifestUrl") if hls_playlist: try: hls_streams = HLSStream.parse_variant_playlist( self.session, hls_playlist, namekey="pixels") streams.update(hls_streams) except IOError as err: log.warning("Failed to extract HLS streams: {0}", err) if not streams and protected: raise PluginError("This plugin does not support protected videos, " "try youtube-dl instead") return streams
def _get_streams(self): match = _url_re.match(self.url) page = match.group("page") channel = match.group("channel") http.headers.update({'User-Agent': useragents.CHROME}) if page == 'user': res = http.get(self.url) userid = _userid_re.search(res.text).group(1) api = http.post(API_URL, data={"targetUserID": userid}) data = http.json(api, schema=_user_api_schema) rid = data["liveStreamID"] if rid == 0: self.logger.info("Stream currently unavailable.") return url = ROOM_URL.format(rid) res = http.get(url) elif page == 'profile': api = http.post(API_URL, data={"targetUserID": channel}) data = http.json(api, schema=_user_api_schema) rid = data["liveStreamID"] if rid == 0: self.logger.info("Stream currently unavailable.") return url = ROOM_URL.format(rid) res = http.get(url) else: res = http.get(self.url) status = _status_re.search(res.text) if not status: return if status.group(1) != 'true': self.logger.info("Stream currently unavailable.") return http_url = _rtmp_re.search(res.text).group(1) yield "live", HTTPStream(self.session, http_url) if 'pull-rtmp' in http_url: url = http_url.replace("http:", "rtmp:").replace(".flv", "") stream = RTMPStream(self.session, {"rtmp": url, "live": True}) yield "live", stream if 'wansu-global-pull-rtmp' in http_url: url = http_url.replace(".flv", "/playlist.m3u8") for stream in HLSStream.parse_variant_playlist(self.session, url).items(): yield stream else: url = http_url.replace(".flv", ".m3u8") yield "live", HLSStream(self.session, url)
def _get_streams(self): self.session.set_option("ffmpeg-start-at-zero", True) self.session.http.headers.update({"Accept-Language": "en-US"}) done = False res = self.session.http.get(self.url) log.trace("{0}".format(res.url)) for title in itertags(res.text, "title"): if title.text.startswith("Log into Facebook"): log.error( "Video is not available, You must log in to continue.") return for s in self._parse_streams(res): done = True yield s if done: return # fallback on to playlist log.debug("Falling back to playlist regex") match = self._playlist_re.search(res.text) playlist = match and match.group(1) if playlist: match = self._plurl_re.search(playlist) if match: url = match.group(1) yield "sd", HTTPStream(self.session, url) return # fallback to tahoe player url log.debug("Falling back to tahoe player") video_id = self._url_re.match(self.url).group("video_id") url = self._TAHOE_URL.format(video_id) data = { "__a": 1, "__pc": self._DEFAULT_PC, "__rev": self._DEFAULT_REV, "fb_dtsg": "", } match = self._pc_re.search(res.text) if match: data["__pc"] = match.group(1) match = self._rev_re.search(res.text) if match: data["__rev"] = match.group(1) match = self._dtsg_re.search(res.text) if match: data["fb_dtsg"] = match.group(1) res = self.session.http.post( url, headers={"Content-Type": "application/x-www-form-urlencoded"}, data=urlencode(data).encode("ascii")) for s in self._parse_streams(res): yield s
def _get_streams(self): streams = self.session.http.get(self.url, schema=self._stream_schema) for stream in streams: if stream["stream-type"] == "hls": for s in HLSStream.parse_variant_playlist( self.session, stream["url"]).items(): yield s elif stream["stream-type"] == "rtmp": yield "0_live", RTMPStream(self.session, {"rtmp": stream["url"]}) elif stream["stream-type"] == "endpoint": res = self.session.http.get(stream["url"]) files = self.session.http.json(res, schema=self._endpoint_schema) for f in files: s = HTTPStream(self.session, f["file"]) yield "vod", s elif stream["stream-type"] == "mp4": yield "vod", HTTPStream(self.session, stream["url"])
def _get_streams(self): self.session.http.headers.update({"User-Agent": useragents.FIREFOX}) info_url = None channel = self.url_re.match(self.url).group('channel') if channel: log.debug('Channel: {0}'.format(channel)) API_URL = 'https://live.russia.tv/api/now/channel/{0}' res = self.session.http.get(API_URL.format(channel)) data = self.session.http.json(res) if data: data['domain'] = '//player.vgtrk.com' data['id'] = data['live_id'] player_url = urlparse(data['player_url']) args = dict(parse_qsl(player_url.query)) if args: data['sid'] = args['sid'] else: data['sid'] = player_url.path.split('/')[-1] info_url = self.DATA_LIVE_URL.format(**data) else: iframe_url = self._get_iframe_url(self.url) if iframe_url: log.debug('Found iframe URL: {0}'.format(iframe_url)) info_url = self._get_stream_info_url(iframe_url) if info_url: log.debug('Getting info from URL: {0}'.format(info_url)) res = self.session.http.get(info_url, headers={'Referer': self.url}) data = self.session.http.json(res) if data['status'] == 200: for media in data['data']['playlist']['medialist']: if media['errors']: log.error(media['errors'].replace('\n', '').replace( '\r', '')) for media_type in media.get('sources', []): if media_type == 'm3u8': hls_url = media['sources'][media_type]['auto'] log.debug('hls_url={0}'.format(hls_url)) for s in HLSStream.parse_variant_playlist( self.session, hls_url).items(): yield s elif media_type == 'http': for pix, http_url in media['sources'][ media_type].items(): log.debug('http_url={0}'.format(http_url)) yield '{0}p'.format(pix), HTTPStream( self.session, http_url) else: log.error('An error occurred: {0}'.format( data['errors'].replace('\n', '').replace('\r', ''))) else: log.error('Unable to get stream info URL')
def _get_streams(self): match = _url_re.match(self.url) channel = match.group("channel") url = ROOM_API + channel res = http.get(url) data = http.json(res, schema=_room_schema) if not isinstance(data, dict): self.logger.error("Please Check PandaTV Room API") return videoinfo = data.get('videoinfo') if not videoinfo or not videoinfo.get('status'): self.logger.error("Please Check PandaTV Room API") return if videoinfo.get('status') != '2': self.logger.info("Channel offline now!") return streams = {} plflag = videoinfo.get('plflag') if not plflag or not '_' in plflag: self.logger.error("Please Check PandaTV Room API") return plflag = plflag.split('_')[1] room_key = videoinfo.get('room_key') # SD(Super high Definition) has higher quality than HD(High Definition) which # conflict with existing code, use ehq and hq instead. stream_addr = videoinfo.get('stream_addr') if stream_addr and stream_addr.get('SD') == '1': streams['ehq'] = HTTPStream( self.session, SD_URL_PATTERN.format(plflag, room_key)) if stream_addr and stream_addr.get('HD') == '1': streams['hq'] = HTTPStream(self.session, HD_URL_PATTERN.format(plflag, room_key)) return streams
def _create_adaptive_streams(self, info, streams, protected): adaptive_streams = {} best_audio_itag = None # Extract audio streams from the DASH format list for stream_info in info.get("adaptive_fmts", []): if stream_info.get("s"): protected = True continue stream_params = dict(parse_qsl(stream_info["url"])) if "itag" not in stream_params: continue itag = int(stream_params["itag"]) # extract any high quality streams only available in adaptive formats adaptive_streams[itag] = stream_info["url"] stream_type, stream_format = stream_info["type"] if stream_type == "audio": stream = HTTPStream(self.session, stream_info["url"]) name = "audio_{0}".format(stream_format) streams[name] = stream # find the best quality audio stream m4a, opus or vorbis if best_audio_itag is None or self.adp_audio[itag] > self.adp_audio[best_audio_itag]: best_audio_itag = itag if best_audio_itag and adaptive_streams and MuxedStream.is_usable(self.session): aurl = adaptive_streams[best_audio_itag] for itag, name in self.adp_video.items(): if itag in adaptive_streams: vurl = adaptive_streams[itag] log.debug("MuxedStream: v {video} a {audio} = {name}".format( audio=best_audio_itag, name=name, video=itag, )) streams[name] = MuxedStream(self.session, HTTPStream(self.session, vurl), HTTPStream(self.session, aurl)) return streams, protected
def _get_streams(self): res = http.get(self.url, schema=_schema) if not res: return if res["type"] == "channel" and urlparse( res["url"]).path.endswith("m3u8"): return HLSStream.parse_variant_playlist(self.session, res["url"]) elif res["type"] == "video": stream = HTTPStream(self.session, res["url"]) return dict(video=stream)
def _get_streams(self): url, params = parse_url_params(self.url) urlnoproto = self._url_re.match(url).group(1) urlnoproto = update_scheme("http://", urlnoproto) self.logger.debug("Video URL: {}", urlnoproto) aurlnoproto = params.get("audio") aurlnoproto = update_scheme("http://", aurlnoproto) quality = params.get("quality", "unknown") self.logger.debug("Video Quality: {}", quality) self.logger.debug("Audio URL: {}", aurlnoproto) streams = {} streams[quality] = MuxedStream(self.session, HTTPStream(self.session, urlnoproto), HTTPStream(self.session, aurlnoproto)) return streams
def _get_radio_streams(self, radio): res = http.get(self.RADIO_STREAM_URL.format(radio.replace('-', '_'))) streams = http.json(res, schema=self._radio_stream_schema) for stream in streams['audioUrls']: match = self._stream_size_re.match(stream['url']) if match is not None: quality = '{}k'.format(match.group('size')) else: quality = stream['mimetype'] yield quality, HTTPStream(self.session, stream['url'])
def _get_all_streams(self, video_content, encrypt): for video in video_content: url = video["url"] quality = QUALITY_MAP[video["profile_name"]] if encrypt: salt, token = self._get_salt_and_token(url) video_url = url + '?salt=%s&token=%s' % (salt, token) else: video_url = url stream = HTTPStream(self.session, video_url) yield quality, stream
def _get_streams(self): room_id = url_re.search(self.url).group("room_id") html = http.get(mobile_url.format(room_id)) stream_id = self.get_stream_id(html.text) stream_info = self.get_stream_info(html.text) streams = {} for info in stream_info: streams[info[2]] = HTTPStream( self.session, info[0] + stream_id + info[1] + ".flv") return streams
def _get_streams(self): quality = ['source', 'medium', 'low'] for i in range(0, 3, 1): if 'rtmp:' in rtmp_url: stream = RTMPStream(self.session, { "rtmp": rtmp_url, "live": True }) yield quality[i], stream else: yield quality[i], HTTPStream(self.session, rtmp_url)
def _get_streams(self): res = self.session.http.get(self.url) m = self._brightcove_video_re.search(res.text) or self._brightcove_video_alt_re.search(res.text) if m: account_id = m.group('account_id') log.debug(f'Account ID: {account_id}') video_id = m.group('video_id') log.debug(f'Video ID: {video_id}') player = BrightcovePlayer(self.session, account_id) yield from player.get_streams(video_id) return # Try to find the Dailymotion video ID m = self._embed_video_id_re.search(res.text) if m: video_id = m.group('video_id') log.debug(f'Video ID: {video_id}') yield from self.session.streams(self._dailymotion_url.format(video_id)).items() return # Try the JS for Brightcove video data m = self._main_js_url_re.search(res.text) if m: log.debug(f'JS URL: {urljoin(self.url, m.group(1))}') res = self.session.http.get(urljoin(self.url, m.group(1))) m = self._js_brightcove_video_re.search(res.text) if m: account_id = m.group('account_id') log.debug(f'Account ID: {account_id}') video_id = m.group('video_id') log.debug(f'Video ID: {video_id}') player = BrightcovePlayer(self.session, account_id) yield from player.get_streams(video_id) return # Audio Live audio_url = None for source in itertags(res.text, 'source'): url = source.attributes.get('src') if url: p_url = urlparse(url) if p_url.path.endswith(('.mp3')): audio_url = url # Audio VOD for div in itertags(res.text, 'div'): if div.attributes.get('class') == 'audio-player': audio_url = div.attributes.get('data-media-url') if audio_url: yield 'audio', HTTPStream(self.session, audio_url) return
def _get_streams(self): """ Find the streams for vk.com :return: """ self.session.http.headers.update({'User-Agent': useragents.IPHONE_6}) # If this is a 'videos' catalog URL # with an video ID in the GET request, get that instead url = self.follow_vk_redirect(self.url) m = self._url_re.match(url) if not m: log.error('URL is not compatible: {0}'.format(url)) return video_id = m.group('video_id') log.debug('video ID: {0}'.format(video_id)) params = { 'act': 'show_inline', 'al': '1', 'video': video_id, } res = self.session.http.post(self.API_URL, params=params) for _i in itertags(res.text, 'iframe'): if _i.attributes.get('src'): iframe_url = update_scheme(self.url, _i.attributes['src']) log.debug('Found iframe: {0}'.format(iframe_url)) for s in self.session.streams(iframe_url).items(): yield s for _i in itertags(res.text, 'source'): if _i.attributes.get('type') == 'application/vnd.apple.mpegurl': video_url = _i.attributes['src'] # Remove invalid URL if video_url.startswith('https://vk.com/'): continue streams = HLSStream.parse_variant_playlist( self.session, video_url) if not streams: yield 'live', HLSStream(self.session, video_url) else: for s in streams.items(): yield s elif _i.attributes.get('type') == 'video/mp4': q = 'vod' video_url = _i.attributes['src'] m = self._vod_quality_re.search(video_url) if m: q = '{0}p'.format(m.group(1)) yield q, HTTPStream(self.session, video_url)
def _get_source_streams(self): res = http.get(self.url) streams = {} sources = _source_re.findall(res.text) for source in sources: src = _source_src_re.search(source).group("src") pixels = _source_type_re.search(source).group("type") streams[pixels] = HTTPStream(self.session, src) return streams
def _create_stream(self, source): url = source["file"] if urlparse(url).path.endswith("m3u8"): streams = HLSStream.parse_variant_playlist(self.session, url) # TODO: Replace with "yield from" when dropping Python 2. for stream in streams.items(): yield stream else: name = source.get("label", "vod") yield name, HTTPStream(self.session, url)
def _get_streams(self): is_live = False self.video_id = self._find_video_id(self.url) log.debug("Using video ID: {0}", self.video_id) info = self._get_stream_info(self.video_id) if info and info.get("status") == "fail": log.error("Could not get video info: {0}".format(info.get("reason"))) return elif not info: log.error("Could not get video info") return if info.get("player_response", {}).get("videoDetails", {}).get("isLive"): log.debug("This video is live.") is_live = True streams = {} protected = False if (info.get("player_response", {}).get("streamingData", {}).get("adaptiveFormats", [{}])[0].get("cipher") or info.get("player_response", {}).get("streamingData", {}).get("adaptiveFormats", [{}])[0].get("signatureCipher") or info.get("player_response", {}).get("streamingData", {}).get("formats", [{}])[0].get("cipher")): protected = True log.debug("This video may be protected.") for stream_info in info.get("player_response", {}).get("streamingData", {}).get("formats", []): if "url" not in stream_info: continue stream = HTTPStream(self.session, stream_info["url"]) name = stream_info["qualityLabel"] streams[name] = stream if not is_live: streams = self._create_adaptive_streams(info, streams) hls_manifest = info.get("player_response", {}).get("streamingData", {}).get("hlsManifestUrl") if hls_manifest: try: hls_streams = HLSStream.parse_variant_playlist( self.session, hls_manifest, namekey="pixels" ) streams.update(hls_streams) except IOError as err: log.warning("Failed to extract HLS streams: {0}", err) if not streams and protected: raise PluginError("This plugin does not support protected videos, " "try youtube-dl instead") return streams
def _get_streams(self): res = http.get(self.url, schema=_schema) if res["export_url"]: return self._get_live_stream(res["export_url"]) elif res["video_flashvars"]: stream = RTMPStream(self.session, { "rtmp": res["video_flashvars"]["_111pix_serverURL"], "playpath": res["video_flashvars"]["en_flash_providerName"], "swfVfy": SWF_VIDEO_URL, "pageUrl": self.url }) return dict(video=stream) elif res["standby_video"]: for stream in res["standby_video"]: stream = HTTPStream(self.session, stream["streamName"]) return dict(replay=stream) elif res["history_video"]: stream = HTTPStream(self.session, res["history_video"]) return dict(history=stream) return
def _get_vod_streams(self): url = 'http://ida.omroep.nl/odi/?prid={0}&puboptions=adaptive,h264_bb,h264_sb,h264_std&adaptive=no&part=1&token={1}'\ .format(quote(self.npo_id), quote(self.get_token())) res = http.get(url, headers=HTTP_HEADERS) data = res.json() streams = {} stream = http.get(data['streams'][0].replace('jsonp', 'json'), headers=HTTP_HEADERS).json() streams['best'] = streams['high'] = HTTPStream(self.session, stream['url']) return streams
def _get_vod_stream(self): def find_video_url(content): for elem in itertags(content, "meta"): if elem.attributes.get("property") == "og:video": return elem.attributes.get("content") video_url = self.session.http.get( self.url, schema=validate.Schema(validate.transform(find_video_url), validate.any(None, validate.url()))) if video_url is not None: return dict(vod=HTTPStream(self.session, video_url))
def _get_streams(self): match = self._url_re.match(self.url) video_id = match.group('video_id') if video_id is not None: # VOD live = False player_url = self.VOD_PLAYER_URL.format(video_id) else: # Live live = True player_url = self.LIVE_PLAYER_URL res = self.session.http.get(player_url) playlist = re.findall(self._playlist_re, res.text) index = 0 if not live: # Get the index for the video on the playlist match = self._vod_video_index_re.search(res.text) if match is None: return index = int(match.group('video_index')) if not playlist: return videos = self._video_schema.validate(playlist[index]) for video in videos: video_url = video['file'] # Ignore non-supported MSS streams if 'isml/Manifest' in video_url: continue try: if '.m3u8' in video_url: for stream in HLSStream.parse_variant_playlist( self.session, video_url).items(): yield stream elif '.mp4' in video_url: match = self._mp4_bitrate_re.match(video_url) if match is not None: bitrate = '%sk' % match.group('bitrate') else: bitrate = 'vod' yield bitrate, HTTPStream(self.session, video_url) except IOError as err: if '403 Client Error' in str(err): self.logger.error( 'Failed to access stream, may be due to geo-restriction' ) raise
def test_http_stream(self): expected = "http://test.se/stream" stream = HTTPStream(self.session, expected) self.assertEqual(expected, stream_to_url(stream)) self.assertEqual(expected, stream.to_url())