Exemple #1
0
class Gulli(Plugin):
    LIVE_PLAYER_URL = 'https://replay.gulli.fr/jwplayer/embedstreamtv'
    VOD_PLAYER_URL = 'https://replay.gulli.fr/jwplayer/embed/{0}'

    _playlist_re = re.compile(r'sources: (\[.+?\])', re.DOTALL)
    _vod_video_index_re = re.compile(
        r'jwplayer\(idplayer\).playlistItem\((?P<video_index>[0-9]+)\)')
    _mp4_bitrate_re = re.compile(r'.*_(?P<bitrate>[0-9]+)\.mp4')

    _video_schema = validate.Schema(
        validate.all(
            validate.transform(
                lambda x: re.sub(r'"?file"?:\s*[\'"](.+?)[\'"],?',
                                 r'"file": "\1"',
                                 x,
                                 flags=re.DOTALL)),
            validate.transform(
                lambda x: re.sub(r'"?\w+?"?:\s*function\b.*?(?<={).*(?=})',
                                 "",
                                 x,
                                 flags=re.DOTALL)), validate.parse_json(),
            [validate.Schema({'file': validate.url()})]))

    def _get_streams(self):
        video_id = self.match.group('video_id')
        if video_id is not None:
            # VOD
            live = False
            player_url = self.VOD_PLAYER_URL.format(video_id)
        else:
            # Live
            live = True
            player_url = self.LIVE_PLAYER_URL

        res = self.session.http.get(player_url)
        playlist = re.findall(self._playlist_re, res.text)
        index = 0
        if not live:
            # Get the index for the video on the playlist
            match = self._vod_video_index_re.search(res.text)
            if match is None:
                return
            index = int(match.group('video_index'))

        if not playlist:
            return
        videos = self._video_schema.validate(playlist[index])

        for video in videos:
            video_url = video['file']

            # Ignore non-supported MSS streams
            if 'isml/Manifest' in video_url:
                continue

            try:
                if '.m3u8' in video_url:
                    yield from HLSStream.parse_variant_playlist(
                        self.session, video_url).items()
                elif '.mp4' in video_url:
                    match = self._mp4_bitrate_re.match(video_url)
                    if match is not None:
                        bitrate = '%sk' % match.group('bitrate')
                    else:
                        bitrate = 'vod'
                    yield bitrate, HTTPStream(self.session, video_url)
            except OSError as err:
                if '403 Client Error' in str(err):
                    log.error(
                        'Failed to access stream, may be due to geo-restriction'
                    )
                raise
from streamlink.plugin.api import http, validate
from streamlink.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)
        match = _url_re.match(self.url)
        parsed = urlparse(self.url)
        if parsed.fragment:
            channel_id = parsed.fragment
Exemple #3
0
import re

from streamlink.plugin import Plugin
from streamlink.plugin.api import validate


_url_re = re.compile(r'http(s)?://www\.skai(?:tv)?.gr/.*')
_api_url = "http://www.skaitv.gr/json/live.php"
_api_res_schema = validate.Schema(validate.all(
    validate.get("now"),
    {
        "livestream": validate.url()
    },
    validate.get("livestream"))
)


