class DingitTV(Plugin): """ Plugin that supports playing streams from DingIt.tv """ # regex to match the site urls url_re = re.compile(r""" http://www.dingit.tv/( highlight/(?P<highlight_id>\d+)| channel/(?P<broadcaster>\w+)/(?P<channel_id>\d+) )""", re.VERBOSE) # flashvars API url and schema flashvars_url = "http://www.dingit.tv/api/get_player_flashvars" flashvars_schema = validate.Schema({ u"status": 0, u"data": [{ validate.optional("stream"): validate.text, validate.optional("akaurl"): validate.text, validate.optional("pereakaurl"): validate.text, }] }, validate.get("data"), validate.length(1), validate.get(0) ) pereakaurl = "http://dingitmedia-vh.akamaihd.net/i/{}/master.m3u8" akaurl = "https://dingmedia1-a.akamaihd.net/processed/delivery/{}70f8b7bc-5ed4-336d-609a-2d2cd86288c6.m3u8" @classmethod def can_handle_url(cls, url): return cls.url_re.match(url) is not None def _get_streams(self): match = self.url_re.match(self.url) res = http.post(self.flashvars_url, data=dict( broadcaster=match.group("broadcaster") or "Verm", stream_id=match.group("channel_id") or match.group("highlight_id"))) flashvars = http.json(res, schema=self.flashvars_schema) if flashvars.get("pereakaurl"): url = self.pereakaurl.format(flashvars.get("pereakaurl").strip("/")) return HLSStream.parse_variant_playlist(self.session, url) elif flashvars.get("akaurl"): url = self.akaurl.format(flashvars.get("akaurl").strip("/")) return HLSStream.parse_variant_playlist(self.session, url) elif flashvars.get("stream"): self.logger.error("OctoStreams are not currently supported")
"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) }, )
class Dogan(Plugin): """ Support for the live streams from Doğan Media Group channels """ url_re = re.compile( r""" https?://(?:www.)? (?:teve2.com.tr/(?:canli-yayin|filmler/.*|programlar/.*)| kanald.com.tr/.*| cnnturk.com/canli-yayin| dreamtv.com.tr/canli-yayin| dreamturk.com.tr/canli) """, re.VERBOSE) playerctrl_re = re.compile( r'''<div[^>]*?ng-controller=(?P<quote>["'])(?:Live)?PlayerCtrl(?P=quote).*?>''', re.DOTALL) data_id_re = re.compile( r'''data-id=(?P<quote>["'])(?P<id>\w+)(?P=quote)''') content_id_re = re.compile(r'"contentId", "(\w+)"') content_api = "/actions/content/media/{id}" alt_content_api = "/action/media/{id}" content_api_schema = validate.Schema({ "Id": validate.text, "Media": { "Link": { "DefaultServiceUrl": validate.url(), validate.optional("ServiceUrl"): validate.url(), "SecurePath": validate.text, } } }) @classmethod def can_handle_url(cls, url): return cls.url_re.match(url) is not None def _get_content_id(self): res = http.get(self.url) # find the PlayerCtrl div player_ctrl_m = self.playerctrl_re.search(res.text) if player_ctrl_m: # extract the content id from the player control data player_ctrl_div = player_ctrl_m.group(0) content_id_m = self.data_id_re.search(player_ctrl_div) if content_id_m: return content_id_m.group("id") # use the fall back regex content_id_m = self.content_id_re.search(res.text) return content_id_m and content_id_m.group(1) def _get_hls_url(self, content_id): # make the api url relative to the current domain if "cnnturk" in self.url: self.logger.debug("Using alternative content API url") api_url = urljoin(self.url, self.alt_content_api.format(id=content_id)) else: api_url = urljoin(self.url, self.content_api.format(id=content_id)) apires = http.get(api_url) stream_data = http.json(apires, schema=self.content_api_schema) d = stream_data["Media"]["Link"] return urljoin((d["ServiceUrl"] or d["DefaultServiceUrl"]), d["SecurePath"]) def _get_streams(self): content_id = self._get_content_id() if content_id: self.logger.debug(u"Loading content: {}", content_id) hls_url = self._get_hls_url(content_id) return HLSStream.parse_variant_playlist(self.session, hls_url) else: self.logger.error(u"Could not find the contentId for this stream")
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.any(validate.text, None), "url": validate.url( scheme="http", path=validate.endswith(".m3u8") ),
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, }]) })
validate.transform(int)), "vid": int }) }) }, validate.get("data")) _plu_schema = validate.Schema({ "urls": [{ "securityUrl": validate.url(scheme=validate.any("rtmp", "http")), "resolution": validate.text, "ext": validate.text }] }) _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"
_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, })
from ACEStream.PluginsContainer.livestreamer.plugin import Plugin from ACEStream.PluginsContainer.livestreamer.plugin.api import http, validate from ACEStream.PluginsContainer.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"),
from ACEStream.PluginsContainer.livestreamer.plugin.api import http, validate from ACEStream.PluginsContainer.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): self.url = http.resolve_url(self.url)
_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):
_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": validate.any(float, int), "id": int, "parts": [{ "duration": validate.any(float, int), "id": int, "offset": validate.any(float, 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):
#-plugin-sig:aavGbgu25BH3tVqGAcLbnkvxoEd3w5BCl8DSx+1DnYg1Uc7gmHVfcBk11uJUqv4DT/MrleczvIlhXNcfrZY6svb4JAGptIzelQrxXrBUUyqnmA7LIByGFWurfVPLTrKv1NWWmurdO6O5IRFf675L3boLPajwpjzkSpJwtR44wl5+SfZ45I9Gr25Aq6VQC1qU7A1qSW9JhTSMcj9uFQ4JEC1AZQtlcuhnP1/Iwz4jjhMziIm2+RGTV2xBcbKI2YNWqsLRlqtT9sT099Eh28iiALeXmvyC5zvXaPvf0Rgz39b7kvSwL9ZAlt0TZwSk741Fg+j6x+9IWL06XgWkHcgUZg== import re from functools import partial from ACEStream.PluginsContainer.livestreamer.plugin.api import validate from ACEStream.PluginsContainer.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)
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)
}], }, 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: {
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)), }]),
_url_re = re.compile( "http(s)?://(\w+\.)?afreeca(tv)?.com/(?P<username>\w+)(/\d+)?") _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} params = {"uid": username} res = http.get(CHANNEL_INFO_URL, params=params, headers=headers) return http.json(res, schema=_channel_schema)
"<meta content=\"([^\"]+.m3u8)\" property=\"og:video\" />") _url_re = re.compile("http(s)?://(\w+\.)?livestation.com") _csrf_token_schema = validate.Schema(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 def can_handle_url(self, url): return _url_re.match(url) def _authenticate(self, email, password):
from ACEStream.PluginsContainer.livestreamer.compat import urljoin from ACEStream.PluginsContainer.livestreamer.plugin import Plugin from ACEStream.PluginsContainer.livestreamer.plugin.api import http, validate from ACEStream.PluginsContainer.livestreamer.plugin.api.utils import parse_json from ACEStream.PluginsContainer.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("playerUri"): validate.text, validate.optional("viewerPlusSwfUrl"): validate.url(scheme="http"), validate.optional("lsPlayerSwfUrl"): validate.text, 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"
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", []), )
#-plugin-sig:jMxqtYMgDlSOLXGENZQ9MHqkS5rEMAFmt6V4P+q+RIuaO/MdUkUfSYCib9qaIAZ7tV/zgq3NL6Ju8SObwKpZuSZN8T7nkuYn/krShb0WTIDOKzTP2r/GuXbfNcO15pZOL3rs5cFQmFNpdjJVkQNX8bh3zJnkdOGYEyiZAZAmyAeUF7wiuBayplvf/Enyu5cF1ucjY20hlkXQSzDuCRj+9ZfXQjybD2eph7Jl/RJcPB9gW57zLntqPnOH0MFV6mJb9q6HkKX5RDgUZC8RHusqm+mCio5EOMwu2AfzO28tDn2+sL57/RLlhO7UUDpa8UNh7BPB/tydTulXGElnVrWAPw== import re from ACEStream.PluginsContainer.livestreamer.compat import urlparse from ACEStream.PluginsContainer.livestreamer.plugin import Plugin from ACEStream.PluginsContainer.livestreamer.plugin.api import http, validate from ACEStream.PluginsContainer.livestreamer.stream import RTMPStream, HTTPStream, HLSStream from ACEStream.PluginsContainer.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)
"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):
class Euronews(Plugin): _url_re = re.compile("http(?:s)?://(\w+)\.?euronews.com/(live|.*)") _re_vod = re.compile( r'<meta\s+property="og:video"\s+content="(http.*?)"\s*/>') _live_api_url = "http://fr.euronews.com/api/watchlive.json" _live_schema = validate.Schema({u"url": validate.url()}) _stream_api_schema = validate.Schema({ u'status': u'ok', u'primary': { validate.text: { validate.optional(u'hls'): validate.url(), validate.optional(u'rtsp'): validate.url(scheme="rtsp") } }, validate.optional(u'backup'): { validate.text: { validate.optional(u'hls'): validate.url(), validate.optional(u'rtsp'): validate.url(scheme="rtsp") } } }) @classmethod def can_handle_url(cls, url): return cls._url_re.match(url) def _get_vod_stream(self): """ Find the VOD video url :return: video url """ res = 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_live_streams(self, language): """ Get the live stream in a particular language :param language: :return: """ res = http.get(self._live_api_url) live_res = http.json(res, schema=self._live_schema) api_res = http.get(live_res[u"url"]) stream_data = http.json(api_res, schema=self._stream_api_schema) # find the stream in the requested language if language in stream_data[u'primary']: playlist_url = stream_data[u'primary'][language][u"hls"] return HLSStream.parse_variant_playlist(self.session, playlist_url) def _get_streams(self): """ Find the streams for euronews :return: """ match = self._url_re.match(self.url) language, path = match.groups() # remap domain to language (default to english) language = { "www": "en", "": "en", "arabic": "ar" }.get(language, language) if path == "live": return self._get_live_streams(language) else: return self._get_vod_stream()
/(?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,
_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,