Пример #1
0
    def _get_live_streams(self, params, swf_url):
        for key, quality in QUALITY_MAP.items():
            key_url = "{0}URL".format(key)
            url = params.get(key_url)

            if not url:
                continue

            try:
                res = http.get(url, exception=IOError)
            except IOError:
                continue

            if quality == "hds":
                streams = HDSStream.parse_manifest(self.session, res.url)
                for name, stream in streams.items():
                    if key == "source":
                        name += "+"

                    yield name, stream
            elif res.text.startswith("rtmp"):
                match = _rtmp_re.match(res.text)
                if not match:
                    continue

                stream = RTMPStream(self.session, {
                    "rtmp": match.group("host"),
                    "app": match.group("app"),
                    "playpath": match.group("playpath"),
                    "swfVfy": swf_url,
                    "live": True
                })

                yield quality, stream
Пример #2
0
    def _get_live_streams(self, params, swf_url):
        for key, quality in QUALITY_MAP.items():
            key_url = "{0}URL".format(key)
            url = params.get(key_url)

            if not url:
                continue

            try:
                res = http.get(url, exception=IOError)
            except IOError:
                continue

            if quality == "hds":
                streams = HDSStream.parse_manifest(self.session, res.url)
                for name, stream in streams.items():
                    if key == "source":
                        name += "+"

                    yield name, stream
            elif res.text.startswith("rtmp"):
                match = _rtmp_re.match(res.text)
                if not match:
                    continue

                stream = RTMPStream(
                    self.session, {
                        "rtmp": match.group("host"),
                        "app": match.group("app"),
                        "playpath": match.group("playpath"),
                        "swfVfy": swf_url,
                        "live": True
                    })

                yield quality, stream
Пример #3
0
    def get_live_streams(self):
        res = self._get_live_page(self.res)

        match = re.search("flashvars\s+=\s+({.+?});", res.text)

        if not match:
            raise NoStreamsError(self.url)

        flashvars = parse_json(match.group(1), "flashvars JSON")
        flashvars["uip"] = self._get_user_ip()

        levels = re.findall("setFlashLevel\((\d+)\);", res.text)
        streams = {}

        for level in levels:
            params = self._create_gox_params(flashvars, level)

            res = urlget(self.GOXLiveURL, params=params,
                         session=self.rsession)
            gox = GOXFile(res.text)

            for entry in gox.filter_entries("live"):
                try:
                    s = HDSStream.parse_manifest(self.session, entry.ref[0])
                    streams.update(s)
                except IOError:
                    self.logger.warning("Unable to parse manifest")

                break

        return streams
Пример #4
0
    def get_alt_live_streams(self):
        res = self._get_live_page(self.res)

        match = re.search('jQuery.post\("/live/ajaxGetUrl.gom", ({.+?}),',
                          res.text)
        if not match:
            raise NoStreamsError(self.url)

        ajaxparams = match.group(1)
        ajaxparams = dict(re.findall("(\w+):(\d+)", ajaxparams))

        levels = re.findall("setFlashLevel\((\d+)\);.+?<span class=\"qtype\">(\w+)</span>", res.text)
        streams = {}

        for level, quality in levels:
            params = ajaxparams.copy()
            params["level"] = level
            quality = quality.lower()

            res = urlopen(self.GetStreamURL, data=params, session=self.rsession)
            url = unquote(res.text)

            if not urlparse(url).path.endswith(".f4m"):
                continue

            try:
                s = HDSStream.parse_manifest(self.session, url)
                if len(s) > 0:
                    bitrate, stream = list(s.items())[0]
                    streams[quality] = stream
            except IOError:
                self.logger.warning("Unable to parse manifest")

        return streams
Пример #5
0
    def _create_streams(self, type_, video_id):
        url = self._generate_security_url(type_, video_id)
        res = http.get(url)

        return HDSStream.parse_manifest(self.session,
                                        res.text,
                                        cookies=res.cookies)