class Skai(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    def _get_streams(self):
        api_res = self.session.http.get(_api_url)
        yt_url = self.session.http.json(api_res, schema=_api_res_schema)
        if yt_url:
            return self.session.streams(yt_url)


__plugin__ = Skai
    (?:
        /live/[^/]+
    )?
    (?:
        /video/\d+/[^/]+
    )?
""", re.VERBOSE)
_file_re = re.compile("\"?file\"?:\s+['\"]([^'\"]+)['\"]")
_swf_url_re = re.compile("swfobject.embedSWF\(\"([^\"]+)\",")

_schema = validate.Schema(
    validate.union({
        "urls": validate.all(
            validate.transform(_file_re.findall),
            validate.map(unquote),
            [validate.url()]
        ),
        "swf": validate.all(
            validate.transform(_swf_url_re.search),
            validate.any(
                None,
                validate.all(
                    validate.get(1),
                    validate.url(
                        scheme="http",
                        path=validate.endswith("swf")
                    )
                )
            )
        )
    })
Exemple #5
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(
_url_re = re.compile(
    r'http(s)?://([^.]*.)?ceskatelevize.cz'
)
_player_re = re.compile(
    r'ivysilani/embed/iFramePlayer[^"]+'
)
_hash_re = re.compile(
    r'hash:"([0-9a-z]+)"'
)
_playlist_info_re = re.compile(
    r'{"type":"([a-z]+)","id":"([0-9]+)"'
)
_playlist_url_schema = validate.Schema({
    validate.optional("streamingProtocol"): validate.text,
    "url": validate.any(
        validate.url(),
        "Error",
        "error_region"
    )
})
_playlist_schema = validate.Schema({
    "playlist": [{
        validate.optional("type"): validate.text,
        "streamUrls": {
            "main": validate.url(),
        }
    }]
})

log = logging.getLogger(__name__)
Exemple #7
0
from streamlink.plugin.api import http, validate
from streamlink.stream import RTMPStream, HLSStream

RUURL = "b=chrome&p=win&v=56&f=0&d=1"

_url_re = re.compile(r"https?://www.rtvs.sk/televizia/live-[\w-]+")
_playlist_url_re = re.compile(r'"playlist": "([^"]+)"')

_playlist_schema = validate.Schema(
    [
        {
            "sources": [
                validate.any(
                    {
                        "type": "dash",
                        "file": validate.url(scheme="http")
                    }, {
                        "type": "hls",
                        "file": validate.url(scheme="http")
                    }, {
                        "type": "rtmp",
                        "file": validate.text,
                        "streamer": validate.url(scheme="rtmp")
                    }
                )
            ]
        }
    ],
    validate.get(0),
    validate.get("sources")
)
Exemple #8
0
    def _get_streams(self):
        self.id = self.session.http.get(
            self.url,
            schema=validate.Schema(
                validate.transform(
                    re.compile(r"\bdata-setup='({.+?})'", re.DOTALL).search),
                validate.any(
                    None,
                    validate.all(
                        validate.get(1), validate.parse_json(), {
                            "idAsset":
                            validate.any(
                                int, validate.all(str,
                                                  validate.transform(int))),
                        }, validate.get("idAsset"))),
            ))
        if not self.id:
            return

        urls = self.session.http.get(
            self.URL_VIDEOS.format(id=self.id),
            schema=validate.Schema(
                validate.transform(ZTNR.translate),
                validate.transform(list),
                [(str, validate.url())],
            ),
        )

        url = next(
            (url for _, url in urls if urlparse(url).path.endswith(".m3u8")),
            None)
        if not url:
            url = next(
                (url
                 for _, url in urls if urlparse(url).path.endswith(".mp4")),
                None)
            if url:
                yield "vod", HTTPStream(self.session, url)
            return

        streams = HLSStream.parse_variant_playlist(self.session, url).items()

        if self.options.get("mux-subtitles"):
            subs = self.session.http.get(
                self.URL_SUBTITLES.format(id=self.id),
                schema=validate.Schema(
                    validate.parse_json(),
                    {
                        "page": {
                            "items": [{
                                "lang": str,
                                "src": validate.url(),
                            }]
                        }
                    },
                    validate.get(("page", "items")),
                ),
            )
            if subs:
                subtitles = {
                    s["lang"]:
                    HTTPStream(self.session,
                               update_scheme("https://", s["src"], force=True))
                    for s in subs
                }
                for quality, stream in streams:
                    yield quality, MuxedStream(self.session,
                                               stream,
                                               subtitles=subtitles)
                return

        yield from streams
Exemple #9
0
_channel_schema = validate.Schema(
    {
        "CHANNEL": {
            "RESULT": validate.transform(int),
            validate.optional("BPWD"): validate.text,
            validate.optional("BNO"): validate.text,
            validate.optional("RMD"): validate.text,
            validate.optional("AID"): validate.text,
            validate.optional("CDN"): validate.text
        }
    }, validate.get("CHANNEL"))

_stream_schema = validate.Schema({
    validate.optional("view_url"):
    validate.url(scheme=validate.any("rtmp", "http")),
    "stream_status":
    validate.text
})


class AfreecaTV(Plugin):
    login_url = "https://member.afreecatv.com:8111/login/LoginAction.php"

    arguments = PluginArguments(
        PluginArgument(
            "username",
            requires=["password"],
            metavar="USERNAME",
            help="The username used to register with afreecatv.com."),
        PluginArgument(
Exemple #10
0
class Mixer(Plugin):
    api_url = "https://mixer.com/api/v1/{type}/{id}"

    _vod_schema = validate.Schema(
        {
            "state": "AVAILABLE",
            "vods": [{
                "baseUrl": validate.url(),
                "data": validate.any(None, {
                    "Height": int
                }),
                "format": validate.text
            }]
        },
        validate.get("vods"),
        validate.filter(lambda x: x["format"] in ("raw", "hls")),
        [validate.union({
            "url": validate.get("baseUrl"),
            "format": validate.get("format"),
            "height": validate.all(validate.get("data"), validate.get("Height"))
        })])

    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    def _get_api_res(self, api_type, api_id):
        try:
            res = http.get(self.api_url.format(type=api_type, id=api_id))
            return res
        except Exception as e:
            if "404" in str(e):
                self.logger.error("invalid {0} - {1}".format(api_type, api_id))
            elif "429" in str(e):
                self.logger.error("Too Many Requests, API rate limit exceeded.")
            raise NoStreamsError(self.url)

    def _get_vod_stream(self, vod_id):
        res = self._get_api_res("recordings", vod_id)

        for sdata in http.json(res, schema=self._vod_schema):
            if sdata["format"] == "hls":
                hls_url = urljoin(sdata["url"], "manifest.m3u8")
                yield "{0}p".format(sdata["height"]), HLSStream(self.session, hls_url)

    def _get_live_stream(self, channel):
        res = self._get_api_res("channels", channel)

        channel_info = http.json(res)
        if not channel_info["online"]:
            return

        user_id = channel_info["id"]
        hls_url = self.api_url.format(type="channels", id="{0}/manifest.m3u8".format(user_id))
        for s in HLSStream.parse_variant_playlist(self.session, hls_url).items():
            yield s

    def _get_streams(self):
        params = dict(parse_qsl(urlparse(self.url).query))
        vod_id = params.get("vod")
        match = _url_re.match(self.url)
        channel = match.group("channel")

        if vod_id:
            self.logger.debug("Looking for VOD {0} from channel: {1}", vod_id, channel)
            return self._get_vod_stream(vod_id)
        else:
            self.logger.debug("Looking for channel: {0}", channel)
            return self._get_live_stream(channel)
Exemple #11
0
class Booyah(Plugin):
    auth_api_url = 'https://booyah.live/api/v3/auths/sessions'
    vod_api_url = 'https://booyah.live/api/v3/playbacks/{0}'
    live_api_url = 'https://booyah.live/api/v3/channels/{0}'
    streams_api_url = 'https://booyah.live/api/v3/channels/{0}/streams'

    auth_schema = validate.Schema({
        'expiry_time': int,
        'uid': int,
    })

    vod_schema = validate.Schema({
        'user': {
            'nickname': validate.text,
        },
        'playback': {
            'name':
            validate.text,
            'endpoint_list': [{
                'stream_url':
                validate.url(),
                'resolution':
                validate.all(
                    int,
                    validate.transform(lambda x: '{}p'.format(x)),
                ),
            }],
        },
    })

    live_schema = validate.Schema({
        'user': {
            'nickname': validate.text,
        },
        'channel': {
            'channel_id': int,
            'name': validate.text,
            'is_streaming': bool,
            validate.optional('hostee'): {
                'channel_id': int,
                'nickname': validate.text,
            },
        },
    })

    @classmethod
    def stream_weight(cls, stream):
        if stream == "source":
            return sys.maxsize, "source"
        return super(Booyah, cls).stream_weight(stream)

    def do_auth(self):
        res = self.session.http.post(self.auth_api_url)
        self.session.http.json(res, self.auth_schema)

    def get_vod(self, id):
        res = self.session.http.get(self.vod_api_url.format(id))
        user_data = self.session.http.json(res, schema=self.vod_schema)

        self.author = user_data['user']['nickname']
        self.category = 'VOD'
        self.title = user_data['playback']['name']

        for stream in user_data['playback']['endpoint_list']:
            if stream['stream_url'].endswith('.mp4'):
                yield stream['resolution'], HTTPStream(
                    self.session,
                    stream['stream_url'],
                )
            else:
                yield stream['resolution'], HLSStream(
                    self.session,
                    stream['stream_url'],
                )

    def get_live(self, id):
        res = self.session.http.get(self.live_api_url.format(id))
        user_data = self.session.http.json(res, schema=self.live_schema)

        if user_data['channel']['is_streaming']:
            self.category = 'Live'
            stream_id = user_data['channel']['channel_id']
        elif 'hostee' in user_data['channel']:
            self.category = 'Hosted by {}'.format(
                user_data["channel"]["hostee"]["nickname"])
            stream_id = user_data['channel']['hostee']['channel_id']
        else:
            log.info('User is offline')
            return

        self.author = user_data['user']['nickname']
        self.title = user_data['channel']['name']

        res = self.session.http.get(self.streams_api_url.format(stream_id))
        streams = self.session.http.json(res,
                                         schema=validate.Schema({
                                             "default_mirror":
                                             validate.text,
                                             "mirror_list": [{
                                                 "name":
                                                 validate.text,
                                                 "url_domain":
                                                 validate.url(),
                                             }],
                                             "source_stream_url_path":
                                             validate.text,
                                             "stream_addr_list": [{
                                                 "resolution":
                                                 validate.text,
                                                 "url_path":
                                                 validate.text,
                                             }],
                                         }))

        mirror = (next(
            filter(lambda item: item["name"] == streams["default_mirror"],
                   streams["mirror_list"]), None)
                  or next(iter(streams["mirror_list"]), None))
        if not mirror:
            return

        auto = next(
            filter(lambda item: item["resolution"] == "Auto",
                   streams["stream_addr_list"]), None)
        if auto:
            for s in HLSStream.parse_variant_playlist(
                    self.session,
                    urljoin(mirror["url_domain"], auto["url_path"])).items():
                yield s

        if streams["source_stream_url_path"]:
            yield "source", HLSStream(
                self.session,
                urljoin(mirror["url_domain"],
                        streams["source_stream_url_path"]))

    def _get_streams(self):
        self.do_auth()

        url_data = self.match.groupdict()
        log.debug('ID={}'.format(url_data["id"]))

        if not url_data['type'] or url_data['type'] == 'channels':
            log.debug('Type=Live')
            return self.get_live(url_data['id'])
        else:
            log.debug('Type=VOD')
            return self.get_vod(url_data['id'])
Exemple #12
0
class Dogan(Plugin):
    """
    Support for the live streams from Doğan Media Group channels
    """
    url_re = re.compile(
        r"""
        https?://(?:www\.)?
        (?:cnnturk\.com/(?:action/embedvideo/.*|canli-yayin|tv-cnn-turk|video/.*)|
           dreamturk\.com\.tr/(?:canli|canli-yayin-izle|dream-turk-ozel/.*|programlar/.*)|
           dreamtv\.com\.tr/dream-ozel/.*|
           kanald\.com\.tr/.*|
           teve2\.com\.tr/(?:canli-yayin|diziler/.*|embed/.*|filmler/.*|programlar/.*))
    """, re.VERBOSE)
    playerctrl_re = re.compile(r'''<div\s+id="video-element".*?>''', re.DOTALL)
    data_id_re = re.compile(
        r'''data-id=(?P<quote>["'])/?(?P<id>\w+)(?P=quote)''')
    content_id_re = re.compile(r'"content[Ii]d",\s*"(\w+)"')
    item_id_re = re.compile(r"_itemId\s+=\s+'(\w+)';")
    content_api = "/actions/media?id={id}"
    dream_api = "/actions/content/media/{id}"
    new_content_api = "/action/media/{id}"
    content_api_schema = validate.Schema(
        {
            "data": {
                "id": str,
                "media": {
                    "link": {
                        validate.optional("defaultServiceUrl"):
                        validate.any(validate.url(), ""),
                        validate.optional("serviceUrl"):
                        validate.any(validate.url(), ""),
                        "securePath":
                        str,
                    },
                },
            },
        },
        validate.get("data"),
        validate.get("media"),
        validate.get("link"),
    )
    new_content_api_schema = validate.Schema(
        {
            "Media": {
                "Link": {
                    "ContentId":
                    str,
                    validate.optional("DefaultServiceUrl"):
                    validate.any(validate.url(), ""),
                    validate.optional("ServiceUrl"):
                    validate.any(validate.url(), ""),
                    "SecurePath":
                    str,
                },
            },
        },
        validate.get("Media"),
        validate.get("Link"),
    )

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def _get_content_id(self):
        res = self.session.http.get(self.url)
        # find the contentId
        content_id_m = self.content_id_re.search(res.text)
        if content_id_m:
            log.debug("Found contentId by contentId regex")
            return content_id_m.group(1)

        # 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:
                log.debug("Found contentId by player data-id regex")
                return content_id_m.group("id")

        # find the itemId var
        item_id_m = self.item_id_re.search(res.text)
        if item_id_m:
            log.debug("Found contentId by itemId regex")
            return item_id_m.group(1)

    def _get_new_content_hls_url(self, content_id, api_url):
        log.debug("Using new content API url")
        d = self.session.http.get(
            urljoin(self.url, api_url.format(id=content_id)))
        d = self.session.http.json(d, schema=self.new_content_api_schema)

        if d["DefaultServiceUrl"] == "https://www.kanald.com.tr":
            self.url = d["DefaultServiceUrl"]
            return self._get_content_hls_url(content_id)
        else:
            if d["SecurePath"].startswith("http"):
                return d["SecurePath"]
            else:
                return urljoin((d["ServiceUrl"] or d["DefaultServiceUrl"]),
                               d["SecurePath"])

    def _get_content_hls_url(self, content_id):
        d = self.session.http.get(
            urljoin(self.url, self.content_api.format(id=content_id)))
        d = self.session.http.json(d, schema=self.content_api_schema)

        return urljoin((d["serviceUrl"] or d["defaultServiceUrl"]),
                       d["securePath"])

    def _get_hls_url(self, content_id):
        # make the api url relative to the current domain
        if "cnnturk.com" in self.url or "teve2.com.tr" in self.url:
            return self._get_new_content_hls_url(content_id,
                                                 self.new_content_api)
        elif "dreamturk.com.tr" in self.url or "dreamtv.com.tr" in self.url:
            return self._get_new_content_hls_url(content_id, self.dream_api)
        else:
            return self._get_content_hls_url(content_id)

    def _get_streams(self):
        content_id = self._get_content_id()
        if content_id:
            log.debug(f"Loading content: {content_id}")
            hls_url = self._get_hls_url(content_id)
            return HLSStream.parse_variant_playlist(self.session, hls_url)
        else:
            log.error("Could not find the contentId for this stream")
Exemple #13
0
USER_INFO_URL = "https://api.dailymotion.com/user/{0}"

_media_schema = validate.Schema(
    validate.any(
        {"error": {
            "title": validate.text
        }},
        # "stream_chromecast_url": validate.url(),
        # Chromecast URL is already available in qualities subdict
        {
            "qualities":
            validate.any({
                validate.text:
                validate.all([{
                    "type": validate.text,
                    "url": validate.url()
                }])
            })
        }))
_live_id_schema = validate.Schema({
    "total":
    int,
    "list":
    validate.any([], [{
        "id": validate.text
    }])
})


@pluginmatcher(
    re.compile(
Exemple #14
0
            "channel" : validate.any(None, {
                "id" : validate.all(
                    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,
Exemple #15
0
    https://www\.kingkong\.com\.tw/
    (?:
        video/(?P<vid>[0-9]+G[0-9A-Za-z]+)|
        (?P<channel>[0-9]+)
    )
""", re.VERBOSE)

