)? (?: /video/\d+/[^/]+ )? """, re.VERBOSE) _file_re = re.compile("\"?file\"?:\s+['\"]([^'\"]+)['\"]") _swf_url_re = re.compile("swfobject.embedSWF\(\"([^\"]+)\",") _schema = validate.Schema( validate.union({ "urls": validate.all(validate.transform(_file_re.findall), validate.map(unquote), [validate.url()]), "swf": validate.all( validate.transform(_swf_url_re.search), validate.any( None, validate.all( validate.get(1), validate.url(scheme="http", path=validate.endswith("swf"))))) })) class Aliez(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): res = http.get(self.url, schema=_schema)
RTMP_URL = "rtmp://{0}/app/{1}" CHANNEL_DETAILS_URI = "https://api.streamup.com/1.0/channels/{0}?access_token={1}" REDIRECT_SERVICE_URI = "https://lancer.streamup.com/api/redirect/{0}" _url_re = re.compile("http(s)?://(\w+\.)?streamup.com/(?P<channel>[^/?]+)") _flashvars_re = re.compile("flashvars\.(?P<var>\w+)\s?=\s?'(?P<value>[^']+)';") _swf_url_re = re.compile('swfobject.embedSWF\(\s*"(?P<player_url>[^"]+)",') _schema = validate.Schema( validate.union( { "vars": validate.all( validate.transform(_flashvars_re.findall), validate.transform(dict), {"owner": validate.text, validate.optional("token"): validate.text}, ), "swf": validate.all( validate.transform(_swf_url_re.search), validate.get("player_url"), validate.endswith(".swf") ), } ) ) _channel_details_schema = validate.Schema({"channel": {"live": bool, "slug": validate.text}}) class StreamupCom(Plugin): @classmethod def can_handle_url(cls, url): return _url_re.match(url)
""", re.VERBOSE) _channel_not_found_re = re.compile("<title>Channel Not Found") def decode_token(token): return token.replace("0m0", "") _schema = validate.Schema( validate.transform(lambda s: s.split(";:mvnkey-")), validate.length(2), validate.union({ "server": validate.all( validate.get(0), validate.text ), "token": validate.all( validate.get(1), validate.text, validate.transform(decode_token) ) }) ) class VaughnLive(Plugin): @classmethod def can_handle_url(cls, url): return _url_re.match(url) def _get_streams(self): res = http.get(self.url)
def test_union(self): assert validate(union((get("foo"), get("bar"))), { "foo": "alpha", "bar": "beta" }) == ("alpha", "beta")
(?P<channel>[^/]+) (?: / (?P<video_type>[bc]) / (?P<video_id>\d+) )? """, re.VERBOSE) _access_token_schema = validate.Schema( { "token": validate.text, "sig": validate.text }, validate.union(( validate.get("sig"), validate.get("token") )) ) _token_schema = validate.Schema( { "chansub": { "restricted_bitrates": validate.all( [validate.text], validate.filter( lambda n: not re.match(r"(.+_)?archives|live|chunked", n) ) ) } }, validate.get("chansub") )
validate.text: { "rtmp_flash": { validate.text: { "name": validate.text, "server": validate.url(scheme="rtmp") } } } } }) _schema = validate.Schema( validate.union({ "lang": validate.all(validate.transform(_lang_re.search), validate.get(1)), "live": validate.all(validate.transform(_live_check_re.search), validate.transform(bool)), "videos": validate.all(validate.transform(_video_re.findall), [(validate.url(scheme="http"), validate.text)]) })) class Euronews(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_live_streams(self, lang): res = http.get(API_URL_LIVE) json_res = http.json(res, schema=_live_schema)
RTMP_URL = "rtmp://{0}/app/{1}" CHANNEL_DETAILS_URI = "https://api.streamup.com/1.0/channels/{0}?access_token={1}" REDIRECT_SERVICE_URI = "https://lancer.streamup.com/api/redirect/{0}" _url_re = re.compile("http(s)?://(\w+\.)?streamup.com/(?P<channel>[^/?]+)") _flashvars_re = re.compile("flashvars\.(?P<var>\w+)\s?=\s?'(?P<value>[^']+)';") _swf_url_re = re.compile("swfobject.embedSWF\(\s*\"(?P<player_url>[^\"]+)\",") _schema = validate.Schema( validate.union({ "vars": validate.all(validate.transform(_flashvars_re.findall), validate.transform(dict), { "owner": validate.text, validate.optional("token"): validate.text }), "swf": validate.all(validate.transform(_swf_url_re.search), validate.get("player_url"), validate.endswith(".swf")) })) _channel_details_schema = validate.Schema( {"channel": { "live": bool, "slug": validate.text }}) class StreamupCom(Plugin): @classmethod
from livestreamer.stream import HTTPStream, RTMPStream from livestreamer.plugin.api.support_plugin import common_jwplayer as jwplayer BASE_VOD_URL = "https://www.connectcast.tv" SWF_URL = "https://www.connectcast.tv/jwplayer/jwplayer.flash.swf" _url_re = re.compile("http(s)?://(\w+\.)?connectcast.tv/") _smil_schema = validate.Schema( validate.union({ "base": validate.all( validate.xml_find("head/meta"), validate.get("base"), validate.url(scheme="rtmp") ), "videos": validate.all( validate.xml_findall("body/video"), [validate.get("src")] ) }) ) class ConnectCast(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_smil_streams(self, url): res = http.get(url, verify=False)
_live_re = re.compile( """ \s*jwplayer\(\"player\"\)\.setup\({.*? \s*primary:\s+"([^"]+)".*? \s*file:\s+"([^"]+)" """, re.DOTALL) _live_schema = validate.Schema( validate.transform(_live_re.search), validate.any( None, validate.union({ "type": validate.get(1), "url": validate.all( validate.get(2), validate.url(scheme="http"), ), }))) class SSH101(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): res = http.get(self.url, schema=_live_schema) if not res: return
_schema = validate.Schema( validate.transform(_js_var_re.findall), validate.transform(dict), { "a": validate.transform(int), "b": validate.transform(int), "c": validate.transform(int), "d": validate.transform(int), "f": validate.transform(int), "v_part": validate.text, }, validate.union({ "server_ip": validate.transform(_parse_server_ip), "path": validate.all( validate.get("v_part"), validate.transform(_rtmp_re.findall), validate.get(0) ) }) ) class LetOnTV(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): match = _url_re.match(self.url) info = http.get(PLAYER_URL, params=match.groupdict(), schema=_schema) if not info["path"]:
from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream STREAM_INFO_URL = "https://api.periscope.tv/api/v2/getAccessPublic" STATUS_GONE = 410 STATUS_UNAVAILABLE = (STATUS_GONE,) _url_re = re.compile(r"http(s)?://(www\.)?periscope.tv/w/(?P<token>[\w\-\=]+)") _stream_schema = validate.Schema( validate.any( None, validate.union({ "hls_url": validate.all( {"hls_url": validate.url(scheme="http")}, validate.get("hls_url") ), }), validate.union({ "replay_url": validate.all( {"replay_url": validate.url(scheme="http")}, validate.get("replay_url") ), }), ), ) class Periscope(Plugin): @classmethod def can_handle_url(cls, url):
_video_schema = validate.Schema(validate.union({ "archives": validate.all( validate.xml_findall("archive"), [ validate.union({ "length": validate.all( validate.xml_findtext("length"), validate.transform(int), ), "transcodes": validate.all( validate.xml_find("transcode_file_urls"), validate.xml_findall("*"), validate.map( lambda e: (e.tag.replace("transcode_", ""), e.text) ), validate.transform(dict), ), "url": validate.xml_findtext("video_file_url") }), ] ), validate.optional("restrictions"): validate.xml_findtext( "archive_restrictions/restriction" ), validate.optional("bracket_start"): validate.all( validate.xml_findtext("bracket_start"), validate.transform(int) ), validate.optional("bracket_end"): validate.all( validate.xml_findtext("bracket_end"), validate.transform(int) ) }))
_video_schema = validate.Schema( validate.union({ "archives": validate.all(validate.xml_findall("archive"), [ validate.union({ "length": validate.all( validate.xml_findtext("length"), validate.transform(int), ), "transcodes": validate.all( validate.xml_find("transcode_file_urls"), validate.xml_findall("*"), validate.map(lambda e: (e.tag.replace("transcode_", ""), e.text)), validate.transform(dict), ), "url": validate.xml_findtext("video_file_url") }), ]), validate.optional("restrictions"): validate.xml_findtext("archive_restrictions/restriction"), validate.optional("bracket_start"): validate.all(validate.xml_findtext("bracket_start"), validate.transform(int)), validate.optional("bracket_end"): validate.all(validate.xml_findtext("bracket_end"), validate.transform(int)) }))
)? """, re.VERBOSE) _file_re = re.compile("\"?file\"?:\s+['\"]([^'\"]+)['\"]") _swf_url_re = re.compile("swfobject.embedSWF\(\"([^\"]+)\",") _schema = validate.Schema( validate.union({ "urls": validate.all( validate.transform(_file_re.findall), validate.map(unquote), [validate.url()] ), "swf": validate.all( validate.transform(_swf_url_re.search), validate.any( None, validate.all( validate.get(1), validate.url( scheme="http", path=validate.endswith("swf") ) ) ) ) }) ) class Aliez(Plugin): @classmethod def can_handle_url(self, url):
validate.union({ "export_url": validate.all( validate.transform(_live_export_re.search), validate.any( None, validate.get(1), ) ), "video_flashvars": validate.all( validate.transform(_video_flashvars_re.search), validate.any( None, validate.all( validate.get(1), validate.transform(parse_query), { "_111pix_serverURL": validate.url(scheme="rtmp"), "en_flash_providerName": validate.text } ) ) ), "history_video": validate.all( validate.transform(_history_re.search), validate.any( None, validate.all( validate.get(1), validate.url(scheme="http") ) ) ), "standby_video": validate.all( validate.transform(_replay_json_re.search), validate.any( None, validate.all( validate.get(1), validate.transform(parse_json), [{ "streamName": validate.url(scheme="http") }] ) ) ) })
validate.text: { "name": validate.text, "server": validate.url(scheme="rtmp") } } } } }) _schema = validate.Schema( validate.union({ "lang": validate.all( validate.transform(_lang_re.search), validate.get(1) ), "live": validate.all( validate.transform(_live_check_re.search), validate.transform(bool) ), "videos": validate.all( validate.transform(_video_re.findall), [(validate.url(scheme="http"), validate.text)] ) }) ) class Euronews(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_live_streams(self, lang):
def test_union(self): assert validate(union((get("foo"), get("bar"))), {"foo": "alpha", "bar": "beta"}) == ("alpha", "beta")
_url_re = re.compile("http(s)?://(\w+\.)?ssh101\.com/") _live_re = re.compile(""" \s*jwplayer\(\"player\"\)\.setup\({.*? \s*primary:\s+"([^"]+)".*? \s*file:\s+"([^"]+)" """, re.DOTALL) _live_schema = validate.Schema( validate.transform(_live_re.search), validate.any( None, validate.union({ "type": validate.get(1), "url": validate.all( validate.get(2), validate.url(scheme="http"), ), }) ) ) class SSH101(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): res = http.get(self.url, schema=_live_schema) if not res: return
_smil_schema = validate.Schema( validate.union({ "http_base": validate.all( validate.xml_find("{http://www.w3.org/2001/SMIL20/Language}head/" "{http://www.w3.org/2001/SMIL20/Language}meta" "[@name='httpBase']"), validate.xml_element(attrib={"content": validate.text}), validate.get("content")), "videos": validate.all( validate.xml_findall( "{http://www.w3.org/2001/SMIL20/Language}body/" "{http://www.w3.org/2001/SMIL20/Language}switch/" "{http://www.w3.org/2001/SMIL20/Language}video"), [ validate.all( validate.xml_element( attrib={ "src": validate.text, "system-bitrate": validate.all(validate.text, validate.transform( int)) }), validate.transform(lambda e: (e.attrib["src"], e.attrib[ "system-bitrate"]))) ], ) }))
from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HTTPStream, RTMPStream from livestreamer.plugin.api.support_plugin import common_jwplayer as jwplayer BASE_VOD_URL = "https://www.connectcast.tv" SWF_URL = "https://www.connectcast.tv/jwplayer/jwplayer.flash.swf" _url_re = re.compile("http(s)?://(\w+\.)?connectcast.tv/") _smil_schema = validate.Schema( validate.union({ "base": validate.all(validate.xml_find("head/meta"), validate.get("base"), validate.url(scheme="rtmp")), "videos": validate.all(validate.xml_findall("body/video"), [validate.get("src")]) })) class ConnectCast(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_smil_streams(self, url): res = http.get(url, verify=False) smil = http.xml(res, schema=_smil_schema) for video in smil["videos"]:
(?P<domain>vaughnlive|breakers|instagib|vapers).tv /(?P<channel>[^/&?]+) """, re.VERBOSE) _channel_not_found_re = re.compile("<title>Channel Not Found") def decode_token(token): return token.replace("0m0", "") _schema = validate.Schema( validate.transform(lambda s: s.split(";:mvnkey%")), validate.length(2), validate.union({ "server": validate.all(validate.get(0), validate.text), "token": validate.all(validate.get(1), validate.text, validate.transform(decode_token)) })) class VaughnLive(Plugin): @classmethod def can_handle_url(cls, url): return _url_re.match(url) def _get_streams(self): res = http.get(self.url) if _channel_not_found_re.search(res.text): return
CHANNEL_INFO = "https://beam.pro/api/v1/channels/{0}" CHANNEL_MANIFEST = "https://beam.pro/api/v1/channels/{0}/manifest.smil" _assets_schema = validate.Schema( validate.union({ "base": validate.all( validate.xml_find("./head/meta"), validate.get("base"), validate.url(scheme="rtmp") ), "videos": validate.all( validate.xml_findall(".//video"), [ validate.union({ "src": validate.all( validate.get("src"), validate.text ), "height": validate.all( validate.get("height"), validate.text, validate.transform(int) ) }) ] ) }) ) class Beam(Plugin): @classmethod
) } _url_re = re.compile(""" http(s)?://(\w+\.)?zdf.de/zdfmediathek(\#)?/.+ /(live|video) /(?P<video_id>\d+) """, re.VERBOSE | re.IGNORECASE) _schema = validate.Schema( validate.xml_findall("video/formitaeten/formitaet"), [ validate.union({ "type": validate.get("basetype"), "quality": validate.xml_findtext("quality"), "url": validate.all( validate.xml_findtext("url"), validate.url() ) }) ] ) class zdf_mediathek(Plugin): @classmethod def can_handle_url(cls, url): return _url_re.match(url) @classmethod def stream_weight(cls, key): weight = QUALITY_WEIGHTS.get(key)
}) _smil_schema = validate.Schema(validate.union({ "http_base": validate.all( validate.xml_find("{http://www.w3.org/2001/SMIL20/Language}head/" "{http://www.w3.org/2001/SMIL20/Language}meta" "[@name='httpBase']"), validate.xml_element(attrib={ "content": validate.text }), validate.get("content") ), "videos": validate.all( validate.xml_findall("{http://www.w3.org/2001/SMIL20/Language}body/" "{http://www.w3.org/2001/SMIL20/Language}switch/" "{http://www.w3.org/2001/SMIL20/Language}video"), [ validate.all( validate.xml_element(attrib={ "src": validate.text, "system-bitrate": validate.all( validate.text, validate.transform(int) ) }), validate.transform( lambda e: (e.attrib["src"], e.attrib["system-bitrate"]) ) ) ], ) }))
validate.union({ "export_url": validate.all(validate.transform(_live_export_re.search), validate.any( None, validate.get(1), )), "video_flashvars": validate.all( validate.transform(_video_flashvars_re.search), validate.any( None, validate.all( validate.get(1), validate.transform(parse_query), { "_111pix_serverURL": validate.url(scheme="rtmp"), "en_flash_providerName": validate.text }))), "history_video": validate.all( validate.transform(_history_re.search), validate.any( None, validate.all(validate.get(1), validate.url(scheme="http")))), "standby_video": validate.all( validate.transform(_replay_json_re.search), validate.any( None, validate.all(validate.get(1), validate.transform(parse_json), [{ "streamName": validate.url(scheme="http") }]))) }))