Пример #6
0
    def _get_streams_from_id(self, stream_id):
        res = urlget(CONFIG_URL, params=dict(id=stream_id))
        config = res_json(res)
        media = verifyjson(config, "media")

        if not (media and isinstance(media, list)):
            return

        streams = {}
        media = media[0]
        hds_manifest = media.get("name")
        hls_manifest = media.get("hlsUrl")

        if hds_manifest:
            try:
                hds_streams = HDSStream.parse_manifest(self.session,
                                                       hds_manifest)
                streams.update(hds_streams)
            except IOError as err:
                if not re.search(r"(404|400) Client Error", str(err)):
                    self.logger.error("Failed to parse HDS manifest: {0}", err)

        if hls_manifest:
            try:
                hls_streams = HLSStream.parse_variant_playlist(self.session,
                                                               hls_manifest,
                                                               nameprefix="mobile_")
                streams.update(hls_streams)
            except IOError as err:
                if not re.search(r"(404|400) Client Error", str(err)):
                    self.logger.error("Failed to parse HLS playlist: {0}", err)

        return streams
Пример #7
0
    def _get_streams(self):
        match = _url_re.match(self.url)
        video_id = match.group("video_id")
        res = http.get(ASSET_URL.format(video_id))
        assets = http.xml(res, schema=_asset_schema)

        streams = {}
        for asset in assets:
            base = asset["base"]
            url = asset["url"]

            if urlparse(url).path.endswith(".f4m"):
                streams.update(
                    HDSStream.parse_manifest(self.session, url, pvswf=SWF_URL)
                )
            elif base.startswith("rtmp"):
                name = "{0}k".format(asset["bitrate"])
                params = {
                    "rtmp": asset["base"],
                    "playpath": url,
                    "live": True
                }
                streams[name] = RTMPStream(self.session, params)

        return streams
Пример #8
0
    def get_live_streams(self):
        res = self._get_live_page(self.res)

        match = re.search("flashvars\s+=\s+({.+?});", res.text)

        if not match:
            raise NoStreamsError(self.url)

        flashvars = parse_json(match.group(1), "flashvars JSON")
        flashvars["uip"] = self._get_user_ip()

        levels = re.findall("setFlashLevel\((\d+)\);", res.text)
        streams = {}

        for level in levels:
            params = self._create_gox_params(flashvars, level)

            res = urlget(self.GOXLiveURL, params=params, session=self.rsession)
            gox = GOXFile(res.text)

            for entry in gox.filter_entries("live"):
                try:
                    s = HDSStream.parse_manifest(self.session, entry.ref[0])
                    streams.update(s)
                except IOError:
                    self.logger.warning("Unable to parse manifest")

                break

        return streams
Пример #9
0
    def _get_streams(self):
        if not RTMPStream.is_usable(self.session):
            self.logger.warning("rtmpdump is not usable, only HDS streams will be available")

        self.logger.debug("Fetching stream info")
        match = re.search("/\w*/(live|video)*/(\d+)", self.url)
        if not match:
            return

        stream_id = match.group(2)
        res = http.get(API_URL, params=dict(ak="web", id=stream_id))
        root = parse_xml(res.text.encode("utf8"))

        streams = {}
        for formitaet in root.iter('formitaet'):
            url = formitaet.find('url').text
            quality = formitaet.find('quality').text

            if formitaet.get('basetype') == "h264_aac_f4f_http_f4m_http":
                hds_streams = HDSStream.parse_manifest(self.session, url)
                streams.update(hds_streams)
            elif formitaet.get('basetype') == 'h264_aac_mp4_rtmp_zdfmeta_http':
                streams[quality] = RTMPStream(self.session, {
                    "rtmp": self._get_stream(url),
                    "pageUrl": self.url,
                })

        return streams
Пример #10
0
    def _get_streams(self):
        res = http.get(self.url)
        match = _manifest_re.search(res.content)
        manifest = match.group(1)
        streams = {}
        streams.update(
            HDSStream.parse_manifest(self.session, manifest, pvswf=SWF_URL))

        return streams
Пример #11
0
 def _get_streams(self):
     res = http.get(self.url)
     match = _manifest_re.search(res.text)
     manifest = match.group(1)
     streams = {}
     streams.update(
         HDSStream.parse_manifest(self.session, manifest, pvswf=SWF_URL)
     )
     
     return streams