_room_schema = validate.Schema(
    {
        "data": {
            "live_info": {
                "live_status": int,
                "stream_items": [{
                    "title": validate.text,
                    "video": validate.any('', validate.url(
                        scheme="https",
                        path=validate.endswith(".flv")
                    ))
                }]
            }
        }
    },
    validate.get("data")
)

_vod_schema = validate.Schema(
    {
        "data": {
            "live_info": {
                "video": validate.text
            }
        }
Exemple #16
0
class Dogan(Plugin):
    playerctrl_re = re.compile(r'''<div\s+id="video-element".*?>''', re.DOTALL)
    data_id_re = re.compile(
        r'''data-id=(?P<quote>["'])/?(?P<id>\w+)(?P=quote)''')
    content_id_re = re.compile(r'"content[Ii]d",\s*"(\w+)"')
    item_id_re = re.compile(r"_itemId\s+=\s+'(\w+)';")
    content_api = "/actions/media?id={id}"
    dream_api = "/actions/content/media/{id}"
    new_content_api = "/action/media/{id}"
    content_api_schema = validate.Schema(
        {
            "data": {
                "id": validate.text,
                "media": {
                    "link": {
                        validate.optional("defaultServiceUrl"):
                        validate.any(validate.url(), ""),
                        validate.optional("serviceUrl"):
                        validate.any(validate.url(), ""),
                        "securePath":
                        validate.text,
                    },
                },
            },
        },
        validate.get("data"),
        validate.get("media"),
        validate.get("link"),
    )
    new_content_api_schema = validate.Schema(
        {
            "Media": {
                "Link": {
                    "ContentId":
                    validate.text,
                    validate.optional("DefaultServiceUrl"):
                    validate.any(validate.url(), ""),
                    validate.optional("ServiceUrl"):
                    validate.any(validate.url(), ""),
                    "SecurePath":
                    validate.text,
                },
            },
        },
        validate.get("Media"),
        validate.get("Link"),
    )

    def _get_content_id(self):
        res = self.session.http.get(self.url)
        # find the contentId
        content_id_m = self.content_id_re.search(res.text)
        if content_id_m:
            log.debug("Found contentId by contentId regex")
            return content_id_m.group(1)

        # 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:
                log.debug("Found contentId by player data-id regex")
                return content_id_m.group("id")

        # find the itemId var
        item_id_m = self.item_id_re.search(res.text)
        if item_id_m:
            log.debug("Found contentId by itemId regex")
            return item_id_m.group(1)

    def _get_new_content_hls_url(self, content_id, api_url):
        log.debug("Using new content API url")
        d = self.session.http.get(
            urljoin(self.url, api_url.format(id=content_id)))
        d = self.session.http.json(d, schema=self.new_content_api_schema)

        if d["DefaultServiceUrl"] == "https://www.kanald.com.tr":
            self.url = d["DefaultServiceUrl"]
            return self._get_content_hls_url(content_id)
        else:
            if d["SecurePath"].startswith("http"):
                return d["SecurePath"]
            else:
                return urljoin((d["ServiceUrl"] or d["DefaultServiceUrl"]),
                               d["SecurePath"])

    def _get_content_hls_url(self, content_id):
        d = self.session.http.get(
            urljoin(self.url, self.content_api.format(id=content_id)))
        d = self.session.http.json(d, schema=self.content_api_schema)

        return urljoin((d["serviceUrl"] or d["defaultServiceUrl"]),
                       d["securePath"])

    def _get_hls_url(self, content_id):
        # make the api url relative to the current domain
        if "cnnturk.com" in self.url or "teve2.com.tr" in self.url:
            return self._get_new_content_hls_url(content_id,
                                                 self.new_content_api)
        elif "dreamturk.com.tr" in self.url or "dreamtv.com.tr" in self.url:
            return self._get_new_content_hls_url(content_id, self.dream_api)
        else:
            return self._get_content_hls_url(content_id)

    def _get_streams(self):
        content_id = self._get_content_id()
        if content_id:
            log.debug(u"Loading content: {0}".format(content_id))
            hls_url = self._get_hls_url(content_id)
            return HLSStream.parse_variant_playlist(self.session, hls_url)
        else:
            log.error(u"Could not find the contentId for this stream")
Exemple #17
0
_media_schema = validate.Schema({
    validate.optional("name"):
    validate.any(validate.text, None),
    validate.optional("series_name"):
    validate.any(validate.text, None),
    validate.optional("media_type"):
    validate.any(validate.text, None),
    "stream_data":
    validate.any(
        None, {
            "streams":
            validate.all([{
                "quality":
                validate.any(validate.text, None),
                "url":
                validate.url(scheme="http", path=validate.endswith(".m3u8")),
                validate.optional("video_encode_id"):
                validate.text
            }])
        })
})
_login_schema = validate.Schema({
    "auth":
    validate.any(validate.text, None),
    "expires":
    validate.all(validate.text, validate.transform(parse_timestamp)),
    "user": {
        "username": validate.any(validate.text, None),
        "email": validate.text
    }
})
Exemple #18
0
class App17(Plugin):
    _url_re = re.compile(r"https://17.live/live/(?P<channel>[^/&?]+)")
    API_URL = "https://api-dsa.17app.co/api/v1/lives/{0}/viewers/alive"

    _api_schema = validate.Schema(
        {
            "rtmpUrls": [{
                validate.optional("provider"): validate.any(int, None),
                "url": validate.url(),
            }],
        },
        validate.get("rtmpUrls"),
    )

    @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)
        channel = match.group("channel")

        self.session.http.headers.update({'User-Agent': useragents.CHROME, 'Referer': self.url})

        data = '{"liveStreamID":"%s"}' % (channel)

        try:
            res = self.session.http.post(self.API_URL.format(channel), data=data)
            res_json = self.session.http.json(res, schema=self._api_schema)
            log.trace("{0!r}".format(res_json))
            http_url = res_json[0]["url"]
        except Exception as e:
            log.info("Stream currently unavailable.")
            log.debug(str(e))
            return

        https_url = http_url.replace("http:", "https:")
        yield "live", HTTPStream(self.session, https_url)

        if 'pull-rtmp' in http_url:
            rtmp_url = http_url.replace("http:", "rtmp:").replace(".flv", "")
            stream = RTMPStream(self.session, {
                "rtmp": rtmp_url,
                "live": True,
                "pageUrl": self.url,
            })
            yield "live", stream

        if 'wansu-' in http_url:
            hls_url = http_url.replace(".flv", "/playlist.m3u8")
        else:
            hls_url = http_url.replace("live-hdl", "live-hls").replace(".flv", ".m3u8")

        s = HLSStream.parse_variant_playlist(self.session, hls_url)
        if not s:
            yield "live", HLSStream(self.session, hls_url)
        else:
            if len(s) == 1:
                for _n, _s in s.items():
                    yield "live", _s
            else:
                for _s in s.items():
                    yield _s
    "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)
    },
)
Exemple #20
0
class NimoTV(Plugin):
    url_re = re.compile(r'https?://(?:www\.)?nimo\.tv/(?P<username>.*)')
    data_url = 'https://m.nimo.tv/{0}'
    data_re = re.compile(r'<script>var G_roomBaseInfo = ({.*?});</script>')

    author = None
    category = None
    title = None

    data_schema = validate.Schema(
        validate.transform(data_re.search),
        validate.any(None, validate.all(
            validate.get(1),
            validate.transform(parse_json), {
                'title': str,
                'nickname': str,
                'game': str,
                'roomLineInfo': validate.any(None, {
                    'vCodeLines2': [{
                        'iBitRate': int,
                        'vCdns': [{
                            'vCdnUrls': [{
                                'smediaUrl': validate.url(),
                            }],
                        }],
                    }],
                }),
            },
        )),
    )

    video_qualities = {
        250: '240p',
        500: '360p',
        1000: '480p',
        2000: '720p',
        6000: '1080p',
    }

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def get_author(self):
        if self.author is not None:
            return self.author

    def get_category(self):
        if self.category is not None:
            return self.category

    def get_title(self):
        if self.title is not None:
            return self.title

    def _get_streams(self):
        m = self.url_re.match(self.url)
        if m and m.group('username'):
            username = m.group('username')
        else:
            return

        headers = {'User-Agent': useragents.ANDROID}
        data = self.session.http.get(
            self.data_url.format(username),
            headers=headers,
            schema=self.data_schema,
        )

        if data is None or data['roomLineInfo'] is None:
            return

        self.author = data['nickname']
        self.category = data['game']
        self.title = data['title']

        for vcl2 in data['roomLineInfo']['vCodeLines2']:
            q = self.video_qualities[vcl2['iBitRate']]
            for vcdn in vcl2['vCdns']:
                for vcdnurl in vcdn['vCdnUrls']:
                    if 'tx.hls.nimo.tv' in vcdnurl['smediaUrl']:
                        log.debug(f"HLS URL={vcdnurl['smediaUrl']} ({q})")
                        yield q, HLSStream(self.session, vcdnurl['smediaUrl'])
