Esempio n. 1
0
    def _get_streams(self):
        is_live = False

        info = self._get_stream_info(self.url)
        if not info:
            return

        if info.get("livestream") == '1' or info.get("live_playback") == '1':
            self.logger.debug("This video is live.")
            is_live = True

        formats = info.get("fmt_list")
        streams = {}
        protected = False
        for stream_info in info.get("url_encoded_fmt_stream_map", []):
            if stream_info.get("s"):
                protected = True
                continue

            stream = HTTPStream(self.session, stream_info["url"])
            name = formats.get(stream_info["itag"]) or stream_info["quality"]

            if stream_info.get("stereo3d"):
                name += "_3d"

            streams[name] = stream

        if is_live is False:
            streams, protected = self._create_adaptive_streams(
                info, streams, protected)

        hls_playlist = info.get("hlsvp")
        if hls_playlist:
            parsed = urlparse(self.url)
            params = parse_query(parsed.query)
            time_offset = params.get("t")
            if time_offset:
                self.session.set_option("hls-start-offset",
                                        time_to_offset(params.get("t")))

            try:
                hls_streams = HLSStream.parse_variant_playlist(
                    self.session,
                    hls_playlist,
                    headers=HLS_HEADERS,
                    namekey="pixels")
                streams.update(hls_streams)
            except IOError as err:
                self.logger.warning("Failed to extract HLS streams: {0}", err)

        if not streams and protected:
            raise PluginError("This plugin does not support protected videos, "
                              "try youtube-dl instead")

        return streams
Esempio n. 2
0
    def _get_video_streams(self):
        self.logger.debug("Getting video steams for {0} (type={1})".format(
            self.video_id, self.video_type))
        self._authenticate()

        if self.video_type == "b":
            self.video_type = "a"

        try:
            videos = self.api.videos(self.video_type + self.video_id,
                                     schema=_video_schema)
        except PluginError as err:
            if "HTTP/1.1 0 ERROR" in str(err):
                raise NoStreamsError(self.url)
            else:
                raise

        # Parse the "t" query parameter on broadcasts and adjust
        # start offset if needed.
        time_offset = self.params.get("t")
        if time_offset:
            videos["start_offset"] += time_to_offset(self.params.get("t"))

        return self._create_playlist_streams(videos)
Esempio n. 3
0
    def _get_streams(self):
        info = self._get_stream_info(self.url)
        if not info:
            return

        formats = info.get("fmt_list")
        streams = {}
        protected = False
        for stream_info in info.get("url_encoded_fmt_stream_map", []):
            if stream_info.get("s"):
                protected = True
                continue

            stream = HTTPStream(self.session, stream_info["url"])
            name = formats.get(stream_info["itag"]) or stream_info["quality"]

            if stream_info.get("stereo3d"):
                name += "_3d"

            streams[name] = stream

        adaptive_streams = {}
        best_audio_itag = None

        # Extract audio streams from the DASH format list
        for stream_info in info.get("adaptive_fmts", []):
            if stream_info.get("s"):
                protected = True
                continue

            stream_params = dict(parse_qsl(stream_info["url"]))
            if "itag" not in stream_params:
                continue
            itag = int(stream_params["itag"])
            # extract any high quality streams only available in adaptive formats
            adaptive_streams[itag] = stream_info["url"]

            stream_type, stream_format = stream_info["type"]
            if stream_type == "audio":
                stream = HTTPStream(self.session, stream_info["url"])
                name = "audio_{0}".format(stream_format)
                streams[name] = stream

                # find the best quality audio stream m4a, opus or vorbis
                if best_audio_itag is None or self.adp_audio[
                        itag] > self.adp_audio[best_audio_itag]:
                    best_audio_itag = itag

        if best_audio_itag and adaptive_streams and MuxedStream.is_usable(
                self.session):
            aurl = adaptive_streams[best_audio_itag]
            for itag, name in self.adp_video.items():
                if itag in adaptive_streams:
                    vurl = adaptive_streams[itag]
                    streams[name] = MuxedStream(self.session,
                                                HTTPStream(self.session, vurl),
                                                HTTPStream(self.session, aurl))

        hls_playlist = info.get("hlsvp")
        if hls_playlist:
            parsed = urlparse(self.url)
            params = parse_query(parsed.query)
            time_offset = params.get("t")
            if time_offset:
                self.session.set_option("hls-start-offset",
                                        time_to_offset(params.get("t")))

            try:
                hls_streams = HLSStream.parse_variant_playlist(
                    self.session,
                    hls_playlist,
                    headers=HLS_HEADERS,
                    namekey="pixels")
                streams.update(hls_streams)
            except IOError as err:
                self.logger.warning("Failed to extract HLS streams: {0}", err)

        if not streams and protected:
            raise PluginError("This plugin does not support protected videos, "
                              "try youtube-dl instead")

        return streams
Esempio n. 4
0
    def _get_hls_streams(self, stream_type="live"):
        self.logger.debug("Getting {0} HLS streams for {1}".format(
            stream_type, self.channel))
        self._authenticate()
        self._hosted_chain.append(self.channel)

        time_offset = self.params.get("t")
        if time_offset:
            self.session.set_option("hls-start-offset",
                                    time_to_offset(self.params.get("t")))

        if stream_type == "live":
            hosted_channel = self._check_for_host()
            if hosted_channel and self.options.get("disable_hosting"):
                self.logger.info("hosting was disabled by command line option")
            elif hosted_channel:
                self.logger.info("switching to {0}", hosted_channel)
                if hosted_channel in self._hosted_chain:
                    self.logger.error(
                        u"A loop of hosted channels has been detected, "
                        "cannot find a playable stream. ({0})".format(
                            u" -> ".join(self._hosted_chain +
                                         [hosted_channel])))
                    return {}
                self.channel = hosted_channel
                return self._get_hls_streams(stream_type)

            # only get the token once the channel has been resolved
            sig, token = self._access_token(stream_type)
            url = self.usher.channel(self.channel, sig=sig, token=token)
        elif stream_type == "video":
            sig, token = self._access_token(stream_type)
            url = self.usher.video(self.video_id, nauthsig=sig, nauth=token)
        else:
            self.logger.debug(
                "Unknown HLS stream type: {0}".format(stream_type))
            return {}

        try:
            # If the stream is a VOD that is still being recorded the stream should start at the
            # beginning of the recording
            streams = HLSStream.parse_variant_playlist(
                self.session, url, force_restart=not stream_type == "live")
        except IOError as err:
            err = str(err)
            if "404 Client Error" in err or "Failed to parse playlist" in err:
                return
            else:
                raise PluginError(err)

        try:
            token = parse_json(token, schema=_token_schema)
            for name in token["restricted_bitrates"]:
                if name not in streams:
                    self.logger.warning(
                        "The quality '{0}' is not available "
                        "since it requires a subscription.", name)
        except PluginError:
            pass

        return streams
Esempio n. 5
0
 def test_time_to_offset(self):
     self.assertEqual(4953, time_to_offset("01h22m33s"))
     self.assertEqual(0, time_to_offset("123123fail"))