Ejemplo n.º 1
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,
            "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)
Ejemplo n.º 2
0
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:
Ejemplo n.º 3
0
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"))

Ejemplo n.º 4
0
_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
Ejemplo n.º 5
0
""", 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"): [{
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
_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)
Ejemplo n.º 8
0
    )?
""", 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,
            }],
        ),
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
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,
                "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):
Ejemplo n.º 11
0
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):
Ejemplo n.º 12
0
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
                },
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
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)
Ejemplo n.º 15
0
    )?
""", 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)
Ejemplo n.º 16
0
_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:
Ejemplo n.º 17
0
    )?
""", 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,
            }],
        ),
Ejemplo n.º 18
0
#!/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)
Ejemplo n.º 19
0
})
_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")
Ejemplo n.º 20
0
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,
            }]
        }
    },
Ejemplo n.º 21
0
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")
Ejemplo n.º 22
0
_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)
Ejemplo n.º 23
0
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":
Ejemplo n.º 24
0
    "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):
Ejemplo n.º 25
0
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={
Ejemplo n.º 26
0
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):
Ejemplo n.º 27
0
        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")
Ejemplo n.º 28
0
#!/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))
Ejemplo n.º 29
0
    {
        "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"))

Ejemplo n.º 30
0
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)
Ejemplo n.º 31
0
#!/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)
Ejemplo n.º 32
0
    "<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
                    }
                )
            )
Ejemplo n.º 33
0
_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)
Ejemplo n.º 34
0
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
Ejemplo n.º 35
0
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
Ejemplo n.º 37
0
        }
    },
    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(
Ejemplo n.º 38
0
#!/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))
Ejemplo n.º 39
0
_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):
Ejemplo n.º 40
0
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
Ejemplo n.º 41
0
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)
Ejemplo n.º 42
0
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,
                    }
                },
            ),
Ejemplo n.º 43
0
                    "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)
Ejemplo n.º 44
0
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":
Ejemplo n.º 45
0
            "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
            }]
Ejemplo n.º 46
0
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")]
        )
Ejemplo n.º 47
0
    {
        "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)
Ejemplo n.º 48
0
_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]
    }]
})

Ejemplo n.º 49
0
    }]
})
_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")
Ejemplo n.º 50
0
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")])
    }))
Ejemplo n.º 51
0
    (?:
        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)
Ejemplo n.º 52
0
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:
Ejemplo n.º 53
0
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"),
Ejemplo n.º 54
0
    },
    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(
    {
Ejemplo n.º 55
0
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":
Ejemplo n.º 56
0
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(