Exemple #21
0
from streamlink.plugin import Plugin
from streamlink.plugin.api import http, validate
from streamlink.plugin.api import useragents
from streamlink.stream import HLSStream

_url_re = re.compile(r"https?://(www\.)?ok\.ru/live/\d+")
_vod_re = re.compile(r";(?P<hlsurl>[^;]+video\.m3u8.+?)\\&quot;")

_schema = validate.Schema(
    validate.transform(_vod_re.search),
    validate.any(
        None,
        validate.all(
            validate.get("hlsurl"),
            validate.url()
        )
    )
)

class OK_live(Plugin):
    """
    Support for ok.ru live stream: http://www.ok.ru/live/
    """
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url) is not None

    def _get_streams(self):
        headers = {
            'User-Agent': useragents.CHROME,
Exemple #22
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(
    "<iframe src=\"(https://www.filmon.com/channel/export[^\"]+)\""
)
_live_json_re = re.compile("var startupChannel = (.+);")
_replay_json_re = re.compile("var standByVideo = encodeURIComponent\('(.+)'\);")
_history_re = re.compile(
    "helpers.common.flash.flashplayerinstall\({url:'([^']+)',"
)
_video_flashvars_re = re.compile(
    "<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,
Exemple #24
0
class Reuters(Plugin):
    _url_re = re.compile(r'https?://(.*?\.)?reuters\.(com|tv)')
    _id_re = re.compile(r'(/l/|id=)(?P<id>.*?)(/|\?|$)')
    _iframe_url = 'https://www.reuters.tv/l/{0}/?nonav=true'
    _hls_re = re.compile(r'''(?<!')https://[^"';!<>]+\.m3u8''')
    _json_re = re.compile(r'''(?P<data>{.*});''')
    _data_schema = validate.Schema(
        validate.transform(_json_re.search),
        validate.any(
            None,
            validate.all(
                validate.get('data'), validate.transform(parse_json), {
                    'title':
                    validate.text,
                    'items': [{
                        'title':
                        validate.text,
                        'type':
                        validate.text,
                        'resources':
                        [{
                            'mimeType': validate.text,
                            'uri': validate.url(),
                            validate.optional('protocol'): validate.text,
                            validate.optional('entityType'): validate.text,
                        }]
                    }],
                })))

    def __init__(self, url):
        super().__init__(url)
        self.title = None

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url) is not None

    def get_title(self):
        if not self.title:
            self._get_data()
        return self.title

    def _get_data(self):
        res = self.session.http.get(self.url)
        for script in itertags(res.text, 'script'):
            if script.attributes.get(
                    'type'
            ) == 'text/javascript' and '#rtvIframe' in script.text:
                m = self._id_re.search(self.url)
                if m and m.group('id'):
                    log.debug('ID: {0}'.format(m.group('id')))
                    res = self.session.http.get(
                        self._iframe_url.format(m.group('id')))

        for script in itertags(res.text, 'script'):
            if script.attributes.get(
                    'type') == 'text/javascript' and 'RTVJson' in script.text:
                data = self._data_schema.validate(script.text)
                if not data:
                    continue
                self.title = data['title']
                for item in data['items']:
                    if data['title'] == item['title']:
                        log.trace('{0!r}'.format(item))
                        log.debug('Type: {0}'.format(item['type']))
                        for res in item['resources']:
                            if res['mimeType'] == 'application/x-mpegURL':
                                return res['uri']

        # fallback
        for title in itertags(res.text, 'title'):
            self.title = title.text
        m = self._hls_re.search(res.text)
        if not m:
            log.error('Unsupported PageType.')
            return
        return m.group(0)

    def _get_streams(self):
        hls_url = self._get_data()
        if not hls_url:
            return
        log.debug('URL={0}'.format(hls_url))
        return HLSStream.parse_variant_playlist(self.session, hls_url)
Exemple #25
0
}
BLOCKED_MSG_FORMAT = (
    "You have crossed the free viewing limit. You have been blocked for "
    "{0} minutes. Try again in {1} minutes"
)
BLOCK_TYPE_VIEWING_LIMIT = 1
BLOCK_TYPE_NO_SLOTS = 11

_url_re = re.compile(r"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),
        },
    )
)
Exemple #26
0
class RTBF(Plugin):
    GEO_URL = 'https://www.rtbf.be/api/geoloc'
    TOKEN_URL = 'https://token.rtbf.be/'
    RADIO_STREAM_URL = 'http://www.rtbfradioplayer.be/radio/liveradio/rtbf/radios/{}/config.json'

    _url_re = re.compile(r'https?://(?:www\.)?(?:rtbf\.be/auvio/.*\?l?id=(?P<video_id>[0-9]+)#?|rtbfradioplayer\.be/radio/liveradio/(?:webradio-)?(?P<radio>.+))')
    _stream_size_re = re.compile(r'https?://.+-(?P<size>\d+p?)\..+?$')

    _video_player_re = re.compile(r'<iframe\s+class="embed-responsive-item\s+js-embed-iframe".*src="(?P<player_url>.+?)".*?</iframe>', re.DOTALL)
    _video_stream_data_re = re.compile(r'<div\s+id="js-embed-player"\s+class="js-embed-player\s+embed-player"\s+data-media="(.+?)"')

    _geo_schema = validate.Schema(
        {
            'country': validate.text,
            'zone': validate.text
        }
    )

    _video_stream_schema = validate.Schema(
        validate.transform(_video_stream_data_re.search),
        validate.any(
            None,
            validate.all(
                validate.get(1),
                validate.transform(HTMLParser().unescape),
                validate.transform(parse_json),
                {
                    'geoLocRestriction': validate.text,
                    validate.optional('isLive'): bool,
                    validate.optional('startDate'): validate.text,
                    validate.optional('endDate'): validate.text,
                    'sources': validate.any(
                        [],
                        validate.Schema({
                            validate.text: validate.any(None, '', validate.url())
                        })
                    ),
                    validate.optional('urlHls'): validate.any(None, '', validate.url()),
                    validate.optional('urlDash'): validate.any(None, '', validate.url()),
                    validate.optional('streamUrlHls'): validate.any(None, '', validate.url()),
                    validate.optional('streamUrlDash'): validate.any(None, '', validate.url())
                }
            )
        )
    )

    _radio_stream_schema = validate.Schema(
        {
            'audioUrls': validate.all(
                [{
                    'url': validate.url(),
                    'mimeType': validate.text
                }]
            )
        }
    )

    @classmethod
    def check_geolocation(cls, geoloc_flag):
        if geoloc_flag == 'open':
            return True

        res = http.get(cls.GEO_URL)
        data = http.json(res, schema=cls._geo_schema)
        return data['country'] == geoloc_flag or data['zone'] == geoloc_flag

    @classmethod
    def tokenize_stream(cls, url):
        res = http.post(cls.TOKEN_URL, data={'streams[url]': url})
        data = http.json(res)
        return data['streams']['url']

    @staticmethod
    def iso8601_to_epoch(date):
        # Convert an ISO 8601-formatted string date to datetime
        return datetime.datetime.strptime(date[:-6], '%Y-%m-%dT%H:%M:%S') + \
            datetime.timedelta(hours=int(date[-6:-3]), minutes=int(date[-2:]))

    @classmethod
    def can_handle_url(cls, url):
        return RTBF._url_re.match(url)

    def _get_radio_streams(self, radio):
        res = http.get(self.RADIO_STREAM_URL.format(radio.replace('-', '_')))
        streams = http.json(res, schema=self._radio_stream_schema)

        for stream in streams['audioUrls']:
            match = self._stream_size_re.match(stream['url'])
            if match is not None:
                quality = '{}k'.format(match.group('size'))
            else:
                quality = stream['mimetype']
            yield quality, HTTPStream(self.session, stream['url'])

    def _get_video_streams(self):
        res = http.get(self.url)
        match = self._video_player_re.search(res.text)
        if match is None:
            return
        player_url = match.group('player_url')
        stream_data = http.get(player_url, schema=self._video_stream_schema)
        if stream_data is None:
            return

        # Check geolocation to prevent further errors when stream is parsed
        if not self.check_geolocation(stream_data['geoLocRestriction']):
            self.logger.error('Stream is geo-restricted')
            return

        now = datetime.datetime.now()
        try:
            if isinstance(stream_data['sources'], dict):
                urls = []
                for profile, url in stream_data['sources'].items():
                    if not url or url in urls:
                        continue
                    match = self._stream_size_re.match(url)
                    if match is not None:
                        quality = match.group('size')
                    else:
                        quality = profile
                    yield quality, HTTPStream(self.session, url)
                    urls.append(url)

            hls_url = stream_data.get('urlHls') or stream_data.get('streamUrlHls')
            if hls_url:
                if stream_data.get('isLive', False):
                    # Live streams require a token
                    hls_url = self.tokenize_stream(hls_url)
                for stream in HLSStream.parse_variant_playlist(self.session, hls_url).items():
                    yield stream

        except IOError as err:
            if '403 Client Error' in str(err):
                # Check whether video is expired
                if 'startDate' in stream_data:
                    if now < self.iso8601_to_epoch(stream_data['startDate']):
                        self.logger.error('Stream is not yet available')
                elif 'endDate' in stream_data:
                    if now > self.iso8601_to_epoch(stream_data['endDate']):
                        self.logger.error('Stream has expired')

    def _get_streams(self):
        match = self.can_handle_url(self.url)
        if match.group('radio'):
            return self._get_radio_streams(match.group('radio'))
        return self._get_video_streams()
