def test_parse_xml_validate(self): expected = ET.Element("test", {"foo": "bar"}) actual = parse_xml(u"""<test foo="bar"/>""", schema=validate.Schema( xml_element(tag="test", attrib={"foo": text}))) self.assertEqual(expected.tag, actual.tag) self.assertEqual(expected.attrib, actual.attrib)
def _get_show_streams(self, stream_data, show, episode, platform="desktop"): video_id = parse_json(stream_data.group(1), schema=self.vod_id_schema) res = http.get(self.vod_api, params={ "platform": platform, "id": video_id }) # create a unique list of the stream manifest URLs streams = [] urldups = [] for stream in parse_xml(res.text, schema=self._vod_api_schema): if stream["url"] not in urldups: streams.append(stream) urldups.append(stream["url"]) mapper = StreamMapper(lambda fmt, strm: strm["url"].endswith(fmt)) mapper.map(".m3u8", self._make_hls_hds_stream, HLSStream.parse_variant_playlist) mapper.map(".f4m", self._make_hls_hds_stream, HDSStream.parse_manifest, is_akamai=True) mapper.map( ".mp4", lambda s: (s["bitrate"] + "k", HTTPStream(self.session, s["url"]))) for q, s in mapper(streams): yield q, s
def test_parse_xml_entities(self): expected = ET.Element("test", {"foo": "bar &"}) actual = parse_xml(u"""<test foo="bar &"/>""", schema=validate.Schema(xml_element(tag="test", attrib={"foo": text})), invalid_char_entities=True) self.assertEqual(expected.tag, actual.tag) self.assertEqual(expected.attrib, actual.attrib)
def test_parse_xml_entities(self): expected = ET.Element("test", {"foo": "bar &"}) actual = parse_xml("""<test foo="bar &"/>""", schema=validate.Schema(xml_element(tag="test", attrib={"foo": text})), invalid_char_entities=True) self.assertEqual(expected.tag, actual.tag) self.assertEqual(expected.attrib, actual.attrib)
def _get_show_streams(self, stream_data, show, episode, platform="desktop"): video_id = parse_json(stream_data.group(1), schema=self.vod_id_schema) res = http.get(self.vod_api, params={"platform": platform, "id": video_id}) # create a unique list of the stream manifest URLs streams = [] urldups = [] for stream in parse_xml(res.text, schema=self._vod_api_schema): if stream["url"] not in urldups: streams.append(stream) urldups.append(stream["url"]) mapper = StreamMapper(lambda fmt, strm: strm["url"].endswith(fmt)) mapper.map(".m3u8", self._make_hls_hds_stream, HLSStream.parse_variant_playlist) mapper.map(".f4m", self._make_hls_hds_stream, HDSStream.parse_manifest, is_akamai=True) mapper.map(".mp4", lambda s: (s["bitrate"] + "k", HTTPStream(self.session, s["url"]))) for q, s in mapper(streams): yield q, s
def parse_manifest(cls, session, url_or_manifest, **args): """ Attempt to parse a DASH manifest file and return its streams :param session: Streamlink session instance :param url_or_manifest: URL of the manifest file or an XML manifest string :return: a dict of name -> DASHStream instances """ if url_or_manifest.startswith('<?xml'): mpd = MPD(parse_xml(url_or_manifest, ignore_ns=True)) else: res = session.http.get(url_or_manifest, **args) url = res.url urlp = list(urlparse(url)) urlp[2], _ = urlp[2].rsplit("/", 1) mpd = MPD(session.http.xml(res, ignore_ns=True), base_url=urlunparse(urlp), url=url) video, audio = [], [] # Search for suitable video and audio representations for aset in mpd.periods[0].adaptationSets: if aset.contentProtection: raise PluginError("{} is protected by DRM".format(url)) for rep in aset.representations: if rep.mimeType.startswith("video"): video.append(rep) elif rep.mimeType.startswith("audio"): audio.append(rep) if not video: video = [None] if not audio: audio = [None] locale = session.localization locale_lang = locale.language lang = None available_languages = set() # if the locale is explicitly set, prefer that language over others for aud in audio: if aud and aud.lang: available_languages.add(aud.lang) try: if locale.explicit and aud.lang and Language.get( aud.lang) == locale_lang: lang = aud.lang except LookupError: continue if not lang: # filter by the first language that appears lang = audio[0] and audio[0].lang log.debug( "Available languages for DASH audio streams: {0} (using: {1})". format(", ".join(available_languages) or "NONE", lang or "n/a")) # if the language is given by the stream, filter out other languages that do not match if len(available_languages) > 1: audio = list( filter(lambda a: a.lang is None or a.lang == lang, audio)) ret = [] for vid, aud in itertools.product(video, audio): stream = DASHStream(session, mpd, vid, aud, **args) stream_name = [] if vid: stream_name.append("{:0.0f}{}".format( vid.height or vid.bandwidth_rounded, "p" if vid.height else "k")) if audio and len(audio) > 1: stream_name.append("a{:0.0f}k".format(aud.bandwidth)) ret.append(('+'.join(stream_name), stream)) # rename duplicate streams dict_value_list = defaultdict(list) for k, v in ret: dict_value_list[k].append(v) ret_new = {} for q in dict_value_list: items = dict_value_list[q] for n in range(len(items)): if n == 0: ret_new[q] = items[n] elif n == 1: ret_new[f'{q}_alt'] = items[n] else: ret_new[f'{q}_alt{n}'] = items[n] return ret_new
def test_parse_xml_ns(self): expected = ET.Element("{foo:bar}test", {"foo": "bar"}) actual = parse_xml(u"""<h:test foo="bar" xmlns:h="foo:bar"/>""") self.assertEqual(expected.tag, actual.tag) self.assertEqual(expected.attrib, actual.attrib)
def test_parse_xml_ns_ignore_tab(self): expected = ET.Element("test", {"foo": "bar"}) actual = parse_xml(u"""<test foo="bar" xmlns="foo:bar"/>""", ignore_ns=True) self.assertEqual(expected.tag, actual.tag) self.assertEqual(expected.attrib, actual.attrib)
def test_parse_xml_ns(self): expected = ET.Element("{foo:bar}test", {"foo": "bar"}) actual = parse_xml(u"""<h:test foo="bar" xmlns:h="foo:bar"/>""") self.assertEqual(expected.tag, actual.tag) self.assertEqual(expected.attrib, actual.attrib)
def test_parse_xml_ns_ignore_tab(self): expected = ET.Element("test", {"foo": "bar"}) actual = parse_xml(u"""<test foo="bar" xmlns="foo:bar"/>""", ignore_ns=True) self.assertEqual(expected.tag, actual.tag) self.assertEqual(expected.attrib, actual.attrib)
def xml(cls, res, *args, **kwargs): """Parses XML from a response.""" return parse_xml(res.text, *args, **kwargs)