Пример #12
0
    def _get_smil_streams(self, info):
        res = http.get(info["_stream"])
        smil = http.xml(res, "SMIL config", schema=_smil_schema)

        streams = {}
        for video in smil["videos"]:
            url = "{0}/{1}{2}".format(smil["base"], video, HDCORE_PARAMETER)
            streams.update(
                HDSStream.parse_manifest(self.session, url, pvswf=SWF_URL))

        return streams
Пример #13
0
    def _get_smil_streams(self, info):
        res = http.get(info["_stream"])
        smil = http.xml(res, "SMIL config", schema=_smil_schema)

        for video in smil["videos"]:
            url = "{0}/{1}{2}".format(smil["base"], video, HDCORE_PARAMETER)
            streams = HDSStream.parse_manifest(self.session, url, pvswf=SWF_URL)

            # TODO: Replace with "yield from" when dropping Python 2.
            for stream in streams.items():
                yield stream
Пример #14
0
    def _get_smil_streams(self, info):
        res = http.get(info["_stream"])
        smil = http.xml(res, "SMIL config", schema=_smil_schema)

        streams = {}
        for video in smil["videos"]:
            url = "{0}/{1}{2}".format(smil["base"], video, HDCORE_PARAMETER)
            streams.update(
                HDSStream.parse_manifest(self.session, url, pvswf=SWF_URL)
            )

        return streams
Пример #15
0
    def _get_streams(self):
        res = http.get(self.url)

        match = _meta_xmlurl_id_re.search(res.text)
        if not match:
            return

        xml_info_url = STREAMS_INFO_URL.format(match.group(1))
        video_info_res = http.get(xml_info_url)
        parsed_info = http.xml(video_info_res)

        live_el = parsed_info.find("live")
        live = live_el is not None and live_el.text == "1"

        streams = {}

        hdsurl_el = parsed_info.find("hdsurl")
        if hdsurl_el is not None and hdsurl_el.text is not None:
            hdsurl = hdsurl_el.text
            streams.update(HDSStream.parse_manifest(self.session, hdsurl))

        if live:
            vurls_el = parsed_info.find("vurls")
            if vurls_el is not None:
                for i, vurl_el in enumerate(vurls_el):
                    bitrate = vurl_el.get("bitrate")
                    name = bitrate + "k" if bitrate is not None else "rtmp{0}".format(
                        i)
                    params = {
                        "rtmp": vurl_el.text,
                    }
                    streams[name] = RTMPStream(self.session, params)

        parsed_urls = set()
        mobileurls_el = parsed_info.find("mobileurls")
        if mobileurls_el is not None:
            for mobileurl_el in mobileurls_el:
                text = mobileurl_el.text
                if not text:
                    continue

                if text in parsed_urls:
                    continue

                parsed_urls.add(text)
                url = urlparse(text)

                if url[0] == "http" and url[2].endswith("m3u8"):
                    streams.update(
                        HLSStream.parse_variant_playlist(self.session, text))

        return streams
Пример #16
0
    def _get_smil_streams(self, info):
        res = http.get(info["_stream"])
        smil = http.xml(res, "SMIL config", schema=_smil_schema)

        for video in smil["videos"]:
            url = "{0}/{1}{2}".format(smil["base"], video, HDCORE_PARAMETER)
            streams = HDSStream.parse_manifest(self.session,
                                               url,
                                               pvswf=SWF_URL)

            # TODO: Replace with "yield from" when dropping Python 2.
            for stream in streams.items():
                yield stream
Пример #17
0
    def _get_streams(self):
        res = http.get(API_URL)
        data = http.json(res, schema=_schema)

        streams = {}
        for livestreams in data["live-streams"]:
            for stream in livestreams["streams"]:
                url = stream["streamUrl"]
                for name, stream in HDSStream.parse_manifest(self.session, url).items():
                    if name.endswith("k"):
                        streams[name] = stream

        return streams
Пример #18
0
    def _get_streams(self):
        res = http.get(API_URL)
        data = http.json(res, schema=_schema)

        streams = {}
        for livestreams in data["live-streams"]:
            for stream in livestreams["streams"]:
                url = stream["streamUrl"]
                for name, stream in HDSStream.parse_manifest(
                        self.session, url).items():
                    if name.endswith("k"):
                        streams[name] = stream

        return streams
