def test_dict_optional_keys(self): assert validate({"a": 1, optional("b"): 2}, {"a": 1}) == {"a": 1} assert validate({ "a": 1, optional("b"): 2 }, { "a": 1, "b": 2 }) == { "a": 1, "b": 2 }
SWF_URL = "http://www.ardmediathek.de/ard/static/player/base/flash/PluginFlash.swf" HDCORE_PARAMETER = "?hdcore=3.3.0" QUALITY_MAP = { "auto": "auto", 3: "544p", 2: "360p", 1: "288p", 0: "144p" } _url_re = re.compile("http(s)?://(\w+\.)?ardmediathek.de/tv") _media_id_re = re.compile("/play/config/(\d+)") _media_schema = validate.Schema({ "_mediaArray": [{ "_mediaStreamArray": [{ validate.optional("_server"): validate.text, "_stream": validate.any(validate.text, [validate.text]), "_quality": validate.any(int, validate.text) }] }] }) _smil_schema = validate.Schema( validate.union({ "base": validate.all( validate.xml_find("head/meta"), validate.get("base"), validate.url(scheme="http") ), "videos": validate.all( validate.xml_findall("body/seq/video"), [validate.get("src")]
_channel_schema = validate.Schema( { "data" : validate.any(None, { "channel" : validate.any(None, { "id" : validate.all( validate.text, validate.transform(int) ), "vid" : int }) }) }, validate.get("data") ); _qq_schema = validate.Schema({ validate.optional("playurl"): validate.url(scheme="http") }, validate.get("playurl") ) STREAM_WEIGHTS = { "middle": 540, "source": 1080 } class Tga(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) @classmethod
HLS_PLAYLIST_URL = ( "http://iphone-streaming.ustream.tv" "/uhls/{0}/streams/live/iphone/playlist.m3u8" ) RECORDED_URL = "http://tcdn.ustream.tv/video/{0}" RTMP_URL = "rtmp://r{0}.1.{1}.channel.live.ums.ustream.tv:80/ustream" SWF_URL = "http://static-cdn1.ustream.tv/swf/live/viewer.rsl:505.swf" _module_info_schema = validate.Schema( list, validate.length(1), validate.get(0), dict ) _recorded_schema = validate.Schema({ validate.optional("stream"): [{ "name": validate.text, "streams": [{ "streamName": validate.text, "bitrate": float, }], validate.optional("url"): validate.text, }] }) _channel_schema = validate.Schema({ validate.optional("stream"): validate.any([{ "name": validate.text, "url": validate.text, "streams": [ validate.any({
validate.length(1), validate.get(0) ) _player_schema = validate.Schema( { "clip": { "baseUrl": validate.any(None, validate.text), "bitrates": validate.all( validate.filter(lambda b: b.get("url") and b.get("label")), [{ "label": validate.text, "url": validate.text }], ) }, validate.optional("playlist"): [{ validate.optional("connectionProvider"): validate.text, validate.optional("netConnectionUrl"): validate.text, validate.optional("bitrates"): [{ "label": validate.text, "url": validate.text }] }], "plugins": { validate.optional("clustering"): { "netConnectionUrl": validate.text, "url": validate.text } } } )
def parse_fmt_list(formatsmap): formats = {} if not formatsmap: return formats for format in formatsmap.split(","): s = format.split("/") (w, h) = s[1].split("x") formats[int(s[0])] = "{0}p".format(h) return formats _config_schema = validate.Schema({ validate.optional("fmt_list"): validate.all(validate.text, validate.transform(parse_fmt_list)), validate.optional("url_encoded_fmt_stream_map"): validate.all(validate.text, validate.transform(parse_stream_map), [{ "itag": validate.all(validate.text, validate.transform(int)), "quality": validate.text, "url": validate.url(scheme="http"), validate.optional("s"): validate.text, validate.optional("stereo3d"): validate.all(validate.text, validate.transform(int), validate.transform(bool)), }]),
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)
int(ts[-6:-5] + "1") ) _url_re = re.compile(""" http(s)?://(\w+\.)?crunchyroll\. (?: com|de|es|fr|co.jp ) /[^/&?]+ /[^/&?]+-(?P<media_id>\d+) """, re.VERBOSE) _api_schema = validate.Schema({ "error": bool, validate.optional("code"): validate.text, validate.optional("message"): validate.text, validate.optional("data"): object, }) _media_schema = validate.Schema( { "stream_data": validate.any( None, { "streams": validate.all( [{ "quality": validate.text, "url": validate.url( scheme="http", path=validate.endswith(".m3u8") )
validate.transform(_csrf_token_re.search), validate.any(None, validate.get(1)) ) _hls_playlist_schema = validate.Schema( validate.transform(_hls_playlist_re.search), validate.any( None, validate.all( validate.get(1), validate.url(scheme="http", path=validate.endswith(".m3u8")) ) ) ) _login_schema = validate.Schema({ "email": validate.text, validate.optional("errors"): validate.all( { "base": [validate.text] }, validate.get("base"), ) }) class Livestation(Plugin): options = PluginOptions({ "email": "", "password": "" }) @classmethod
API_URL = "http://veetle.com/index.php/stream/ajaxStreamLocation/{0}/flash" _url_re = re.compile( """ http(s)?://(\w+\.)?veetle.com (:? /.*(v|view)/ (?P<channel>[^/]+/[^/&?]+) )? """, re.VERBOSE, ) _schema = validate.Schema( {validate.optional("isLive"): bool, "payload": validate.any(int, validate.url(scheme="http")), "success": bool} ) class Veetle(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): match = _url_re.match(self.url) parsed = urlparse(self.url) if parsed.fragment: channel_id = parsed.fragment elif parsed.path[:3] == "/v/": channel_id = parsed.path.split("/")[-1]
KEEP_ALIVE_URL = "{server}/stream_keepalive.html" STREAM_INFO_URLS = { "rtmp": "http://sessionmanager01.afreeca.tv:6060/broad_stream_assign.html", "hls": "http://resourcemanager.afreeca.tv:9090/broad_stream_assign.html" } CHANNEL_RESULT_ERROR = 0 CHANNEL_RESULT_OK = 1 _url_re = re.compile("http(s)?://(\w+\.)?afreeca.com/(?P<username>\w+)") _channel_schema = validate.Schema( { "CHANNEL": { "RESULT": validate.transform(int), validate.optional("BNO"): validate.text, } }, validate.get("CHANNEL")) _stream_schema = validate.Schema({ validate.optional("view_url"): validate.url(scheme=validate.any("rtmp", "http")) }) class AfreecaTV(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_channel_info(self, username): data = {"bid": username}
validate.filter(lambda s: s["LinkType"] in STREAMING_TYPES), ), } ] }, validate.get("Data", {}), ) _video_schema = validate.Schema( { "Data": [ { "Assets": validate.all( [ { validate.optional("Links"): validate.all( [{"Target": validate.text, "Uri": validate.text}], validate.filter(lambda l: l["Target"] in STREAMING_TYPES), ) } ], validate.filter(lambda a: "Links" in a), ) } ] }, validate.get("Data", {}), validate.get(0, {}), validate.get("Assets", {}), validate.get(0, {}), validate.get("Links", []),
"http(s)?://(\w+\.)?weeb.tv/(channel|online)/(?P<channel>[^/&?]+)") _schema = validate.Schema( dict, validate.map(lambda k, v: (PARAMS_KEY_MAP.get(k, k), v)), validate.any( { "status": validate.transform(int), "rtmp": validate.url(scheme="rtmp"), "playpath": validate.text, "multibitrate": validate.all(validate.transform(int), validate.transform(bool)), "block_type": validate.transform(int), validate.optional("token"): validate.text, validate.optional("block_time"): validate.text, validate.optional("reconnect_time"): validate.text, }, { "status": validate.transform(int), }, )) class Weeb(Plugin): @classmethod def can_handle_url(self, url):
STREAM_INFO_URLS = { "rtmp": "http://sessionmanager01.afreeca.tv:6060/broad_stream_assign.html", "hls": "http://resourcemanager.afreeca.tv:9090/broad_stream_assign.html" } CHANNEL_RESULT_ERROR = 0 CHANNEL_RESULT_OK = 1 _url_re = re.compile("http(s)?://(\w+\.)?afreeca.com/(?P<username>\w+)") _channel_schema = validate.Schema( { "CHANNEL": { "RESULT": validate.transform(int), validate.optional("BNO"): validate.text, } }, validate.get("CHANNEL") ) _stream_schema = validate.Schema( { validate.optional("view_url"): validate.url( scheme=validate.any("rtmp", "http") ) } ) class AfreecaTV(Plugin): @classmethod
from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HTTPStream, HDSStream, RTMPStream MEDIA_URL = "http://www.ardmediathek.de/play/media/{0}" SWF_URL = "http://www.ardmediathek.de/ard/static/player/base/flash/PluginFlash.swf" HDCORE_PARAMETER = "?hdcore=3.3.0" QUALITY_MAP = {"auto": "auto", 3: "544p", 2: "360p", 1: "288p", 0: "144p"} _url_re = re.compile("http(s)?://(\w+\.)?ardmediathek.de/tv") _media_id_re = re.compile("/play/config/(\d+)") _media_schema = validate.Schema({ "_mediaArray": [{ "_mediaStreamArray": [{ validate.optional("_server"): validate.text, "_stream": validate.any(validate.text, [validate.text]), "_quality": validate.any(int, validate.text) }] }] }) _smil_schema = validate.Schema( validate.union({ "base": validate.all(validate.xml_find("head/meta"), validate.get("base"), validate.url(scheme="http")), "videos": validate.all(validate.xml_findall("body/seq/video"),
_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")) _user_schema = validate.Schema( {validate.optional("display_name"): validate.text}, validate.get("display_name")) _video_schema = validate.Schema({ "chunks": { validate.text: [{ "length": int, "url": validate.any(None, validate.url(scheme="http")), "upkeep": validate.any("pass", "fail", None) }] }, "restrictions": { validate.text: validate.text }, "start_offset": int, "end_offset": int, })
import re from random import random from livestreamer.plugin import Plugin, PluginError from livestreamer.plugin.api import http, validate from livestreamer.stream import HTTPStream, RTMPStream API_CLIENT_NAME = "Bambuser AS2" API_CONTEXT = "b_broadcastpage" API_KEY = "005f64509e19a868399060af746a00aa" API_URL_VIDEO = "http://player-c.api.bambuser.com/getVideo.json" _url_re = re.compile("http(s)?://(\w+.)?bambuser.com/v/(?P<video_id>\d+)") _video_schema = validate.Schema({ validate.optional("error"): validate.text, validate.optional("result"): { "id": validate.text, "size": validate.text, "url": validate.url(scheme=validate.any("rtmp", "http")) } }) class Bambuser(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): match = _url_re.match(self.url)
from livestreamer.plugin.api import validate from livestreamer.plugin.api.utils import parse_json __all__ = ["parse_playlist"] _playlist_re = re.compile("\(?\{.*playlist: (\[.*\]),.*?\}\)?;", re.DOTALL) _js_to_json = partial(re.compile("(\w+):\s").sub, r'"\1":') _playlist_schema = validate.Schema( validate.transform(_playlist_re.search), validate.any( None, validate.all( validate.get(1), validate.transform(_js_to_json), validate.transform(parse_json), [{ "sources": [{ "file": validate.text, validate.optional("label"): validate.text }] }] ) ) ) def parse_playlist(res): """Attempts to parse a JWPlayer playlist in a HTTP response body.""" return _playlist_schema.validate(res.text)
validate.get("Stream")) ], validate.get(0)) }, validate.get("Streams")) ], "Server": validate.text }], validate.filter(lambda s: s["LinkType"] in STREAMING_TYPES)) }] }, validate.get("Data", {})) _video_schema = validate.Schema( { "Data": [{ "Assets": validate.all([{ validate.optional("Links"): validate.all([{ "Target": validate.text, "Uri": validate.text }], validate.filter(lambda l: l["Target"] in STREAMING_TYPES)) }], validate.filter(lambda a: "Links" in a)) }] }, validate.get("Data", {}), validate.get(0, {}), validate.get("Assets", {}), validate.get(0, {}), validate.get("Links", []), )
(?: /recorded/(?P<video_id>\d+) )? """, re.VERBOSE) _channel_id_re = re.compile("\"cid\":(\d+)") HLS_PLAYLIST_URL = ("http://iphone-streaming.ustream.tv" "/uhls/{0}/streams/live/iphone/playlist.m3u8") RECORDED_URL = "http://tcdn.ustream.tv/video/{0}" RTMP_URL = "rtmp://r{0}.1.{1}.channel.live.ums.ustream.tv:80/ustream" SWF_URL = "http://static-cdn1.ustream.tv/swf/live/viewer.rsl:505.swf" _module_info_schema = validate.Schema(list, validate.length(1), validate.get(0), dict) _recorded_schema = validate.Schema({ validate.optional("stream"): [{ "name": validate.text, "streams": [{ "streamName": validate.text, "bitrate": float, }], validate.optional("url"): validate.text, }] }) _channel_schema = validate.Schema({ validate.optional("stream"): validate.any([{ "name": validate.text,
_channel_schema = validate.Schema( { "data": validate.any( None, { "channel": validate.any( None, { "id": validate.all(validate.text, validate.transform(int)), "vid": int }) }) }, validate.get("data")) _qq_schema = validate.Schema( {validate.optional("playurl"): validate.url(scheme="http")}, validate.get("playurl")) STREAM_WEIGHTS = {"middle": 540, "source": 1080} class Tga(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) @classmethod def stream_weight(cls, stream): if stream in STREAM_WEIGHTS: return STREAM_WEIGHTS[stream], "tga"
""" http(s)?://(\w+\.)? dailymotion.com (/embed)?/video /(?P<media_id>[^_?/]+) """, re.VERBOSE, ) _media_inner_schema = validate.Schema( [ { "layerList": [ { "name": validate.text, validate.optional("sequenceList"): [ { "layerList": validate.all( [{"name": validate.text, validate.optional("param"): dict}], validate.filter(lambda l: l["name"] in ("video", "reporting")), ) } ], } ] } ] ) _media_schema = validate.Schema( validate.any(_media_inner_schema, validate.all({"sequence": _media_inner_schema}, validate.get("sequence"))) )
_url_re = re.compile("http(s)?://(\w+\.)?connectcast.tv/") _playlist_re = re.compile("playlist: (\[.+\]),", re.DOTALL) _js_to_json = partial(re.compile("(\w+):\s").sub, r'"\1":') _playlist_schema = validate.Schema( validate.transform(_playlist_re.search), validate.any( None, validate.all( validate.get(1), validate.transform(_js_to_json), validate.transform(parse_json), [{ "sources": [{ "file": validate.text, validate.optional("label"): validate.text }] }] ) ) ) _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")]
def parse_fmt_list(formatsmap): formats = {} if not formatsmap: return formats for format in formatsmap.split(","): s = format.split("/") (w, h) = s[1].split("x") formats[int(s[0])] = "{0}p".format(h) return formats _config_schema = validate.Schema( { validate.optional("fmt_list"): validate.all( validate.text, validate.transform(parse_fmt_list) ), validate.optional("url_encoded_fmt_stream_map"): validate.all( validate.text, validate.transform(parse_stream_map), [{ "itag": validate.all( validate.text, validate.transform(int) ), "quality": validate.text, "url": validate.url(scheme="http"), validate.optional("s"): validate.text, validate.optional("stereo3d"): validate.all(
_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") ) _user_schema = validate.Schema( { validate.optional("display_name"): validate.text }, validate.get("display_name") ) _video_schema = validate.Schema( { "chunks": { validate.text: [{ "length": int, "url": validate.any(None, validate.url(scheme="http")), "upkeep": validate.any("pass", "fail", None) }] }, "restrictions": { validate.text: validate.text }, "start_offset": int, "end_offset": int,
import re from livestreamer.compat import urlparse from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import RTMPStream, HTTPStream, HLSStream from livestreamer.utils import parse_json, rtmpparse, swfdecompress _url_re = re.compile("http(s)?://api.dmcloud.net/player/embed/[^/]+/[^/]+") _rtmp_re = re.compile(b"customURL[^h]+(https://.*?)\\\\") _info_re = re.compile("var info = (.*);") _schema = validate.Schema({ "mode": validate.text, validate.optional("mp4_url"): validate.url(scheme="http"), validate.optional("ios_url"): validate.url(scheme="http"), validate.optional("swf_url"): validate.url(scheme="http"), }) class DMCloud(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_rtmp_stream(self, swfurl): res = http.get(swfurl) swf = swfdecompress(res.content)
_url_re = re.compile(r"http(s)?://([\w\.]+)?twitch.tv/[^/]+(/[ab]/\d+)?") _time_re = re.compile(""" (?: (?P<hours>\d+)h )? (?: (?P<minutes>\d+)m )? (?: (?P<seconds>\d+)s )? """, re.VERBOSE) _user_schema = validate.Schema( { validate.optional("display_name"): validate.text }, validate.get("display_name") ) _video_schema = validate.Schema( { "chunks": { validate.text: [{ "length": int, "url": validate.text }] }, "restrictions": { validate.text: validate.text }, "start_offset": int, "end_offset": int, }
from livestreamer.plugin.api.utils import parse_json from livestreamer.stream import AkamaiHDStream, HLSStream _url_re = re.compile("http(s)?://new.livestream.com/") _stream_config_schema = validate.Schema({ "event": { "stream_info": validate.any( { "is_live": bool, "qualities": [{ "bitrate": int, "height": int }], validate.optional("play_url"): validate.url(scheme="http"), validate.optional("m3u8_url"): validate.url(scheme="http", path=validate.endswith(".m3u8")), }, None) }, validate.optional("viewerPlusSwfUrl"): validate.url(scheme="http"), validate.optional("hdPlayerSwfUrl"): validate.text }) _smil_schema = validate.Schema( validate.union({ "http_base": validate.all( validate.xml_find("{http://www.w3.org/2001/SMIL20/Language}head/"
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)) })) def convert_jtv_to_twitch_video(video): data = dict(start_offset=video.get("bracket_start", 0), end_offset=video.get("bracket_end", 0), chunks=defaultdict(list), restrictions={})
/(?P<app>[^/]+) /(?P<playpath>.+) """, re.VERBOSE) _url_re = re.compile( """ http(s)?://(\w+\.)? dailymotion.com (/embed)?/(video|live) /(?P<media_id>[^_?/]+) """, re.VERBOSE) _media_inner_schema = validate.Schema([{ "layerList": [{ "name": validate.text, validate.optional("sequenceList"): [{ "layerList": validate.all([{ "name": validate.text, validate.optional("param"): dict }], validate.filter(lambda l: l["name"] in ("video", "reporting"))) }] }] }]) _media_schema = validate.Schema( validate.any( _media_inner_schema, validate.all({"sequence": _media_inner_schema}, validate.get("sequence")))) _vod_playlist_schema = validate.Schema({ "duration": float,
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) ) })) def convert_jtv_to_twitch_video(video): data = dict(start_offset=video.get("bracket_start", 0),
from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import FLVPlaylist, HTTPStream API_URL = "http://veetle.com/index.php/stream/ajaxStreamLocation/{0}/flash" _url_re = re.compile(""" http(s)?://(\w+\.)?veetle.com (:? /.*(v|view)/ (?P<channel>[^/]+/[^/&?]+) )? """, re.VERBOSE) _schema = validate.Schema({ validate.optional("isLive"): bool, "payload": validate.any(int, validate.url(scheme="http")), "success": bool }) class Veetle(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): match = _url_re.match(self.url) parsed = urlparse(self.url) if parsed.fragment: channel_id = parsed.fragment
import re from random import random from livestreamer.plugin import Plugin, PluginError from livestreamer.plugin.api import http, validate from livestreamer.stream import HTTPStream, RTMPStream API_CLIENT_NAME = "Bambuser AS2" API_CONTEXT = "b_broadcastpage" API_KEY = "005f64509e19a868399060af746a00aa" API_URL_VIDEO = "http://player-c.api.bambuser.com/getVideo.json" _url_re = re.compile("http(s)?://(\w+.)?bambuser.com/v/(?P<video_id>\d+)") _video_schema = validate.Schema({ validate.optional("error"): validate.text, validate.optional("result"): { "id": validate.text, "size": validate.text, "url": validate.url( scheme=validate.any("rtmp", "http") ) } }) class Bambuser(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url)
CHANNELS_API_URL = "http://api.gaminglive.tv/channels/{0}" QUALITY_WEIGHTS = { "live": 3, "medium": 2, "low": 1, } _url_re = re.compile(""" http(s)?://(staging|alpha)\.gaminglive\.tv /\#/channels/(?P<channel>[^/]+) """, re.VERBOSE) _quality_re = re.compile("[^/]+-(?P<quality>[^/]+)") _channel_schema = validate.Schema( { validate.optional("state"): { "stream": { "qualities": [validate.text], "rootUrl": validate.url(scheme="rtmp") } } }, validate.get("state") ) class GamingLive(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url)
list, validate.length(1), validate.get(0), dict ) _amf3_array = validate.Schema( validate.any( validate.all( {int: object}, validate.transform(lambda a: list(a.values())), ), list ) ) _recorded_schema = validate.Schema({ validate.optional("stream"): validate.all( _amf3_array, [{ "name": validate.text, "streams": validate.all( _amf3_array, [{ "streamName": validate.text, "bitrate": float, }], ), validate.optional("url"): validate.text, }] ) }) _stream_schema = validate.Schema({
HLS_PLAYLIST_URL = ("http://iphone-streaming.ustream.tv" "/uhls/{0}/streams/live/iphone/playlist.m3u8") RECORDED_URL = "http://tcdn.ustream.tv/video/{0}" RTMP_URL = "rtmp://r{0}-1-{1}-channel-live.ums.ustream.tv:1935/ustream" SWF_URL = "http://static-cdn1.ustream.tv/swf/live/viewer.rsl:505.swf" _module_info_schema = validate.Schema(list, validate.length(1), validate.get(0), dict) _amf3_array = validate.Schema( validate.any( validate.all( {int: object}, validate.transform(lambda a: list(a.values())), ), list)) _recorded_schema = validate.Schema({ validate.optional("stream"): validate.all(_amf3_array, [{ "name": validate.text, "streams": validate.all( _amf3_array, [{ "streamName": validate.text, "bitrate": float, }], ), validate.optional("url"): validate.text, }]) })
_url_re = re.compile("http(s)?://(\w+\.)?weeb.tv/channel/(?P<channel>[^/&?]+)") _schema = validate.Schema( dict, validate.map(lambda k, v: (PARAMS_KEY_MAP.get(k, k), v)), validate.any( { "status": validate.transform(int), "rtmp": validate.url(scheme="rtmp"), "playpath": validate.text, "multibitrate": validate.all( validate.transform(int), validate.transform(bool) ), "block_type": validate.transform(int), validate.optional("token"): validate.text, validate.optional("block_time"): validate.text, validate.optional("reconnect_time"): validate.text, }, { "status": validate.transform(int), }, ) ) class Weeb(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self):
import re from livestreamer.compat import urlparse from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import RTMPStream, HTTPStream, HLSStream from livestreamer.utils import parse_json, rtmpparse, swfdecompress _url_re = re.compile("http(s)?://api.dmcloud.net/player/embed/[^/]+/[^/]+") _rtmp_re = re.compile(b"customURL[^h]+(https://.*?)\\\\") _info_re = re.compile("var info = (.*);") _schema = validate.Schema( { "mode": validate.text, validate.optional("mp4_url"): validate.url(scheme="http"), validate.optional("ios_url"): validate.url(scheme="http"), validate.optional("swf_url"): validate.url(scheme="http"), } ) class DMCloud(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_rtmp_stream(self, swfurl): res = http.get(swfurl) swf = swfdecompress(res.content) match = _rtmp_re.search(swf) if not match:
_url_re = re.compile("http(s)?://(\w+\.)?be-at.tv/") _schema = validate.Schema( validate.any( None, { "status": int, "media": [{ "duration": validate.any(float, int), "offset": int, "id": int, "parts": [{ "duration": validate.any(float, int), "id": int, "offset": int, validate.optional("recording"): int, validate.optional("start"): validate.any(float, int) }] }] } ) ) Chunk = namedtuple("Chunk", "recording quality sequence extension") class BeatFLVTagConcat(FLVTagConcat): def __init__(self, *args, **kwargs): FLVTagConcat.__init__(self, *args, **kwargs) def decrypt_data(self, key, iv, data):
_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") ) _user_schema = validate.Schema( { validate.optional("display_name"): validate.text }, validate.get("display_name") ) _video_schema = validate.Schema( { "chunks": { validate.text: [{ "length": int, "url": validate.any(None, validate.url(scheme="http")), "upkeep": validate.any("pass", "fail", None) }] }, "restrictions": {validate.text: validate.text}, "start_offset": int, "end_offset": int,
from livestreamer.compat import urljoin from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.plugin.api.utils import parse_json from livestreamer.stream import AkamaiHDStream, HLSStream _url_re = re.compile("http(s)?://(www\.)?livestream.com/") _stream_config_schema = validate.Schema({ "event": { "stream_info": validate.any({ "is_live": bool, "qualities": [{ "bitrate": int, "height": int }], validate.optional("play_url"): validate.url(scheme="http"), validate.optional("m3u8_url"): validate.url( scheme="http", path=validate.endswith(".m3u8") ), }, None) }, validate.optional("viewerPlusSwfUrl"): validate.url(scheme="http"), validate.optional("hdPlayerSwfUrl"): validate.text }) _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={
SWF_URL = "http://mips.tv/content/scripts/eplayer.swf" _url_re = re.compile("http(s)?://(\w+.)?mips.tv/(?P<channel>[^/&?]+)") _flashvars_re = re.compile("'FlashVars', '([^']+)'") _rtmp_re = re.compile("redirect=(.+)") _schema = validate.Schema( validate.transform(_flashvars_re.search), validate.any( None, validate.all( validate.get(1), validate.transform(parse_query), { "id": validate.transform(int), validate.optional("s"): validate.text } ) ) ) _rtmp_schema = validate.Schema( validate.transform(_rtmp_re.search), validate.get(1), ) class Mips(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url)
"480": 2, "medium": 2, "360": 1, "low": 1 } _url_re = re.compile( """ http(s)?://(\w+\.)?gaminglive\.tv /(?P<type>channels|videos)/(?P<name>[^/]+) """, re.VERBOSE) _quality_re = re.compile("[^/]+-(?P<quality>[^/]+)") _channel_schema = validate.Schema( { validate.optional("state"): { "stream": { "qualities": [validate.text], "rootUrl": validate.url(scheme="rtmp") } } }, validate.get("state")) _vod_schema = validate.Schema( { "name": validate.text, "channel_slug": validate.text, "title": validate.text, "created_at": validate.transform(int) }, )
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
_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") ) _viewer_info_schema = validate.Schema( { validate.optional("login"): validate.text }, validate.get("login") ) _viewer_token_schema = validate.Schema( { validate.optional("token"): validate.text }, validate.get("token") ) class UsherService(object): def __init__(self, host="justin.tv"): self.host = host
BALANCER_URL = "http://www.mips.tv:1935/loadbalancer" PLAYER_URL = "http://mips.tv/embedplayer/{0}/1/500/400" SWF_URL = "http://mips.tv/content/scripts/eplayer.swf" _url_re = re.compile("http(s)?://(\w+.)?mips.tv/(?P<channel>[^/&?]+)") _flashvars_re = re.compile("'FlashVars', '([^']+)'") _rtmp_re = re.compile("redirect=(.+)") _schema = validate.Schema( validate.transform(_flashvars_re.search), validate.any( None, validate.all(validate.get(1), validate.transform(parse_query), { "id": validate.transform(int), validate.optional("s"): validate.text }))) _rtmp_schema = validate.Schema( validate.transform(_rtmp_re.search), validate.get(1), ) class Mips(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): match = _url_re.match(self.url) channel = match.group("channel")
_channel_schema = validate.Schema( { "CHANNEL": { "RESULT": validate.transform(int), "BNO": validate.text, "CDN": validate.text, "RMD": validate.text, } }, validate.get("CHANNEL")) _channel_aid_schema = validate.Schema( {"CHANNEL": { "RESULT": validate.transform(int), "AID": validate.text, }}, validate.get("CHANNEL")) _stream_schema = validate.Schema({ validate.optional("view_url"): validate.url(scheme=validate.any("rtmp", "http")) }) class AfreecaTV_PC(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_channel_info(self, bid): headers = { "Referer": "http://play.afreecatv.com", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", } params = {"bid": bid}
def test_dict_optional_keys(self): assert validate({"a": 1, optional("b"): 2}, {"a": 1}) == {"a": 1} assert validate({"a": 1, optional("b"): 2}, {"a": 1, "b": 2}) == {"a": 1, "b": 2}
}], }, validate.get("livestream"), validate.length(1), validate.get(0)) _player_schema = validate.Schema({ "clip": { "baseUrl": validate.any(None, validate.text), "bitrates": validate.all( validate.filter(lambda b: b.get("url") and b.get("label")), [{ "label": validate.text, "url": validate.text, }], ) }, validate.optional("playlist"): [{ validate.optional("connectionProvider"): validate.text, validate.optional("netConnectionUrl"): validate.text, validate.optional("bitrates"): [{ "label": validate.text, "url": validate.text, "provider": validate.text }] }], "plugins": validate.all( dict, validate.filter(lambda k, v: k in ["rtmp", "rtmpHitbox", "hls"]), { validate.text: {
_json_re = re.compile('arte_vp_(?:live-)?url="([^"]+)"') _schema = validate.Schema( validate.transform(_json_re.search), validate.any(None, validate.all(validate.get(1), validate.url(scheme="http"))) ) _video_schema = validate.Schema( { "videoJsonPlayer": { "VSR": validate.any( [], { validate.text: { "height": int, "mediaType": validate.text, "url": validate.text, validate.optional("streamer"): validate.text, } }, ), "VTY": validate.text, } } ) class ArteTV(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _create_stream(self, stream, is_live):
from livestreamer.compat import urljoin from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.plugin.api.utils import parse_json from livestreamer.stream import AkamaiHDStream, HLSStream _url_re = re.compile("http(s)?://new.livestream.com/") _stream_config_schema = validate.Schema({ "event": { "stream_info": validate.any({ "is_live": bool, "qualities": [{ "bitrate": int, "height": int }], validate.optional("play_url"): validate.url(scheme="http"), validate.optional("m3u8_url"): validate.url( scheme="http", path=validate.endswith(".m3u8") ), }, None) }, validate.optional("viewerPlusSwfUrl"): validate.url(scheme="http"), validate.optional("hdPlayerSwfUrl"): validate.text }) _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={
_rtmp_re = re.compile(""" (?P<host>rtmp://[^/]+) /(?P<app>[^/]+) /(?P<playpath>.+) """, re.VERBOSE) _url_re = re.compile(""" http(s)?://(\w+\.)? dailymotion.com (/embed)?/(video|live) /(?P<media_id>[^_?/]+) """, re.VERBOSE) _media_inner_schema = validate.Schema([{ "layerList": [{ "name": validate.text, validate.optional("sequenceList"): [{ "layerList": validate.all( [{ "name": validate.text, validate.optional("param"): dict }], validate.filter(lambda l: l["name"] in ("video", "reporting")) ) }] }] }]) _media_schema = validate.Schema( validate.any( _media_inner_schema, validate.all( {"sequence": _media_inner_schema},
_schema = validate.Schema( validate.transform(_json_re.search), validate.any(None, validate.all(validate.get(2), validate.url(scheme="http")))) _video_schema = validate.Schema({ "videoJsonPlayer": { "VSR": validate.any( [], { validate.text: { "height": int, "mediaType": validate.text, "url": validate.text, validate.optional("streamer"): validate.text }, }, ), "VTY": validate.text } }) class ArteTV(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _create_stream(self, stream, is_live):
_channel_schema = validate.Schema( { "CHANNEL": { "RESULT": validate.transform(int), "BROAD_INFOS": [{ "list": [{ "nBroadNo": validate.text }] }] } }, validate.get("CHANNEL") ) _stream_schema = validate.Schema( { validate.optional("view_url"): validate.url( scheme=validate.any("rtmp", "http") ) } ) class AfreecaTV(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_channel_info(self, username): headers = { "Referer": self.url }