def fragment_url(self, segment, fragment): url = absolute_url(self.stream.baseurl, self.stream.url) return FRAGMENT_URL.format(url=url, segment=segment, fragment=fragment, identifier="", quality="")
def _create_video_stream(self, cls, base_url, bitrate): url = absolute_url(base_url, bitrate["url"]) if bitrate["label"].lower() == "auto": try: return cls.parse_variant_playlist(self.session, url).items() except IOError as err: log.warning("Failed to extract HLS streams: {0}".format(err)) return quality = self._get_quality(bitrate["label"]) return quality, cls(self.session, url)
def _create_video_stream(self, cls, base_url, bitrate): url = absolute_url(base_url, bitrate["url"]) if bitrate["label"].lower() == "auto": try: return cls.parse_variant_playlist(self.session, url).items() except IOError as err: self.logger.warning("Failed to extract HLS streams: {0}", err) return quality = self._get_quality(bitrate["label"]) return quality, cls(self.session, url)
def test_absolute_url(self): self.assertEqual("http://test.se/test", absolute_url("http://test.se", "/test")) self.assertEqual( "http://test2.se/test", absolute_url("http://test.se", "http://test2.se/test"))
def test_absolute_url(self): self.assertEqual("http://test.se/test", absolute_url("http://test.se", "/test")) self.assertEqual("http://test2.se/test", absolute_url("http://test.se", "http://test2.se/test"))
def parse_manifest(cls, session, url, timeout=60, pvswf=None, is_akamai=False, **request_params): """Parses a HDS manifest and returns its substreams. :param url: The URL to the manifest. :param timeout: How long to wait for data to be returned from from the stream before raising an error. :param is_akamai: force adding of the akamai parameters :param pvswf: URL of player SWF for Akamai HD player verification. """ # private argument, should only be used in recursive calls raise_for_drm = request_params.pop("raise_for_drm", False) if not request_params: request_params = {} request_params["headers"] = request_params.get("headers", {}) request_params["params"] = request_params.get("params", {}) # These params are reserved for internal use request_params.pop("exception", None) request_params.pop("stream", None) request_params.pop("timeout", None) request_params.pop("url", None) if "akamaihd" in url or is_akamai: request_params["params"]["hdcore"] = HDCORE_VERSION request_params["params"]["g"] = cls.cache_buster_string(12) res = session.http.get(url, exception=IOError, **request_params) manifest = session.http.xml(res, "manifest XML", ignore_ns=True, exception=IOError) if manifest.findtext("drmAdditionalHeader"): log.debug(f"Omitting HDS stream protected by DRM: {url}") if raise_for_drm: raise PluginError("{} is protected by DRM".format(url)) log.warning("Some or all streams are unavailable as they are protected by DRM") return {} parsed = urlparse(url) baseurl = manifest.findtext("baseURL") baseheight = manifest.findtext("height") bootstraps = {} streams = {} if not baseurl: baseurl = urljoin(url, os.path.dirname(parsed.path)) if not baseurl.endswith("/"): baseurl += "/" for bootstrap in manifest.findall("bootstrapInfo"): name = bootstrap.attrib.get("id") or "_global" url = bootstrap.attrib.get("url") if url: box = absolute_url(baseurl, url) else: data = base64.b64decode(bytes(bootstrap.text, "utf8")) box = Box.deserialize(BytesIO(data)) bootstraps[name] = box pvtoken = manifest.findtext("pv-2.0") if pvtoken: if not pvswf: raise IOError("This manifest requires the 'pvswf' parameter " "to verify the SWF") params = cls._pv_params(session, pvswf, pvtoken, **request_params) request_params["params"].update(params) child_drm = False for media in manifest.findall("media"): url = media.attrib.get("url") bootstrapid = media.attrib.get("bootstrapInfoId", "_global") href = media.attrib.get("href") if url and bootstrapid: bootstrap = bootstraps.get(bootstrapid) if not bootstrap: continue bitrate = media.attrib.get("bitrate") streamid = media.attrib.get("streamId") height = media.attrib.get("height") if height: quality = height + "p" elif bitrate: quality = bitrate + "k" elif streamid: quality = streamid elif baseheight: quality = baseheight + "p" else: quality = "live" metadata = media.findtext("metadata") if metadata: metadata = base64.b64decode(bytes(metadata, "utf8")) metadata = ScriptData.deserialize(BytesIO(metadata)) else: metadata = None stream = HDSStream(session, baseurl, url, bootstrap, metadata=metadata, timeout=timeout, **request_params) streams[quality] = stream elif href: url = absolute_url(baseurl, href) try: child_streams = cls.parse_manifest(session, url, timeout=timeout, is_akamai=is_akamai, raise_for_drm=True, **request_params) except PluginError: child_drm = True child_streams = {} for name, stream in child_streams.items(): # Override stream name if bitrate is available in parent # manifest but not the child one. bitrate = media.attrib.get("bitrate") if bitrate and not re.match(r"^(\d+)k$", name): name = bitrate + "k" streams[name] = stream if child_drm: log.warning("Some or all streams are unavailable as they are protected by DRM") return streams