Пример #19
0
 def _get_streams(self):
     res = http.get(self.url)
     
     match = _meta_xmlurl_id_re.search(res.text)
     if not match:
         return;
     
     xml_info_url = STREAMS_INFO_URL.format(match.group(1))
     video_info_res = http.get(xml_info_url)
     parsed_info = http.xml(video_info_res)
     
     live_el = parsed_info.find("live");
     live = live_el is not None and live_el.text == "1"
     
     streams = { }
     
     hdsurl_el = parsed_info.find("hdsurl");
     if hdsurl_el is not None and hdsurl_el.text is not None:
         hdsurl = hdsurl_el.text
         streams.update(HDSStream.parse_manifest(self.session, hdsurl))
         
     if live:
         vurls_el = parsed_info.find("vurls");
         if vurls_el is not None:
             for i, vurl_el in enumerate(vurls_el):
                 bitrate = vurl_el.get("bitrate")
                 name = bitrate + "k" if bitrate is not None else "rtmp{0}".format(i)
                 params = {
                     "rtmp": vurl_el.text,
                 }
                 streams[name] = RTMPStream(self.session, params)
                 
     parsed_urls = set()
     mobileurls_el = parsed_info.find("mobileurls");
     if mobileurls_el is not None:
         for mobileurl_el in mobileurls_el:
             text = mobileurl_el.text
             if not text:
                 continue
             
             if text in parsed_urls:
                 continue
             
             parsed_urls.add(text)
             url = urlparse(text)
             
             if url[0] == "http" and url[2].endswith("m3u8"):
                 streams.update(HLSStream.parse_variant_playlist(self.session, text))
     
     return streams
Пример #20
0
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = http.get(self.url, params=dict(output="json"))
        json = http.json(res)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")

        streams = {}
        video = verifyjson(json, "video")
        videos = verifyjson(video, "videoReferences")

        for video in videos:
            if not ("url" in video and "playerType" in video):
                continue

            url = video["url"]

            if video["playerType"] == "flash":
                if url.startswith("rtmp"):
                    stream = RTMPStream(
                        self.session, {
                            "rtmp": url,
                            "pageUrl": PAGE_URL,
                            "swfVfy": SWF_URL,
                            "live": True
                        })
                    streams[str(video["bitrate"]) + "k"] = stream
                elif "manifest.f4m" in url:
                    try:
                        hdsstreams = HDSStream.parse_manifest(
                            self.session, url)
                        streams.update(hdsstreams)
                    except IOError as err:
                        self.logger.warning("Failed to get HDS manifest: {0}",
                                            err)

            elif video["playerType"] == "ios":
                try:
                    hlsstreams = HLSStream.parse_variant_playlist(
                        self.session, url)
                    streams.update(hlsstreams)
                except IOError as err:
                    self.logger.warning("Failed to get variant playlist: {0}",
                                        err)

        return streams
Пример #21
0
    def _get_streams(self):
        match = _url_re.match(self.url)
        stream_id = match.group("stream_id") or self._find_stream_id()
        if not stream_id:
            return

        res = http.get(STREAM_API_URL.format(stream_id))
        stream_info = http.json(res, schema=_stream_schema)
        streams = {}
        swf_url = None
        for name, stream_url in stream_info.items():
            if stream_url.endswith(".m3u8"):
                try:
                    streams.update(
                        HLSStream.parse_variant_playlist(self.session, stream_url)
                    )
                except IOError as err:
                    self.logger.error("Failed to fetch HLS streams: {0}", err)
            elif stream_url.endswith(".f4m"):
                try:
                    streams.update(
                        HDSStream.parse_manifest(self.session, stream_url)
                    )
                except IOError as err:
                    self.logger.error("Failed to fetch HDS streams: {0}", err)
            elif stream_url.startswith("rtmp://"):
                swf_url = swf_url or self._get_swf_url()
                params = {
                    "rtmp": stream_url,
                    "pageUrl": self.url,
                    "swfVfy": swf_url,
                }

                if stream_url.endswith(".mp4"):
                    tcurl, playpath = rtmpparse(stream_url)
                    params["rtmp"] = tcurl
                    params["playpath"] = playpath
                else:
                    params["live"] = True

                streams[name] = RTMPStream(self.session, params)

        return streams
