} _url_re = re.compile(""" http(s)?://(www\.)?douyutv.com /(?P<channel>[^/]+) """, re.VERBOSE) _room_schema = validate.Schema( { "data": validate.any(None, { "show_status": validate.all( validate.text, validate.transform(int) ), "rtmp_url": validate.text, "rtmp_live": validate.text, "rtmp_multi_bitrate": validate.all( validate.any([], { validate.text: validate.text }), validate.transform(dict) ) }) }, validate.get("data") ) class Douyutv(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url)
import re from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream _url_re = re.compile("http(s)?://chaturbate.com/[^/?&]+") _playlist_url_re = re.compile("html \+= \"src='(?P<url>[^']+)'\";") _schema = validate.Schema( validate.transform(_playlist_url_re.search), validate.any( None, validate.all( validate.get("url"), validate.url( scheme="http", path=validate.endswith(".m3u8") ) ) ) ) class Chaturbate(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams(self): playlist_url = http.get(self.url, schema=_schema) if not playlist_url:
from livestreamer.plugin.api.support_plugin import viasat STREAM_API_URL = "http://playapi.mtgx.tv/v3/videos/stream/{0}" _embed_url_re = re.compile( '<meta itemprop="embedURL" content="http://www.viagame.com/embed/video/([^"]+)"' ) _store_data_re = re.compile("window.fluxData\s*=\s*JSON.parse\(\"(.+)\"\);") _url_re = re.compile("http(s)?://(www\.)?viagame.com/channels/.+") _store_schema = validate.Schema( { "initialStoresData": [{ "instanceName": validate.text, "storeName": validate.text, "initialData": validate.any(dict, list) }] }, validate.get("initialStoresData")) _match_store_schema = validate.Schema( { "match": { "id": validate.text, "type": validate.text, "videos": [{ "id": validate.text, "play_id": validate.text, }] } }, validate.get("match"))
_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
""", re.VERBOSE) _live_schema = validate.Schema( { "livestream": [{ "media_is_live": validate.all(validate.text, validate.transform(int), validate.transform(bool)), "media_id": validate.text }], }, 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"): [{
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)
_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.filter(lambda s: s["quality"] != "adaptive") ) } ) }, validate.get("stream_data") ) _login_schema = validate.Schema({ "auth": validate.text, "expires": validate.all( validate.text, validate.transform(parse_timestamp)
)? """, 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: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, }], ),
BLOCK_TYPE_VIEWING_LIMIT = 1 BLOCK_TYPE_NO_SLOTS = 11 _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)
_url_re = re.compile( """ http(s)?://(www\.)?douyutv.com /(?P<channel>[^/]+) """, re.VERBOSE) _room_schema = validate.Schema( { "data": validate.any( None, { "show_status": validate.all(validate.text, validate.transform(int)), "rtmp_url": validate.text, "rtmp_live": validate.text, "rtmp_multi_bitrate": validate.all(validate.any([], {validate.text: validate.text}), validate.transform(dict)) }) }, validate.get("data")) class Douyutv(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) @classmethod def stream_weight(cls, stream):
from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream USER_AGENT = ( "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 " "(KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25") HEADERS = {"User-Agent": USER_AGENT} PLAYLIST_URL = "http://m.afreeca.com/live/stream/a/hls/broad_no/{broad_no}" BROAD_INFO_URL = "https://api.m.afreeca.com/broad/a/getbroadinfo" _broadcast_re = re.compile(r".+\/(\d+)\.gif") _url_re = re.compile("http(s)?://(\w+\.)?afreeca.com/(?P<username>\w+)") _broadcast_schema = validate.Schema( {"data": validate.any(None, { "broad_no": int, })}, validate.get("data")) class AfreecaTV(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_broadcast(self, username): data = {"szBjId": username} res = http.post(BROAD_INFO_URL, headers=HEADERS, data=data) return http.json(res, schema=_broadcast_schema) def _get_streams(self):
from livestreamer.compat import urlparse from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream, HTTPStream, RTMPStream SWF_URL = "http://www.arte.tv/player/v2/jwplayer6/mediaplayer.6.6.swf" _url_re = re.compile("http(s)?://(\w+\.)?arte.tv/") _json_re = re.compile("arte_vp_(?:live-)?url=(['\"])(.+?)\\1") _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 },
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): return _url_re.match(url)
import re from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import RTMPStream _url_re = re.compile("^http(s)?://(\w+\.)?furstre\.am/stream/.+") _stream_url_re = re.compile("<source src=\"([^\"]+)\"") _schema = validate.Schema( validate.transform(_stream_url_re.search), validate.any(None, validate.all(validate.get(1), validate.url(scheme="rtmp")))) class Furstream(Plugin): @classmethod def can_handle_url(cls, url): return _url_re.match(url) def _get_streams(self): stream_url = http.get(self.url, schema=_schema) if not stream_url: return stream = RTMPStream(self.session, { "rtmp": stream_url, "pageUrl": self.url, "live": True }) return dict(live=stream)
)? """, 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) streams = {} for url in res["urls"]: parsed = urlparse(url)
_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:
)? """, re.VERBOSE) _channel_id_re = re.compile("\"channelId\":(\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: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, }], ),
#!/usr/bin/env python import re from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream STREAM_INFO_URL = "http://lapi.cdn.tvplayer.com/tvplayer/stream/live/id/{id}" _url_re = re.compile(r"http://(?:www.)?tvplayer.com/watch/(.+)") _channel_map_re = re.compile(r'href="/watch/([a-z]+?)".*?img.*?src=".*?/(\d+).png"', re.S) _channel_schema = validate.Schema({"stream": validate.url(scheme=validate.any("http"))}) class TVPlayer(Plugin): @classmethod def can_handle_url(cls, url): match = _url_re.match(url) return match def _get_streams(self): url_match = _url_re.match(self.url) if url_match: # find the list of channels from the html in the page res = http.get(self.url) channel_map = dict(_channel_map_re.findall(res.text)) channel_id = channel_map.get(url_match.group(1)) # get the stream urls res = http.get(STREAM_INFO_URL.format(id=channel_id)) stream_data = http.json(res, schema=_channel_schema)
}) _channel_schema = validate.Schema({ validate.optional("stream"): validate.any([{ "name": validate.text, "url": validate.text, "streams": [ validate.any( { "chunkId": float, "chunkRange": { validate.text: validate.text }, "chunkTime": float, "offset": float, "offsetInMs": float, "streamName": validate.text, validate.optional("bitrate"): float, validate.optional("height"): float, validate.optional("description"): validate.text, validate.optional("isTranscoded"): bool }, { "streamName": validate.text, }) ] }], "offline") }) Chunk = namedtuple("Chunk", "num url offset")
from livestreamer.plugin.api.support_plugin import viasat STREAM_API_URL = "http://playapi.mtgx.tv/v3/videos/stream/{0}" _embed_url_re = re.compile( '<meta itemprop="embedURL" content="http://www.viagame.com/embed/video/([^"]+)"' ) _store_data_re = re.compile("window.fluxData\s*=\s*JSON.parse\(\"(.+)\"\);") _url_re = re.compile("http(s)?://(www\.)?viagame.com/channels/.+") _store_schema = validate.Schema( { "initialStoresData": [{ "instanceName": validate.text, "storeName": validate.text, "initialData": validate.any(dict, list) }] }, validate.get("initialStoresData") ) _match_store_schema = validate.Schema( { "match": { "id": validate.text, "type": validate.text, "videos": [{ "id": validate.text, "play_id": validate.text, }] } },
API_URL = "http://www.douyutv.com/api/client/room/{0}" _url_re = re.compile( """ http(s)?://(www\.)?douyutv.com /(?P<channel>[^/]+) """, re.VERBOSE) _room_schema = validate.Schema( { "data": validate.any( None, { "show_status": validate.all(validate.text, validate.transform(int)), "rtmp_url": validate.text, "rtmp_live": validate.text }) }, validate.get("data")) class Douyutv(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")
_token_schema = validate.Schema( { "token": validate.text }, validate.get("token") ) _schema = validate.Schema( validate.transform(_rtmp_re.search), validate.any( None, validate.all( validate.transform(methodcaller("groupdict")), { "rtmp_playpath": validate.text, "rtmp_url": validate.all( validate.transform(methodcaller("replace", "\\/", "/")), validate.url(scheme="rtmp"), ), "swf_url": validate.url(scheme="http"), "token_url": validate.url(scheme="http") } ) ) ) class ILive(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url)
from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HTTPStream, RTMPStream SWF_URL = "http://euronews.com/media/player_live_1_14.swf" API_URL_LIVE = "http://euronews.hexaglobe.com/json/" _url_re = re.compile("http(s)?://(\w+\.)?euronews.com") _lang_re = re.compile("EN.lang\s+= \"([^\"]+)\";") _live_check_re = re.compile( "swfobject.embedSWF\(\"[^\"]+\", \"streaming-live-player\",") _video_re = re.compile( "{file: \"(?P<url>[^\"]+)\", label: \"(?P<name>[^\"]+)\"}") _live_schema = validate.Schema({ validate.any("primary", "secondary"): { 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":
"web_medium": 10, "web_high": 11, "web_hd": 12 } _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):
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={
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):
viasat4play | play.tv3 ) \. (?: dk|ee|lt|lv|no|se|com ) (/.+?/|/embed\?id=) (?P<stream_id>\d+) """, re.VERBOSE) _stream_schema = validate.Schema( { "streams": validate.all( {validate.text: validate.any(validate.text, int, None)}, validate.filter(lambda k, v: isinstance(v, validate.text))) }, validate.get("streams")) class Viasat(Plugin): @classmethod def can_handle_url(cls, url): return _url_re.match(url) def _get_swf_url(self): res = http.get(self.url) match = _swf_url_re.search(res.text) if not match: raise PluginError("Unable to find SWF URL in the HTML")
#!/usr/bin/env python import re from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream USER_AGENT_STRING = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/43.0.2357.65 Safari/537.36") STREAM_INFO_URL = "http://lapi.cdn.tvplayer.com/tvplayer/stream/live/id/{id}" _url_re = re.compile(r"http://(?:www.)?tvplayer.com/watch/(.+)") _channel_map_re = re.compile( r'href="/watch/([a-z]+?)".*?img.*?src=".*?/(\d+).png"', re.S) _channel_schema = validate.Schema( {"stream": validate.url(scheme=validate.any("http"))}) class TVPlayer(Plugin): @classmethod def can_handle_url(cls, url): match = _url_re.match(url) return match def _get_streams(self): url_match = _url_re.match(self.url) if url_match: # find the list of channels from the html in the page res = http.get(self.url) channel_map = dict(_channel_map_re.findall(res.text)) channel_id = channel_map.get(url_match.group(1))
{ "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, }) _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"))
from livestreamer.plugin.api.utils import parse_query from livestreamer.stream import RTMPStream 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)
#!/usr/bin/env python import re from livestreamer.plugin import Plugin from livestreamer.plugin.api import http from livestreamer.stream import HLSStream from livestreamer.plugin.api import validate STREAM_INFO_URL = "http://dinamics.ccma.cat/pvideo/media.jsp?media=video&version=0s&idint={ident}&profile=pc&desplacament=0" _url_re = re.compile(r"http://(?:www.)?ccma.cat/tv3/directe/(.+?)/") _media_schema = validate.Schema({ "geo": validate.text, "url": validate.url(scheme=validate.any("http")) }) _channel_schema = validate.Schema({ "media": validate.any([_media_schema], _media_schema) }) class TV3Cat(Plugin): @classmethod def can_handle_url(self, url): match = _url_re.match(url) return match def _get_streams(self): match = _url_re.match(self.url) if match: ident = match.group(1) data_url = STREAM_INFO_URL.format(ident=ident)
"<embed width=\"486\" height=\"326\" flashvars=\"([^\"]+)\"" ) _live_schema = validate.Schema({ "streams": [{ "name": validate.text, "quality": validate.text, "url": validate.url(scheme="rtmp") }] }) _schema = validate.Schema( 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 } ) )
USER_AGENT = ( "Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 " "(KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25" ) HEADERS = {"User-Agent": USER_AGENT} PLAYLIST_URL = "http://m.afreeca.com/live/stream/a/hls/broad_no/{broad_no}" BROAD_INFO_URL = "https://api.m.afreeca.com/broad/a/getbroadinfo" _broadcast_re = re.compile(r".+\/(\d+)\.gif") _url_re = re.compile("http(s)?://(\w+\.)?afreeca.com/(?P<username>\w+)") _broadcast_schema = validate.Schema( { "data": validate.any( None, { "broad_no": int, } ) }, validate.get("data") ) class AfreecaTV(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_broadcast(self, username): data = { "szBjId": username
STREAM_WEIGHTS = {"low": 540, "middle": 720, "source": 1080} _url_re = re.compile( """ http(s)?://(www\.)?douyu.com /(?P<channel>[^/]+) """, re.VERBOSE) _json_re = re.compile(r"var\s*\$ROOM\s*=\s*({.+?});") _room_id_schema = validate.Schema( validate.all( validate.transform(_json_re.search), validate.any( None, validate.all(validate.get(1), validate.transform(parse_json), { "room_id": validate.any(validate.text, validate.transform(int)) })))) _room_schema = validate.Schema( { "data": validate.any(None, { "show_status": validate.all(validate.text, validate.transform(int)) }) }, validate.get("data")) _lapi_schema = validate.Schema( { "data":
def test_any(self): assert validate(any(int, dict), 5) == 5 assert validate(any(int, dict), {}) == {} assert validate(any(int), 4) == 4
} }, 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, } ) _viewer_info_schema = validate.Schema( { validate.optional("login"): validate.text }, validate.get("login") ) _viewer_token_schema = validate.Schema(
#!/usr/bin/env python import re from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream USER_AGENT_STRING = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/43.0.2357.65 Safari/537.36") STREAM_INFO_URL = "http://lapi.cdn.tvplayer.com/tvplayer/stream/live/id/{id}" _url_re = re.compile(r"http://(?:www.)?tvplayer.com/watch/(.+)") _channel_map_re = re.compile(r'href="/watch/([a-z]+?)".*?img.*?src=".*?/(\d+).png"', re.S) _channel_schema = validate.Schema({ "stream": validate.url(scheme=validate.any("http")) }) class TVPlayer(Plugin): @classmethod def can_handle_url(cls, url): match = _url_re.match(url) return match def _get_streams(self): url_match = _url_re.match(self.url) if url_match: # find the list of channels from the html in the page res = http.get(self.url) channel_map = dict(_channel_map_re.findall(res.text)) channel_id = channel_map.get(url_match.group(1))
_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):
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 livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HTTPStream, RTMPStream SWF_URL = "http://euronews.com/media/player_live_1_14.swf" API_URL_LIVE = "http://euronews.hexaglobe.com/json/" _url_re = re.compile("http(s)?://(\w+\.)?euronews.com") _lang_re = re.compile("EN.lang\s+= \"([^\"]+)\";") _live_check_re = re.compile("swfobject.embedSWF\(\"[^\"]+\", \"streaming-live-player\",") _video_re = re.compile("{file: \"(?P<url>[^\"]+)\", label: \"(?P<name>[^\"]+)\"}") _live_schema = validate.Schema({ validate.any("primary", "secondary"): { 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)
import re from itertools import chain from livestreamer.compat import urlparse from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream, HTTPStream, RTMPStream SWF_URL = "http://www.arte.tv/player/v2/jwplayer6/mediaplayer.6.6.swf" _url_re = re.compile("http(s)?://(\w+\.)?arte.tv/") _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, } }, ),
"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, "fragments": [[int, float]], "template": validate.text}) _vod_manifest_schema = validate.Schema( {"alternates": [{"height": int, "template": validate.text, validate.optional("failover"): [validate.text]}]} ) class DailyMotion(Plugin): @classmethod def can_handle_url(self, url): return _url_re.match(url) def _get_streams_from_media(self, media_id): res = http.get(STREAM_INFO_URL.format(media_id), cookies=COOKIES) media = http.json(res, schema=_media_schema)
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":
"media_is_live": validate.all( validate.text, validate.transform(int), validate.transform(bool) ), "media_id": validate.text }], }, 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 }]
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": { "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} res = http.post(CHANNEL_INFO_URL, data=params, headers=headers)
_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, "fragments": [[int, float]], "template": validate.text }) _vod_manifest_schema = validate.Schema({ "alternates": [{ "height": int, "template": validate.text, validate.optional("failover"): [validate.text] }] })
}] }) _channel_schema = validate.Schema({ validate.optional("stream"): validate.any([{ "name": validate.text, "url": validate.text, "streams": [ validate.any({ "chunkId": float, "chunkRange": {validate.text: validate.text}, "chunkTime": float, "offset": float, "offsetInMs": float, "streamName": validate.text, validate.optional("bitrate"): float, validate.optional("height"): float, validate.optional("description"): validate.text, validate.optional("isTranscoded"): bool }, { "streamName": validate.text, }) ] }], "offline" ) }) Chunk = namedtuple("Chunk", "num url offset")
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"), [validate.get("src")]) }))
(?: tv(3|6|8|10)play | viasat4play ) \. (?: dk|ee|lt|lv|no|se|com ) /.+/ (?P<stream_id>\d+) """, re.VERBOSE) _stream_schema = validate.Schema( { "streams": validate.all( {validate.text: validate.any(validate.text, int, None)}, validate.filter(lambda k, v: isinstance(v, validate.text)) ) }, validate.get("streams") ) class Viasat(Plugin): @classmethod def can_handle_url(cls, url): return _url_re.match(url) def _get_swf_url(self): res = http.get(self.url) match = _swf_url_re.search(res.text)
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 else:
from livestreamer.stream import RTMPStream VIEW_LIVE_API_URL = "http://api.afreeca.tv/live/view_live.php" _url_re = re.compile("http(s)?://(\w+\.)?afreeca.tv/(?P<channel>[\w\-_]+)") _flashvars_re = re.compile('<param name="flashvars" value="([^"]+)" />') _flashvars_schema = validate.Schema( validate.transform(_flashvars_re.findall), validate.get(0), validate.transform(parse_query), validate.any( { "s": validate.text, "id": validate.text }, {} ) ) _view_live_schema = validate.Schema( { "channel": { "strm": [{ "brt": validate.text, "bps": validate.text, "purl": validate.url(scheme="rtmp") }] }, }, validate.get("channel"),
}, 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.text, "upkeep": validate.any("pass", "fail", None) }] }, "restrictions": { validate.text: validate.text }, "start_offset": int, "end_offset": int, } ) _viewer_info_schema = validate.Schema( { validate.optional("login"): validate.text }, validate.get("login") ) _viewer_token_schema = validate.Schema( {
from itertools import chain from livestreamer.compat import urlparse from livestreamer.plugin import Plugin from livestreamer.plugin.api import http, validate from livestreamer.stream import HLSStream, HTTPStream, RTMPStream SWF_URL = "http://www.arte.tv/player/v2/jwplayer6/mediaplayer.6.6.swf" _url_re = re.compile("http(s)?://(\w+\.)?arte.tv/") _json_re = re.compile("arte_vp_(?:live-)?url=(['\"])(.+?)\\1") _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":
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/") _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(