_csrf_token_re = re.compile("<meta content=\"([^\"]+)\" name=\"csrf-token\"")
_hls_playlist_re = re.compile("<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):
Exemple #28
0
import re

from streamlink.plugin import Plugin
from streamlink.plugin.api import validate

_url_re = re.compile(r'http(s)?://www\.skai(?:tv)?.gr/.*')
_api_url = "http://www.skaitv.gr/json/live.php"
_api_res_schema = validate.Schema(validate.all(
    validate.get("now"),
    {
        "livestream": validate.url()
    },
    validate.get("livestream"))
)


class Skai(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    @Plugin.broken()
    def _get_streams(self):
        api_res = self.session.http.get(_api_url)
        yt_url = self.session.http.json(api_res, schema=_api_res_schema)
        if yt_url:
            return self.session.streams(yt_url)


__plugin__ = Skai
Exemple #29
0
    "_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")),
        "cdn":
        validate.all(validate.xml_find("head/meta"), validate.get("cdn")),
        "videos":
        validate.all(validate.xml_findall("body/seq/video"),
                     [validate.get("src")])
    }))


class ard_mediathek(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    def _get_http_streams(self, info):
        name = QUALITY_MAP.get(info["_quality"], "vod")
Exemple #30
0
#!/usr/bin/env python
import re

from streamlink.plugin import Plugin
from streamlink.plugin.api import http, validate
from streamlink.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))
Exemple #31
0
class BrightcovePlayer(object):
    player_page = "http://players.brightcove.net/{account_id}/{player_id}/index.html"
    api_url = "https://edge.api.brightcove.com/playback/v1/"
    amf_broker = "http://c.brightcove.com/services/messagebroker/amf"

    policy_key_re = re.compile(
        r'''policyKey\s*:\s*(?P<q>['"])(?P<key>.*?)(?P=q)''')

    schema = validate.Schema({
        "sources": [{
            validate.optional("height"):
            validate.any(int, None),
            validate.optional("avg_bitrate"):
            validate.any(int, None),
            validate.optional("src"):
            validate.url(),
            validate.optional("app_name"):
            validate.any(validate.url(scheme="rtmp"),
                         validate.url(scheme="rtmpe")),
            validate.optional("stream_name"):
            validate.text,
            validate.optional("type"):
            validate.text
        }]
    })

    def __init__(self, session, account_id, player_id="default_default"):
        self.session = session
        log.debug("Creating player for account {0} (player_id={1})".format(
            account_id, player_id))
        self.account_id = account_id
        self.player_id = player_id

    def player_url(self, video_id):
        return self.player_page.format(account_id=self.account_id,
                                       player_id=self.player_id,
                                       params=dict(videoId=video_id))

    def video_info(self, video_id, policy_key):
        url = "{base}accounts/{account_id}/videos/{video_id}".format(
            base=self.api_url, account_id=self.account_id, video_id=video_id)
        res = self.session.http.get(
            url,
            headers={
                "User-Agent": useragents.CHROME,
                "Referer": self.player_url(video_id),
                "Accept": "application/json;pk={0}".format(policy_key)
            })
        return self.session.http.json(res, schema=self.schema)

    def policy_key(self, video_id):
        # Get the embedded player page
        res = self.session.http.get(self.player_url(video_id))

        policy_key_m = self.policy_key_re.search(res.text)
        policy_key = policy_key_m and policy_key_m.group("key")
        if not policy_key:
            raise PluginError("Could not find Brightcove policy key")

        return policy_key

    def get_streams(self, video_id):
        log.debug("Finding streams for video: {0}".format(video_id))
        policy_key = self.policy_key(video_id)
        log.debug("Found policy key: {0}".format(policy_key))
        data = self.video_info(video_id, policy_key)
        headers = {"Referer": self.player_url(video_id)}

        for source in data.get("sources"):
            # determine quality name
            if source.get("height"):
                q = "{0}p".format(source.get("height"))
            elif source.get("avg_bitrate"):
                q = "{0}k".format(source.get("avg_bitrate") // 1000)
            else:
                q = "live"
            if ((source.get("type") == "application/x-mpegURL"
                 and source.get("src"))
                    or (source.get("src") and ".m3u8" in source.get("src"))):
                yield from HLSStream.parse_variant_playlist(
                    self.session, source.get("src"), headers=headers).items()
            elif source.get("app_name"):
                s = RTMPStream(
                    self.session, {
                        "rtmp": source.get("app_name"),
                        "playpath": source.get("stream_name")
                    })
                yield q, s
            elif source.get("src") and source.get("src").endswith(".mp4"):
                yield q, HTTPStream(self.session,
                                    source.get("src"),
                                    headers=headers)

    @classmethod
    def from_url(cls, session, url):
        purl = urlparse(url)
        querys = dict(parse_qsl(purl.query))

        account_id, player_id, _ = purl.path.lstrip("/").split("/", 3)
        video_id = querys.get("videoId")

        bp = cls(session, account_id=account_id, player_id=player_id)
        return bp.get_streams(video_id)

    @classmethod
    def from_player_key(cls,
                        session,
                        player_id,
                        player_key,
                        video_id,
                        url=None):
        amf_message = AMFMessage(
            "com.brightcove.experience.ExperienceRuntimeFacade.getDataForExperience",
            "/1",
            [
                ''.join([
                    "{0:02x}".format(random.randint(0, 255)) for _ in range(20)
                ]),  # random id
                ViewerExperienceRequest(experienceId=int(player_id),
                                        URL=url or "",
                                        playerKey=player_key,
                                        deliveryType=float('nan'),
                                        TTLToken="",
                                        contentOverrides=[
                                            ContentOverride(
                                                featuredRefId=None,
                                                contentRefIds=None,
                                                contentId=int(video_id))
                                        ])
            ])
        amf_packet = AMFPacket(version=3)
        amf_packet.messages.append(amf_message)

        res = session.http.post(cls.amf_broker,
                                headers={"Content-Type": "application/x-amf"},
                                data=amf_packet.serialize(),
                                params=dict(playerKey=player_key),
                                raise_for_status=False)
        data = AMFPacket.deserialize(BytesIO(res.content))
        result = data.messages[0].value
        bp = cls(session=session, account_id=int(result.publisherId))
        return bp.get_streams(video_id)
Exemple #32
0
class ITVPlayer(Plugin):
    _url_re = re.compile(r"https?://(?:www.)?itv.com/hub/(?P<stream>.+)")
    _video_info_schema = validate.Schema({
        "StatusCode": 200,
        "AdditionalInfo": {
            "Message": validate.any(None, validate.text)
        },
        "Playlist": {
            "VideoType": validate.text,
            "Video": {
                "Subtitles": validate.any(None, [{
                    "Href": validate.url(),
                }]),
                "Base": validate.url(),
                "MediaFiles": [
                    {"Href": validate.text,
                     "KeyServiceUrl": validate.any(None, validate.url())}
                ]
            }
        }
    })

    @classmethod
    def can_handle_url(cls, url):
        match = cls._url_re.match(url)
        return match is not None

    @property
    def device_info(self):
        return {"user": {},
                "device": {"manufacturer": "Chrome", "model": "66",
                           "os": {"name": "Windows", "version": "10", "type": "desktop"}},
                "client": {"version": "4.1", "id": "browser"},
                "variantAvailability": {"featureset": {"min": ["hls", "aes"],
                                                       "max": ["hls", "aes"]},
                                        "platformTag": "dotcom"}}

    def video_info(self):
        page = self.session.http.get(self.url)
        for div in itertags(page.text, 'div'):
            if div.attributes.get("id") == "video":
                return div.attributes

    def _get_streams(self):
        """
            Find all the streams for the ITV url
            :return: Mapping of quality to stream
        """
        self.session.http.headers.update({"User-Agent": useragents.FIREFOX})
        video_info = self.video_info()
        video_info_url = video_info.get("data-html5-playlist") or video_info.get("data-video-id")

        res = self.session.http.post(video_info_url,
                        data=json.dumps(self.device_info),
                        headers={"hmac": video_info.get("data-video-hmac")})
        data = self.session.http.json(res, schema=self._video_info_schema)

        log.debug("Video ID info response: {0}".format(data))

        stype = data['Playlist']['VideoType']

        for media in data['Playlist']['Video']['MediaFiles']:
            url = urljoin(data['Playlist']['Video']['Base'], media['Href'])
            name_fmt = "{pixels}_{bitrate}" if stype == "CATCHUP" else None
            for s in HLSStream.parse_variant_playlist(self.session, url, name_fmt=name_fmt).items():
                yield s
Exemple #33
0
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'"content(?:I|i)d", "(\w+)"')
    content_api = "/actions/content/media/{id}"
    new_content_api = "/action/media/{id}"
    content_api_schema = validate.Schema({
        "Id": validate.text,
        "Media": {
            "Link": {
                "DefaultServiceUrl": validate.url(),
                validate.optional("ServiceUrl"):
                validate.any(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 contentId
        content_id_m = self.content_id_re.search(res.text)
        if content_id_m:
            return content_id_m.group(1)

        # 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")

    def _get_hls_url(self, content_id):
        # make the api url relative to the current domain
        if "cnnturk" in self.url or "teve2.com.tr" in self.url:
            self.logger.debug("Using new content API url")
            api_url = urljoin(self.url,
                              self.new_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")
Exemple #34
0
class Rtve(Plugin):
    secret_key = base64.b64decode("eWVMJmRhRDM=")
    content_id_re = re.compile(r'data-id\s*=\s*"(\d+)"')
    url_re = re.compile(
        r"""
        https?://(?:www\.)?rtve\.es/(?:directo|noticias|television|deportes|alacarta|drmn)/.*?/?
    """, re.VERBOSE)
    cdn_schema = validate.Schema(
        validate.transform(parse_xml), validate.xml_findall(".//preset"), [
            validate.union({
                "quality":
                validate.all(validate.getattr("attrib"), validate.get("type")),
                "urls":
                validate.all(validate.xml_findall(".//url"),
                             [validate.getattr("text")])
            })
        ])
    subtitles_api = "http://www.rtve.es/api/videos/{id}/subtitulos.json"
    subtitles_schema = validate.Schema(
        {"page": {
            "items": [{
                "src": validate.url(),
                "lang": validate.text
            }]
        }}, validate.get("page"), validate.get("items"))
    video_api = "http://www.rtve.es/api/videos/{id}.json"
    video_schema = validate.Schema(
        {
            "page": {
                "items": [{
                    "qualities": [{
                        "preset": validate.text,
                        "height": int
                    }]
                }]
            }
        }, validate.get("page"), validate.get("items"), validate.get(0))
    options = PluginOptions({"mux_subtitles": False})

    @classmethod
    def can_handle_url(cls, url):
        return cls.url_re.match(url) is not None

    def __init__(self, url):
        Plugin.__init__(self, url)
        self.zclient = ZTNRClient(self.secret_key)
        http.headers = {"User-Agent": useragents.SAFARI_8}

    def _get_content_id(self):
        res = http.get(self.url)
        m = self.content_id_re.search(res.text)
        return m and int(m.group(1))

    def _get_subtitles(self, content_id):
        res = http.get(self.subtitles_api.format(id=content_id))
        return http.json(res, schema=self.subtitles_schema)

    def _get_quality_map(self, content_id):
        res = http.get(self.video_api.format(id=content_id))
        data = http.json(res, schema=self.video_schema)
        qmap = {}
        for item in data["qualities"]:
            qname = {
                "MED": "Media",
                "HIGH": "Alta"
            }.get(item["preset"], item["preset"])
            qmap[qname] = u"{0}p".format(item["height"])
        return qmap

    def _get_streams(self):
        streams = []
        content_id = self._get_content_id()
        if content_id:
            self.logger.debug("Found content with id: {0}", content_id)
            stream_data = self.zclient.get_cdn_list(content_id,
                                                    schema=self.cdn_schema)
            quality_map = None

            for stream in stream_data:
                for url in stream["urls"]:
                    if url.endswith("m3u8"):
                        streams.extend(
                            HLSStream.parse_variant_playlist(
                                self.session, url).items())
                    elif url.endswith("mp4"):
                        if quality_map is None:  # only make the request when it is necessary
                            quality_map = self._get_quality_map(content_id)
                        # rename the HTTP sources to match the HLS sources
                        quality = quality_map.get(stream["quality"],
                                                  stream["quality"])
                        streams.append((quality, HTTPStream(self.session,
                                                            url)))

            subtitles = None
            if self.get_option("mux_subtitles"):
                subtitles = self._get_subtitles(content_id)
            if subtitles:
                substreams = {}
                for i, subtitle in enumerate(subtitles):
                    substreams[subtitle["lang"]] = HTTPStream(
                        self.session, subtitle["src"])

                for q, s in streams:
                    yield q, MuxedStream(self.session, s, subtitles=substreams)
            else:
                for s in streams:
                    yield s
from streamlink.plugin.api import http, validate
from streamlink.stream import HTTPStream, RTMPStream

API_CLIENT_NAME = "Bambuser AS2"
API_CONTEXT = "b_broadcastpage"
API_KEY = "005f64509e19a868399060af746a00aa"
API_URL_VIDEO = "http://player-c.api.bambuser.com/getVideo.json"

_url_re = re.compile("http(s)?://(\w+.)?bambuser.com/v/(?P<video_id>\d+)")
_video_schema = validate.Schema({
    validate.optional("error"): validate.text,
    validate.optional("result"): {
        "id": validate.text,
        "size": validate.text,
        "url": validate.url(
            scheme=validate.any("rtmp", "http")
        )
    }
})


class Bambuser(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    def _get_streams(self):
        match = _url_re.match(self.url)
        video_id = match.group("video_id")
        params = {
            "client_name": API_CLIENT_NAME,
Exemple #36
0
class Vlive(Plugin):
    _page_info = re.compile(r"window\.__PRELOADED_STATE__\s*=\s*({.*})\s*(?:<|,\s*function)", re.DOTALL)
    _playinfo_url = "https://www.vlive.tv/globalv-web/vam-web/old/v3/live/{0}/playInfo"

    _schema_video = validate.Schema(
        validate.transform(_page_info.search),
        validate.any(None, validate.all(
            validate.get(1),
            validate.parse_json(),
            validate.any(
                validate.all(
                    {"postDetail": {"post": {"officialVideo": {
                        "type": str,
                        "videoSeq": int,
                        validate.optional("status"): str}}}},
                    validate.get(("postDetail", "post", "officialVideo"))),
                validate.all(
                    {"postDetail": {"error": {"errorCode": str}}},
                    validate.get(("postDetail", "error")),
                )
            )
        ))
    )

    _schema_stream = validate.Schema(
        validate.parse_json(),
        {"result": {"adaptiveStreamUrl": validate.url()}},
        validate.get(("result", "adaptiveStreamUrl")),
    )

    def _get_streams(self):
        self.session.http.headers.update({"Referer": self.url})
        video_json = self.session.http.get(self.url, schema=self._schema_video)
        if video_json is None:
            log.error('Could not parse video page')
            return

        err = video_json.get('errorCode')
        if err == 'common_700':
            log.error('Available only to members of the channel')
            return
        elif err == 'common_702':
            log.error('Vlive+ VODs are not supported')
            return
        elif err == 'common_404':
            log.error('Could not find video page')
            return
        elif err is not None:
            log.error('Unknown error code: {0}'.format(err))
            return

        if video_json['type'] == 'VOD':
            log.error('VODs are not supported')
            return

        url_format, video_id = self.match.groups()
        if url_format == 'post':
            video_id = str(video_json['videoSeq'])

        video_status = video_json.get('status')
        if video_status == 'ENDED':
            log.error('Stream has ended')
            return
        elif video_status != 'ON_AIR':
            log.error('Unknown video status: {0}'.format(video_status))
            return

        stream_url = self.session.http.get(
            self._playinfo_url.format(video_id),
            schema=self._schema_stream)
        return HLSStream.parse_variant_playlist(self.session, stream_url).items()
Exemple #37
0
    def test_url(self):
        url_ = "https://google.se/path"

        assert validate(url(), url_)
        assert validate(url(scheme="http"), url_)
        assert validate(url(path="/path"), url_)
    def test_url(self):
        url_ = "https://google.se/path"

        assert validate(url(), url_)
        assert validate(url(scheme="http"), url_)
        assert validate(url(path="/path"), url_)
from streamlink.plugin import Plugin, PluginError
from streamlink.plugin.api import http, validate
from streamlink.stream import RTMPStream, HLSStream

SWF_URL = "http://play.streamingvideoprovider.com/player2.swf"
API_URL = "http://player.webvideocore.net/index.php"

_url_re = re.compile(
    r"http(s)?://(\w+\.)?streamingvideoprovider.co.uk/(?P<channel>[^/&?]+)"
)
_hls_re = re.compile(r"'(http://.+\.m3u8)'")

_rtmp_schema = validate.Schema(
    validate.xml_findtext("./info/url"),
    validate.url(scheme="rtmp")
)
_hls_schema = validate.Schema(
    validate.transform(_hls_re.search),
    validate.any(
        None,
        validate.all(
            validate.get(1),
            validate.url(
                scheme="http",
                path=validate.endswith("m3u8")
            )
        )
    )
)
Exemple #40
0
    "low": 1
}

_url_re = re.compile(
    r"""
    http(s)?://(\w+\.)?gaminglive\.tv
    /(?P<type>channels|videos)/(?P<name>[^/]+)
""", re.VERBOSE)
_quality_re = re.compile(r"[^/]+-(?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 GamingLive(Plugin):
    @classmethod
Exemple #41
0
    (?:
        (/embed)?/(video|live)
        /(?P<media_id>[^_?/]+)
    |
        /(?P<channel_name>[A-Za-z0-9-_]+)
    )
""", re.VERBOSE)

_media_schema = validate.Schema(validate.any(
    {"error": {"title": validate.text}},
    # "stream_chromecast_url": validate.url(),
    # Chromecast URL is already available in qualities subdict
    {"qualities": validate.any({
        validate.text: validate.all([{
            "type": validate.text,
            "url": validate.url()
        }])
    })
    }))
_live_id_schema = validate.Schema(
    {
        "total": int,
        "list": validate.any(
            [],
            [{"id": validate.text}]
        )
    }
)


class DailyMotion(Plugin):
Exemple #42
0
class PlayTV(Plugin):
    FORMATS_URL = 'http://playtv.fr/player/initialize/{0}/'
    API_URL = 'http://playtv.fr/player/play/{0}/?format={1}&language={2}&bitrate={3}'

    _url_re = re.compile(r'http://playtv\.fr/television/(?P<channel>[^/]+)/?')

    _formats_schema = validate.Schema({
        'streams':
        validate.any(
            [], {
                validate.text:
                validate.Schema({
                    validate.text: {
                        'bitrates': validate.all(
                            [validate.Schema({'value': int})])
                    }
                })
            })
    })
    _api_schema = validate.Schema({'url': validate.url()})

    @classmethod
    def can_handle_url(cls, url):
        return PlayTV._url_re.match(url)

    def _get_streams(self):
        match = self._url_re.match(self.url)
        channel = match.group('channel')

        res = http.get(self.FORMATS_URL.format(channel))
        streams = http.json(res, schema=self._formats_schema)['streams']
        if streams == []:
            self.logger.error(
                'Channel may be geo-restricted, not directly provided by PlayTV or not freely available'
            )
            return

        for language in streams:
            for protocol, bitrates in list(streams[language].items()):
                # - Ignore non-supported protocols (RTSP, DASH)
                # - Ignore deprecated Flash (RTMPE/HDS) streams (PlayTV doesn't provide anymore a Flash player)
                if protocol in ['rtsp', 'flash', 'dash', 'hds']:
                    continue

                for bitrate in bitrates['bitrates']:
                    if bitrate['value'] == 0:
                        continue
                    api_url = self.API_URL.format(channel, protocol, language,
                                                  bitrate['value'])
                    res = http.get(api_url)
                    video_url = http.json(res, schema=self._api_schema)['url']
                    bs = '{0}k'.format(bitrate['value'])

                    if protocol == 'hls':
                        for _, stream in HLSStream.parse_variant_playlist(
                                self.session, video_url).items():
                            yield bs, stream
                    elif protocol == 'hds':
                        for _, stream in HDSStream.parse_manifest(
                                self.session, video_url).items():
                            yield bs, stream
import re

from streamlink.compat import urlparse
from streamlink.plugin import Plugin
from streamlink.plugin.api import http, validate
from streamlink.stream import RTMPStream, HTTPStream, HLSStream
from streamlink.utils import parse_json, rtmpparse, swfdecompress

_url_re = re.compile("http(s)?://api.dmcloud.net/player/embed/[^/]+/[^/]+")
_rtmp_re = re.compile(b"customURL[^h]+(https://.*?)\\\\")
_info_re = re.compile("var info = (.*);")
_schema = validate.Schema(
    {
        "mode": validate.text,
        validate.optional("mp4_url"): validate.url(scheme="http"),
        validate.optional("ios_url"): validate.url(scheme="http"),
        validate.optional("swf_url"): validate.url(scheme="http"),
    }
)


class DMCloud(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    def _get_rtmp_stream(self, swfurl):
        res = http.get(swfurl)
        swf = swfdecompress(res.content)
        match = _rtmp_re.search(swf)
        if not match:
Exemple #44
0
    def _get_streams(self):
        self.session.http.headers.update({"Referer": self.url})
        schema_data = validate.Schema(
            validate.parse_html(),
            validate.xml_xpath_string(
                ".//script[@id='__NEXT_DATA__'][text()]/text()"),
            str,
            validate.parse_json(),
            {
                "props": {
                    "pageProps": {
                        "data": {
                            "liveBroadcast": {
                                # "id": str,
                                "current":
                                validate.any(
                                    None, {
                                        "channel": str,
                                        "channelName": str,
                                        "legacyEncoder": str,
                                    }),
                                "next":
                                validate.any(
                                    None, {
                                        "channel": str,
                                        "channelName": str,
                                        "legacyEncoder": str,
                                    })
                            }
                        }
                    }
                }
            },
            validate.get(("props", "pageProps", "data", "liveBroadcast")),
            validate.union_get("current", "next"),
        )

        try:
            data_current, data_next = self.session.http.get(self.url,
                                                            schema=schema_data)
        except PluginError:
            return

        log.debug(f"current={data_current!r}")
        log.debug(f"next={data_next!r}")

        data = data_current or data_next
        video_id = data["legacyEncoder"]
        self.title = data["channelName"]

        _hash = self.session.http.get(
            "https://www.ceskatelevize.cz/v-api/iframe-hash/",
            schema=validate.Schema(str))
        res = self.session.http.get(
            "https://www.ceskatelevize.cz/ivysilani/embed/iFramePlayer.php",
            params={
                "hash": _hash,
                "origin": "iVysilani",
                "autoStart": "true",
                "videoID": video_id,
            },
        )

        m = self._re_playlist_info.search(res.text)
        if not m:
            return
        _type, _id = m.groups()

        data = self.session.http.post(
            "https://www.ceskatelevize.cz/ivysilani/ajax/get-client-playlist/",
            data={
                "playlist[0][type]": _type,
                "playlist[0][id]": _id,
                "requestUrl": "/ivysilani/embed/iFramePlayer.php",
                "requestSource": "iVysilani",
                "type": "html",
                "canPlayDRM": "false",
            },
            headers={
                "x-addr": "127.0.0.1",
            },
            schema=validate.Schema(
                validate.parse_json(), {
                    validate.optional("streamingProtocol"): str,
                    "url": validate.any(validate.url(), "Error",
                                        "error_region")
                }),
        )

        if data["url"] in ["Error", "error_region"]:
            log.error("This stream is not available")
            return

        url = self.session.http.get(
            data["url"],
            schema=validate.Schema(
                validate.parse_json(), {
                    "playlist": [{
                        validate.optional("type"): str,
                        "streamUrls": {
                            "main": validate.url(),
                        }
                    }]
                }, validate.get(("playlist", 0, "streamUrls", "main"))))
        return DASHStream.parse_manifest(self.session, url)
Exemple #45
0
_url_re = re.compile(r"http(s)?://(\w+\.)?seemeplay.ru/")
_player_re = re.compile(r"""
    SMP.(channel|video).player.init\({
    \s+file:\s+"([^"]+)"
""", re.VERBOSE)

_schema = validate.Schema(
    validate.transform(_player_re.search),
    validate.any(
        None,
        validate.union({
            "type": validate.get(1),
            "url": validate.all(
                validate.get(2),
                validate.url(scheme="http"),
            ),
        })
    )
)


class SeeMePlay(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    def _get_streams(self):
        res = http.get(self.url, schema=_schema)
        if not res:
            return
class Bloomberg(Plugin):
    VOD_API_URL = 'https://www.bloomberg.com/api/embed?id={0}'
    PLAYER_URL = 'https://cdn.gotraffic.net/projector/latest/bplayer.js'
    CHANNEL_MAP = {
        'audio': 'BBG_RADIO',
        'live/europe': 'EU',
        'live/us': 'US',
        'live/asia': 'ASIA',
        'live/stream': 'EVENT',
        'live/emea': 'EMEA_EVENT',
        'live/asia_stream': 'ASIA_EVENT'
    }

    _url_re = re.compile(
        r'''
        https?://www\.bloomberg\.com/(
            news/videos/[^/]+/[^/]+ |
            (?P<channel>live/(?:stream|emea|asia_stream|europe|us|asia)|audio)/?
        )
''', re.VERBOSE)
    _live_player_re = re.compile(
        r'{APP_BUNDLE:"(?P<live_player_url>.+?/app.js)"')
    _js_to_json_re = partial(
        re.compile(r'(\w+):(["\']|\d?\.?\d+,|true|false|\[|{)').sub,
        r'"\1":\2')
    _video_id_re = re.compile(r'data-bmmr-id=\\"(?P<video_id>.+?)\\"')
    _mp4_bitrate_re = re.compile(r'.*_(?P<bitrate>[0-9]+)\.mp4')

    _live_streams_schema = validate.Schema(
        validate.transform(_js_to_json_re),
        validate.transform(lambda x: x.replace(':.', ':0.')),
        validate.transform(parse_json),
        validate.Schema(
            {
                'cdns':
                validate.all([
                    validate.Schema(
                        {
                            'streams':
                            validate.all([
                                validate.Schema(
                                    {
                                        'url':
                                        validate.transform(lambda x: re.sub(
                                            r'(https?:/)([^/])', r'\1/\2', x))
                                    }, validate.get('url'), validate.url())
                            ]),
                        }, validate.get('streams'))
                ], validate.transform(lambda x: [i for y in x for i in y]))
            }, validate.get('cdns')))

    _vod_api_schema = validate.Schema(
        {
            'secureStreams':
            validate.all([
                validate.Schema({'url': validate.url()}, validate.get('url'))
            ]),
            'streams':
            validate.all([
                validate.Schema({'url': validate.url()}, validate.get('url'))
            ]),
            'contentLoc':
            validate.url(),
        },
        validate.transform(lambda x: list(
            set(x['secureStreams'] + x['streams'] + [x['contentLoc']]))))

    @classmethod
    def can_handle_url(cls, url):
        return Bloomberg._url_re.match(url)

    def _get_live_streams(self):
        # Get channel id
        match = self._url_re.match(self.url)
        channel = match.group('channel')

        # Retrieve live player URL
        res = http.get(self.PLAYER_URL)
        match = self._live_player_re.search(res.text)
        if match is None:
            return []
        live_player_url = update_scheme(self.url,
                                        match.group('live_player_url'))

        # Extract streams from the live player page
        res = http.get(live_player_url)
        stream_datas = re.findall(
            r'{0}(?:_MINI)?:({{.+?}}]}}]}})'.format(self.CHANNEL_MAP[channel]),
            res.text)
        streams = []
        for s in stream_datas:
            for u in self._live_streams_schema.validate(s):
                if u not in streams:
                    streams.append(u)

        return streams

    def _get_vod_streams(self):
        # Retrieve URL page and search for video ID
        res = http.get(self.url)
        match = self._video_id_re.search(res.text)
        if match is None:
            return []
        video_id = match.group('video_id')

        res = http.get(self.VOD_API_URL.format(video_id))
        streams = http.json(res, schema=self._vod_api_schema)
        return streams

    def _get_streams(self):
        if '/news/videos/' in self.url:
            # VOD
            streams = self._get_vod_streams()
        else:
            # Live
            streams = self._get_live_streams()

        for video_url in streams:
            if '.f4m' in video_url:
                for stream in HDSStream.parse_manifest(self.session,
                                                       video_url).items():
                    yield stream
            elif '.m3u8' in video_url:
                for stream in HLSStream.parse_variant_playlist(
                        self.session, video_url).items():
                    yield stream
            if '.mp4' in video_url:
                match = self._mp4_bitrate_re.match(video_url)
                if match is not None:
                    bitrate = match.group('bitrate') + 'k'
                else:
                    bitrate = 'vod'
                yield bitrate, HTTPStream(self.session, video_url)
Exemple #47
0
    "preferred-player-odm=hlslink&"
    "preferred-player-live=hlslink"
)

_id_re = re.compile(r"/(?:program|direkte|serie/[^/]+)/([^/]+)")
_url_re = re.compile(r"https?://(tv|radio).nrk.no/")
_api_baseurl_re = re.compile(r'''apiBaseUrl:\s*["'](?P<baseurl>[^"']+)["']''')

_schema = validate.Schema(
    validate.transform(_api_baseurl_re.search),
    validate.any(
        None,
        validate.all(
            validate.get("baseurl"),
            validate.url(
                scheme="http"
            )
        )
    )
)

_mediaelement_schema = validate.Schema({
    "mediaUrl": validate.url(
        scheme="http",
        path=validate.endswith(".m3u8")
    )
})


class NRK(Plugin):
    @classmethod
    {
        "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"))

Exemple #49
0
_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)
                ),
            }]
        ),
        validate.optional("adaptive_fmts"): validate.all(
            validate.text,
            validate.transform(parse_stream_map),
            [{
                validate.optional("s"): validate.text,
                "type": validate.all(
                    validate.text,
Exemple #50
0
class Mitele(Plugin):
    _url_re = re.compile(
        r"https?://(?:www\.)?mitele\.es/directo/(?P<channel>[\w-]+)")

    pdata_url = "https://indalo.mediaset.es/mmc-player/api/mmc/v1/{channel}/live/html5.json"
    gate_url = "https://gatekeeper.mediaset.es"

    error_schema = validate.Schema({
        "code": validate.any(validate.text, int),
        "message": validate.text,
    })
    pdata_schema = validate.Schema(
        validate.transform(parse_json),
        validate.any(
            validate.all(
                {
                    "locations": [{
                        "gcp": validate.text,
                        "ogn": validate.any(None, validate.text),
                    }],
                },
                validate.get("locations"),
                validate.get(0),
            ),
            error_schema,
        ))
    gate_schema = validate.Schema(
        validate.transform(parse_json),
        validate.any(
            {
                "mimeType": validate.text,
                "stream": validate.url(),
            },
            error_schema,
        ))

    def __init__(self, url):
        super(Mitele, self).__init__(url)
        self.session.http.headers.update({
            "User-Agent": useragents.FIREFOX,
            "Referer": self.url
        })

    @classmethod
    def can_handle_url(cls, url):
        return cls._url_re.match(url) is not None

    def _get_streams(self):
        channel = self._url_re.match(self.url).group("channel")

        pdata = self.session.http.get(self.pdata_url.format(channel=channel),
                                      acceptable_status=(200, 403, 404),
                                      schema=self.pdata_schema)
        log.trace("{0!r}".format(pdata))
        if pdata.get("code"):
            log.error("{0} - {1}".format(pdata["code"], pdata["message"]))
            return

        gdata = self.session.http.post(self.gate_url,
                                       acceptable_status=(200, 403, 404),
                                       data=pdata,
                                       schema=self.gate_schema)
        log.trace("{0!r}".format(gdata))
        if gdata.get("code"):
            log.error("{0} - {1}".format(gdata["code"], gdata["message"]))
            return

        log.debug("Stream: {0} ({1})".format(gdata["stream"],
                                             gdata.get("mimeType", "n/a")))
        for s in HLSStream.parse_variant_playlist(
                self.session, gdata["stream"],
                name_fmt="{pixels}_{bitrate}").items():
            yield s
from streamlink.compat import urljoin
from streamlink.plugin import Plugin
from streamlink.plugin.api import http, validate
from streamlink.plugin.api.utils import parse_json
from streamlink.stream import AkamaiHDStream, HLSStream

_url_re = re.compile(r"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"
Exemple #52
0
class TV5Monde(Plugin):
    _url_re = re.compile(r'http://(.+\.)?(tv|tivi)5monde(plus(afrique)?)?\.com')
    _videos_re = re.compile(r'"?(?:files|sources)"?:\s*(?P<videos>\[.+?\])')
    _videos_embed_re = re.compile(r'(?:file:\s*|src=)"(?P<embed>.+?\.mp4|.+?/embed/.+?)"')

    _videos_schema = validate.Schema(
        validate.transform(_js_to_json),
        validate.transform(parse_json),
        validate.all([
            validate.any(
                validate.Schema(
                    {'url': validate.url()},
                    validate.get('url')
                ),
                validate.Schema(
                    {'file': validate.url()},
                    validate.get('file')
                ),
            )
        ])
    )

    @classmethod
    def can_handle_url(cls, url):
        return TV5Monde._url_re.match(url)

    def _get_non_embed_streams(self, page):
        match = self._videos_re.search(page)
        if match is not None:
            videos = self._videos_schema.validate(match.group('videos'))
            return videos

        return []

    def _get_embed_streams(self, page):
        match = self._videos_embed_re.search(page)
        if match is None:
            return []

        url = match.group('embed')
        if '.mp4' in url:
            return [url]

        res = self.session.http.get(url)
        videos = self._get_non_embed_streams(res.text)
        if videos:
            return videos

        return []

    def _get_streams(self):
        res = self.session.http.get(self.url)
        match = self._videos_re.search(res.text)
        if match is not None:
            videos = self._videos_schema.validate(match.group('videos'))
        else:
            videos = self._get_embed_streams(res.text)

        for url in videos:
            if '.m3u8' in url:
                for stream in HLSStream.parse_variant_playlist(self.session, url).items():
                    yield stream
            elif 'rtmp' in url:
                yield 'vod', RTMPStream(self.session, {'rtmp': url})
            elif '.mp4' in url:
                yield 'vod', HTTPStream(self.session, url)
Exemple #53
0
        "CHANNEL": {
            "RESULT": validate.transform(int),
            validate.optional("BPWD"): validate.text,
            validate.optional("BNO"): validate.text,
            validate.optional("RMD"): validate.text,
            validate.optional("AID"): validate.text,
            validate.optional("CDN"): validate.text
        }
    },
    validate.get("CHANNEL")
)

_stream_schema = validate.Schema(
    {
        validate.optional("view_url"): validate.url(
            scheme=validate.any("rtmp", "http")
        ),
        "stream_status": validate.text
    }
)


class AfreecaTV(Plugin):
    login_url = "https://member.afreecatv.com:8111/login/LoginAction.php"

    arguments = PluginArguments(
        PluginArgument(
            "username",
            requires=["password"],
            metavar="USERNAME",
            help="The username used to register with afreecatv.com."
Exemple #54
0
class IDF1(Plugin):
    DACAST_API_URL = 'https://json.dacast.com/b/{}/{}/{}'
    DACAST_TOKEN_URL = 'https://services.dacast.com/token/i/b/{}/{}/{}'

    _url_re = re.compile(
        r'http://www\.idf1\.fr/(videos/[^/]+/[^/]+\.html|live\b)')
    _video_id_re = re.compile(
        r"dacast\('(?P<broadcaster_id>\d+)_(?P<video_type>[a-z]+)_(?P<video_id>\d+)', 'replay_content', data\);"
    )
    _video_id_alt_re = re.compile(
        r'<script src="//player.dacast.com/js/player.js" id="(?P<broadcaster_id>\d+)_(?P<video_type>[cf])_(?P<video_id>\d+)"'
    )
    _player_url = 'http://ssl.p.jwpcdn.com/player/v/7.12.6/jwplayer.flash.swf'

    _api_schema = validate.Schema(
        validate.transform(parse_json), {
            validate.optional('html5'): validate.all([
                {
                    'src': validate.url()
                },
            ], ),
            'hls': validate.url(),
            'hds': validate.url()
        },
        validate.transform(
            lambda x: [update_scheme(IDF1.DACAST_API_URL, x['hls']), x['hds']
                       ] + [y['src'] for y in x.get('html5', [])]))

    _token_schema = validate.Schema(validate.transform(parse_json),
                                    {'token': validate.text},
                                    validate.get('token'))

    _user_agent = useragents.IE_11

    @classmethod
    def can_handle_url(cls, url):
        return IDF1._url_re.match(url)

    def _get_streams(self):
        res = self.session.http.get(self.url)
        match = self._video_id_re.search(
            res.text) or self._video_id_alt_re.search(res.text)
        if match is None:
            return
        broadcaster_id = match.group('broadcaster_id')
        video_type = match.group('video_type')
        video_id = match.group('video_id')

        videos = self.session.http.get(self.DACAST_API_URL.format(
            broadcaster_id, video_type, video_id),
                                       schema=self._api_schema)
        token = self.session.http.get(self.DACAST_TOKEN_URL.format(
            broadcaster_id, video_type, video_id),
                                      schema=self._token_schema)
        parsed = []

        for video_url in videos:
            video_url += token

            # Ignore duplicate video URLs
            if video_url in parsed:
                continue
            parsed.append(video_url)

            # Ignore HDS streams (broken)
            if '.m3u8' in video_url:
                for s in HLSStream.parse_variant_playlist(
                        self.session, video_url).items():
                    yield s
Exemple #55
0
from streamlink.plugin import Plugin
from streamlink.plugin.api import http, validate
from streamlink.stream import HLSStream

STREAM_INFO_URL = "https://api.periscope.tv/api/v2/getAccessPublic"

STATUS_GONE = 410
STATUS_UNAVAILABLE = (STATUS_GONE,)

_url_re = re.compile(r"http(s)?://(www\.)?(periscope|pscp)\.tv/[^/]+/(?P<broadcast_id>[\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
Exemple #56
0
""", re.VERBOSE)

_room_id_schema = validate.Schema(
    {
        "data": validate.any(None, {
            "room_id": int,
            "live_status": int
        })
    },
    validate.get("data")
)

_room_stream_list_schema = validate.Schema(
    {
        "data": validate.any(None, {
            "durl": [{"url": validate.url()}]
        })
    },
    validate.get("data")
)


class Bilibili(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], "Bilibili"