Пример #22
0
    def _get_streams(self):
        self.logger.debug("Fetching stream info")
        res = http.get(self.url, params=dict(output="json"))
        json = http.json(res)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")

        streams = {}
        video = verifyjson(json, "video")
        videos = verifyjson(video, "videoReferences")

        for video in videos:
            if not ("url" in video and "playerType" in video):
                continue

            url = video["url"]

            if video["playerType"] == "flash":
                if url.startswith("rtmp"):
                    stream = RTMPStream(self.session, {
                        "rtmp": url,
                        "pageUrl": PAGE_URL,
                        "swfVfy": SWF_URL,
                        "live": True
                    })
                    streams[str(video["bitrate"]) + "k"] = stream
                elif "manifest.f4m" in url:
                    try:
                        hdsstreams = HDSStream.parse_manifest(self.session, url)
                        streams.update(hdsstreams)
                    except IOError as err:
                        self.logger.warning("Failed to get HDS manifest: {0}", err)

            elif video["playerType"] == "ios":
                try:
                    hlsstreams = HLSStream.parse_variant_playlist(self.session, url)
                    streams.update(hlsstreams)
                except IOError as err:
                    self.logger.warning("Failed to get variant playlist: {0}", err)

        return streams
Пример #23
0
    def _get_streams(self):
        match = _url_re.match(self.url)
        video_id = match.group("video_id")
        res = http.get(ASSET_URL.format(video_id))
        assets = http.xml(res, schema=_asset_schema)

        streams = {}
        for asset in assets:
            base = asset["base"]
            url = asset["url"]

            if urlparse(url).path.endswith(".f4m"):
                streams.update(
                    HDSStream.parse_manifest(self.session, url, pvswf=SWF_URL))
            elif base.startswith("rtmp"):
                name = "{0}k".format(asset["bitrate"])
                params = {"rtmp": asset["base"], "playpath": url, "live": True}
                streams[name] = RTMPStream(self.session, params)

        return streams
Пример #24
0
    def get_alt_live_streams(self):
        res = self._get_live_page(self.res)

        match = re.search('jQuery.post\("/live/ajaxGetUrl.gom", ({.+?}),',
                          res.text)
        if not match:
            raise NoStreamsError(self.url)

        ajaxparams = match.group(1)
        ajaxparams = dict(re.findall("(\w+):(\d+)", ajaxparams))

        levels = re.findall(
            "setFlashLevel\((\d+)\);.+?<span class=\"qtype\">(\w+)</span>",
            res.text)
        streams = {}

        for level, quality in levels:
            params = ajaxparams.copy()
            params["level"] = level
            quality = quality.lower()

            res = urlopen(self.GetStreamURL,
                          data=params,
                          session=self.rsession)
            url = unquote(res.text)

            if not urlparse(url).path.endswith(".f4m"):
                continue

            try:
                s = HDSStream.parse_manifest(self.session, url)
                if len(s) > 0:
                    bitrate, stream = list(s.items())[0]
                    streams[quality] = stream
            except IOError:
                self.logger.warning("Unable to parse manifest")

        return streams
Пример #25
0
    def get_alt_live_streams(self):
        res = self._get_live_page(self.res)

        match = re.search('jQuery.post\("/live/ajaxGetUrl.gom", ({.+?}),',
                          res.text)
        if not match:
            raise NoStreamsError(self.url)

        ajaxparams = match.group(1)
        ajaxparams = dict(re.findall("(\w+):(\d+)", ajaxparams))

        levels = re.findall("setFlashLevel\((\d+)\);", res.text)
        streams = {}

        for level in levels:
            params = ajaxparams.copy()
            params["level"] = level

            res = urlopen(self.GetStreamURL, data=params, session=self.rsession)
            url = unquote(res.text)

            if not urlparse(url).path.endswith(".f4m"):
                continue

            try:
                s = HDSStream.parse_manifest(self.session, url)
                streams.update(s)
            except IOError:
                self.logger.warning("Unable to parse manifest")

        # Hack to rename incorrect bitrate specified by GOM to something
        # more sane.
        for name, stream in streams.items():
            if name == "1k":
                streams["1000k"] = stream
                del streams[name]

        return streams
