def __init__( self, url=None, defer_prefetch_init=False, on_progress_callback=None, on_complete_callback=None, proxies=None, ): """Construct a :class:`YouTube <YouTube>`. :param str url: A valid YouTube watch URL. :param bool defer_init: Defers executing any network requests. :param func on_progress_callback: (Optional) User defined callback function for stream download progress events. :param func on_complete_callback: (Optional) User defined callback function for stream download complete events. """ self.js = None # js fetched by js_url self.js_url = None # the url to the js, parsed from watch html # note: vid_info may eventually be removed. It sounds like it once had # additional formats, but that doesn't appear to still be the case. self.vid_info = None # content fetched by vid_info_url self.vid_info_url = None # the url to vid info, parsed from watch html self.watch_html = None # the html of /watch?v=<video_id> self.embed_html = None self.player_config_args = None # inline js in the html containing # streams self.age_restricted = None self.fmt_streams = [] # list of :class:`Stream <Stream>` instances self.caption_tracks = [] # video_id part of /watch?v=<video_id> self.video_id = extract.video_id(url) # https://www.youtube.com/watch?v=<video_id> self.watch_url = extract.watch_url(self.video_id) self.embed_url = extract.embed_url(self.video_id) # A dictionary shared between all instances of :class:`Stream <Stream>` # (Borg pattern). self.stream_monostate = { # user defined callback functions. 'on_progress': on_progress_callback, 'on_complete': on_complete_callback, } if proxies: install_proxy(proxies) if not defer_prefetch_init: self.prefetch_init()
def __init__( self, url=None, defer_prefetch_init=False, on_progress_callback=None, on_complete_callback=None, ): """Construct a :class:`YouTube <YouTube>`. :param str url: A valid YouTube watch URL. :param bool defer_init: Defers executing any network requests. :param func on_progress_callback: (Optional) User defined callback function for stream download progress events. :param func on_complete_callback: (Optional) User defined callback function for stream download complete events. """ self.js = None # js fetched by js_url self.js_url = None # the url to the js, parsed from watch html # note: vid_info may eventually be removed. It sounds like it once had # additional formats, but that doesn't appear to still be the case. self.vid_info = None # content fetched by vid_info_url self.vid_info_url = None # the url to vid info, parsed from watch html self.watch_html = None # the html of /watch?v=<video_id> self.player_config_args = None # inline js in the html containing # streams self.age_restricted = None self.fmt_streams = [] # list of :class:`Stream <Stream>` instances self.caption_tracks = [] # video_id part of /watch?v=<video_id> self.video_id = extract.video_id(url) # https://www.youtube.com/watch?v=<video_id> self.watch_url = extract.watch_url(self.video_id) self.embed_url = extract.embed_url(self.video_id) # A dictionary shared between all instances of :class:`Stream <Stream>` # (Borg pattern). self.stream_monostate = { # user defined callback functions. 'on_progress': on_progress_callback, 'on_complete': on_complete_callback, } if not defer_prefetch_init: self.prefetch_init()
def on_get(request, response): variables = {} video_id = request.get_param("id", required=True, store=variables) _type = request.get_param("type", required=False, store=variables, default="audio") _format = request.get_param("format", required=False, store=variables, default="mp4") # TODO: Handle quality filtering # quality = request.get_param_as_int("quality", required=False, store=variables, default="128") # TODO: Properly handle validation and API errors if _type not in ("video", "audio"): raise falcon.HTTPInvalidParam(param_name="type", msg="") if _format not in ("mp3", "mp4", "3gpp", "webm"): raise falcon.HTTPInvalidParam(param_name="format", msg="") if video_id in video_cache: video = video_cache[video_id] else: video = pytube.YouTube(watch_url(video_id)) video_cache[video_id] = video stream = video.streams.filter(type=_type, subtype=_format).first() if stream is None: raise falcon.HTTPBadRequest() try: filename = video.player_config_args["player_response"][ "videoDetails"]["title"] except KeyError: filename = video_id filename = safe_filename(filename, max_length=25) # Handle stream download manually response.downloadable_as = f"{filename}.{_format}" response.content_type = stream.mime_type response.content_length = stream.filesize response.stream = stream.stream_to_buffer()
def __init__( self, url: str, defer_prefetch_init: bool = False, on_progress_callback: Optional[OnProgress] = None, on_complete_callback: Optional[OnComplete] = None, proxies: Dict[str, str] = None, ): """Construct a :class:`YouTube <YouTube>`. :param str url: A valid YouTube watch URL. :param bool defer_prefetch_init: Defers executing any network requests. :param func on_progress_callback: (Optional) User defined callback function for stream download progress events. :param func on_complete_callback: (Optional) User defined callback function for stream download complete events. """ self.js: Optional[str] = None # js fetched by js_url self.js_url: Optional[ str] = None # the url to the js, parsed from watch html # note: vid_info may eventually be removed. It sounds like it once had # additional formats, but that doesn't appear to still be the case. # the url to vid info, parsed from watch html self.vid_info_url: Optional[str] = None self.vid_info_raw = None # content fetched by vid_info_url self.vid_info: Optional[Dict] = None # parsed content of vid_info_raw self.watch_html: Optional[ str] = None # the html of /watch?v=<video_id> self.embed_html: Optional[str] = None self.player_config_args: Dict = {} # inline js in the html containing # streams self.age_restricted: Optional[bool] = None self.fmt_streams: List[Stream] = [] self.caption_tracks: List[Caption] = [] # video_id part of /watch?v=<video_id> self.video_id = extract.video_id(url) # https://www.youtube.com/watch?v=<video_id> self.watch_url = extract.watch_url(self.video_id) self.embed_url = extract.embed_url(self.video_id) # A dictionary shared between all instances of :class:`Stream <Stream>` # (Borg pattern). self.stream_monostate = Monostate(on_progress=on_progress_callback, on_complete=on_complete_callback) if proxies: install_proxy(proxies) if not defer_prefetch_init: self.prefetch() self.descramble()
def test_extract_watch_url(): video_id = '9bZkp7q19f0' watch_url = extract.watch_url(video_id) assert watch_url == 'https://youtube.com/watch?v=9bZkp7q19f0'