Пример #26
0
    def _get_vod_streams(self, params):
        manifest_url = params.get("autoURL")
        if not manifest_url:
            return

        res = http.get(manifest_url)
        if res.headers.get("Content-Type") == "application/f4m+xml":
            streams = HDSStream.parse_manifest(self.session, res.url)

            # TODO: Replace with "yield from" when dropping Python 2.
            for __ in streams.items():
                yield __
        else:
            manifest = http.json(res, schema=_vod_manifest_schema)
            for params in manifest["alternates"]:
                name = "{0}p".format(params["height"])
                stream = self._create_flv_playlist(params["template"])
                yield name, stream

                failovers = params.get("failover", [])
                for failover in failovers:
                    stream = self._create_flv_playlist(failover)
                    yield name, stream
Пример #27
0
    def _get_vod_streams(self, params):
        manifest_url = params.get("autoURL")
        if not manifest_url:
            return

        res = http.get(manifest_url)
        if res.headers.get("Content-Type") == "application/f4m+xml":
            streams = HDSStream.parse_manifest(self.session, res.url)

            # TODO: Replace with "yield from" when dropping Python 2.
            for __ in streams.items():
                yield __
        else:
            manifest = http.json(res, schema=_vod_manifest_schema)
            for params in manifest["alternates"]:
                name = "{0}p".format(params["height"])
                stream = self._create_flv_playlist(params["template"])
                yield name, stream

                failovers = params.get("failover", [])
                for failover in failovers:
                    stream = self._create_flv_playlist(failover)
                    yield name, stream
Пример #28
0
 def _get_hds_streams(self, info):
     # Needs the hdcore parameter added
     url = info["_stream"] + HDCORE_PARAMETER
     return HDSStream.parse_manifest(self.session, url,
                                     pvswf=SWF_URL).items()
Пример #29
0
    def _create_streams(self, type_, video_id):
        url = self._generate_security_url(type_, video_id)
        res = http.get(url)

        return HDSStream.parse_manifest(self.session, res.text, cookies=res.cookies)
Пример #30
0
    def _get_rtmp_streams(self, channelname):
        self.logger.debug("Fetching stream info")
        res = http.get(STREAM_INFO_URL.format(channelname))
        json = http.json(res)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")

        if not json:
            raise PluginError("JSON is empty")

        # This is ugly, not sure how to fix it.
        back_json_node = json["sequence"][0]["layerList"][0]
        if back_json_node["name"] != "background":
            raise PluginError("JSON data has unexpected structure")

        rep_node = self._get_node_by_name(back_json_node["sequenceList"], "reporting")["layerList"]
        main_node = self._get_node_by_name(back_json_node["sequenceList"], "main")["layerList"]

        if not (rep_node and main_node):
            raise PluginError("Error parsing stream RTMP url")

        swfurl = self._get_node_by_name(rep_node, "reporting")["param"]["extraParams"]["videoSwfURL"]
        feeds_params = self._get_node_by_name(main_node, "video")["param"]

        if not (swfurl and feeds_params):
            raise PluginError("Error parsing stream RTMP url")


        # Different feed qualities are available are a dict under "live"
        # In some cases where there's only 1 quality available,
        # it seems the "live" is absent. We use the single stream available
        # under the "customURL" key.
        streams = {}
        if "mode" in feeds_params and feeds_params["mode"] == "live":
            for key, quality in QUALITY_MAP.items():
                url = feeds_params.get("{0}URL".format(key))
                if not url:
                    continue

                try:
                    res = http.get(url, exception=IOError)
                except IOError:
                    continue

                if quality == "hds":
                    hds_streams = HDSStream.parse_manifest(self.session,
                                                           res.url)
                    streams.update(hds_streams)
                else:
                    match = re.match(RTMP_SPLIT_REGEX, res.text)
                    if not match:
                        self.logger.warning("Failed to split RTMP URL: {0}",
                                            res.text)
                        continue

                    stream = RTMPStream(self.session, {
                        "rtmp": match.group("host"),
                        "app": match.group("app"),
                        "playpath": match.group("playpath"),
                        "swfVfy": swfurl,
                        "live": True
                    })

                    self.logger.debug("Adding URL: {0}", res.text)
                    streams[quality] = stream

        return streams
Пример #31
0
    def _get_hds_streams(self, info):
        # Needs the hdcore parameter added
        url = info["_stream"] + HDCORE_PARAMETER

        return HDSStream.parse_manifest(self.session, url, pvswf=SWF_URL)
Пример #32
0
    def _get_rtmp_streams(self, channelname):
        self.logger.debug("Fetching stream info")
        res = http.get(STREAM_INFO_URL.format(channelname))
        json = http.json(res)

        if not isinstance(json, dict):
            raise PluginError("Invalid JSON response")

        if not json:
            raise PluginError("JSON is empty")

        # This is ugly, not sure how to fix it.
        back_json_node = json["sequence"][0]["layerList"][0]
        if back_json_node["name"] != "background":
            raise PluginError("JSON data has unexpected structure")

        rep_node = self._get_node_by_name(back_json_node["sequenceList"],
                                          "reporting")["layerList"]
        main_node = self._get_node_by_name(back_json_node["sequenceList"],
                                           "main")["layerList"]

        if not (rep_node and main_node):
            raise PluginError("Error parsing stream RTMP url")

        swfurl = self._get_node_by_name(
            rep_node, "reporting")["param"]["extraParams"]["videoSwfURL"]
        feeds_params = self._get_node_by_name(main_node, "video")["param"]

        if not (swfurl and feeds_params):
            raise PluginError("Error parsing stream RTMP url")

        # Different feed qualities are available are a dict under "live"
        # In some cases where there's only 1 quality available,
        # it seems the "live" is absent. We use the single stream available
        # under the "customURL" key.
        streams = {}
        if "mode" in feeds_params and feeds_params["mode"] == "live":
            for key, quality in QUALITY_MAP.items():
                url = feeds_params.get("{0}URL".format(key))
                if not url:
                    continue

                try:
                    res = http.get(url, exception=IOError)
                except IOError:
                    continue

                if quality == "hds":
                    hds_streams = HDSStream.parse_manifest(
                        self.session, res.url)
                    streams.update(hds_streams)
                else:
                    match = re.match(RTMP_SPLIT_REGEX, res.text)
                    if not match:
                        self.logger.warning("Failed to split RTMP URL: {0}",
                                            res.text)
                        continue

                    stream = RTMPStream(
                        self.session, {
                            "rtmp": match.group("host"),
                            "app": match.group("app"),
                            "playpath": match.group("playpath"),
                            "swfVfy": swfurl,
                            "live": True
                        })

                    self.logger.debug("Adding URL: {0}", res.text)
                    streams[quality] = stream

        return streams
Пример #33
0
    def get_vod_streams(self):
        match = re.search("flashvars\s+=\s+({.+?});", self.res.text)

        if not match:
            raise NoStreamsError(self.url)

        flashvars = parse_json(match.group(1), "flashvars JSON")

        match = re.search("var jsonData\s+= eval \((.+?)\);",
                             self.res.text, re.DOTALL)

        if not match:
            raise NoStreamsError(self.url)

        playlists = parse_json(match.group(1), "playlist JSON")

        self.logger.info("Playlist items found:")
        for i, playlist in enumerate(playlists):
            for fvars in playlist:
                if self.url[-1] != "/":
                    url = self.url + "/"
                else:
                    url = self.url

                url = urljoin(url, "?set={1}&lang={0}".format(i,
                              fvars["set"]))

                self.logger.info("[Set {1} ({0})] {2}", self.Lang[i],
                                                        fvars["set"],
                                                        url)

        params = parse_qsd(urlparse(self.url).query)
        currentset = int(params.get("set", "1"))
        lang = int(params.get("lang", "0"))

        flashvars.update(playlists[lang][currentset - 1])
        flashvars["uip"] = self._get_user_ip()

        streams = {}

        for level in self.VODQualityLevels:
            params = self._create_gox_params(flashvars, level)

            res = urlget(self.GOXVODURL, params=params,
                         session=self.rsession)

            gox = GOXFile(res.text)
            entries = gox.filter_entries("vod")

            for entry in entries:
                try:
                    s = HDSStream.parse_manifest(self.session, entry.ref[0])
                    streams.update(s)
                except IOError:
                    self.logger.warning("Unable to parse manifest")

        if len(streams) == 0:
            self.logger.warning(("Unable to access any streams, "
                                 "make sure you have access to this VOD"))

        return streams