def download_video(url, filename): global is_paused, is_cancelled download_button['state'] = 'disabled' pause_button['state'] = 'normal' cancel_button['state'] = 'normal' try: progress['text'] = 'Connecting ...' yt = YouTube(url) stream = yt.streams.first() filesize = stream.filesize with open(filename, 'wb') as f: is_paused = is_cancelled = False stream = request.stream(stream.url) downloaded = 0 while True: if is_cancelled: progress['text'] = 'Download cancelled' break if is_paused: continue chunk = next(stream, None) if chunk: f.write(chunk) downloaded += len(chunk) progress['text'] = f'Downloaded {downloaded} / {filesize}' else: # no more data progress['text'] = 'Download completed' break print('done') except Exception as e: print(e) download_button['state'] = 'normal' pause_button['state'] = 'disabled' cancel_button['state'] = 'disabled'
def download( self, output_path: Optional[str] = None, filename: Optional[str] = None, filename_prefix: Optional[str] = None, skip_existing: bool = True, ) -> str: """Write the media stream to disk. :param output_path: (optional) Output path for writing media file. If one is not specified, defaults to the current working directory. :type output_path: str or None :param filename: (optional) Output filename (stem only) for writing media file. If one is not specified, the default filename is used. :type filename: str or None :param filename_prefix: (optional) A string that will be prepended to the filename. For example a number in a playlist or the name of a series. If one is not specified, nothing will be prepended This is separate from filename so you can use the default filename but still add a prefix. :type filename_prefix: str or None :param skip_existing: (optional) skip existing files, defaults to True :type skip_existing: bool :returns: Path to the saved video :rtype: str """ file_path = self.get_file_path( filename=filename, output_path=output_path, filename_prefix=filename_prefix, ) if skip_existing and self.exists_at_path(file_path): logger.debug("file %s already exists, skipping", file_path) self.on_complete(file_path) return file_path bytes_remaining = self.filesize logger.debug( "downloading (%s total bytes) file to %s", self.filesize, file_path, ) with open(file_path, "wb") as fh: for chunk in request.stream(self.url): # reduce the (bytes) remainder by the length of the chunk. bytes_remaining -= len(chunk) # send to the on_progress callback. self.on_progress(chunk, fh, bytes_remaining) self.on_complete(file_path) return file_path
def __call__(self, *args, **kwargs): try: for chunk in request.stream(self.url): yield chunk except HTTPError as e: if e.code != 404: raise # Some adaptive streams need to be requested with sequence numbers for chunk in request.seq_stream(self.url): yield chunk
def download( self, output_path: Optional[str] = None, filename: Optional[str] = None, filename_prefix: Optional[str] = None, ) -> str: """Write the media stream to disk. :param output_path: (optional) Output path for writing media file. If one is not specified, defaults to the current working directory. :type output_path: str or None :param filename: (optional) Output filename (stem only) for writing media file. If one is not specified, the default filename is used. :type filename: str or None :param filename_prefix: (optional) A string that will be prepended to the filename. For example a number in a playlist or the name of a series. If one is not specified, nothing will be prepended This is separate from filename so you can use the default filename but still add a prefix. :type filename_prefix: str or None :rtype: str """ output_path = output_path or os.getcwd() if filename: safe = safe_filename(filename) filename = "{filename}.{s.subtype}".format(filename=safe, s=self) filename = filename or self.default_filename if filename_prefix: filename = "{prefix}{filename}".format( prefix=safe_filename(filename_prefix), filename=filename, ) file_path = os.path.join(output_path, filename) bytes_remaining = self.filesize logger.debug( "downloading (%s total bytes) file to %s", self.filesize, file_path, ) with open(file_path, "wb") as fh: for chunk in request.stream(self.url): # reduce the (bytes) remainder by the length of the chunk. bytes_remaining -= len(chunk) # send to the on_progress callback. self.on_progress(chunk, fh, bytes_remaining) self.on_complete(fh) return file_path
def test_streaming(mock_urlopen): fake_stream_binary = [ iter(os.urandom(8 * 1024)), iter(os.urandom(8 * 1024)), iter(os.urandom(8 * 1024)), None, ] response = mock.Mock() response.read.side_effect = fake_stream_binary mock_urlopen.return_value = response response = request.stream("http://fakeassurl.gov") call_count = len(list(response)) assert call_count == 3
def stream_to_buffer(self, buffer: BinaryIO) -> None: """Write the media stream to buffer :rtype: io.BytesIO buffer """ bytes_remaining = self.filesize logger.info( "downloading (%s total bytes) file to buffer", self.filesize, ) for chunk in request.stream(self.url): # reduce the (bytes) remainder by the length of the chunk. bytes_remaining -= len(chunk) # send to the on_progress callback. self.on_progress(chunk, buffer, bytes_remaining) self.on_complete(None)
def test_streaming(mock_urlopen): # Given fake_stream_binary = [ os.urandom(8 * 1024), os.urandom(8 * 1024), os.urandom(8 * 1024), None, ] mock_response = mock.Mock() mock_response.read.side_effect = fake_stream_binary mock_response.info.return_value = {"Content-Range": "bytes 200-1000/24576"} mock_urlopen.return_value = mock_response # When response = request.stream("http://fakeassurl.gov/streaming_test") # Then assert len(b''.join(response)) == 3 * 8 * 1024 assert mock_response.read.call_count == 4
def test_streaming(mock_urlopen): # Given fake_stream_binary = [ os.urandom(8 * 1024), os.urandom(8 * 1024), os.urandom(8 * 1024), None, ] response = mock.Mock() response.read.side_effect = fake_stream_binary response.info.return_value = {"Content-Range": "bytes 200-1000/24576"} mock_urlopen.return_value = response # When response = request.stream("http://fakeassurl.gov") # Then call_count = len(list(response)) assert call_count == 3
def download_media(url, filename, audioOnly=False): if (url): global is_paused, is_cancelled download_button['state'] = 'disabled' download_audio_button['state'] = 'disabled' pause_button['state'] = 'normal' cancel_button['state'] = 'normal' var = optMval.get() try: progress['text'] = 'Connecting ...' yt = YouTube(url) if (audioOnly): stream = yt.streams.filter(subtype='mp4', only_audio=True).first() filename = filename + '/' + yt.title + '.mp3' else: stream = yt.streams[res_list_db[var]] filename = filename + '/' + yt.title + '.mp4' filesize = stream.filesize with open(filename, 'wb') as f: is_paused = is_cancelled = False stream = request.stream(stream.url) downloaded = 0 while True: if is_cancelled: progress['text'] = 'Download cancelled' break if is_paused: continue chunk = next(stream, None) if chunk: f.write(chunk) downloaded += len(chunk) progress[ 'text'] = f'Downloaded {downloaded} / {filesize}' else: # no more data progress['text'] = 'Download completed' break print('done') except Exception as e: print(e) download_button['state'] = 'normal' download_audio_button['state'] = 'normal' pause_button['state'] = 'disabled' cancel_button['state'] = 'disabled'
def download_audio(url, filelocation): global is_paused, is_cancelled, filesize, downloaded download_audio_button['state'] = 'disabled' pause_button['state'] = 'normal' cancel_button['state'] = 'normal' try: progress['text'] = 'Connecting ...' yt = YouTube(url) stream = yt.streams.filter(only_audio=True).first() filesize = stream.filesize string = ''.join( [i for i in re.findall('[\w +/.]', yt.title) if i.isalpha()]) filename = filelocation + '/' + string + '.mp3' with open(filename, 'wb') as f: is_paused = is_cancelled = False stream = request.stream(stream.url) downloaded = 0 while True: pbar["maximum"] = filesize pbar["value"] = downloaded pbar.start() if is_cancelled: progress['text'] = 'Download cancelled' pbar.stop() break if is_paused: continue chunk = next(stream, None) if chunk: f.write(chunk) downloaded += len(chunk) progress['text'] = f'Downloaded {downloaded} / {filesize}' else: # no more data progress['text'] = 'Audio Download completed!' break print('done') except Exception as e: print(e) download_audio_button['state'] = 'normal' pause_button['state'] = 'disabled' cancel_button['state'] = 'disabled'
def download_as_temp(self, video): with tempfile.NamedTemporaryFile(delete=False) as f: for chunk in request.stream(video.url): f.write(chunk) return f.name
def download(self, output_path: Optional[str] = None, filename: Optional[str] = None, filename_prefix: Optional[str] = None, skip_existing: bool = True, timeout: Optional[int] = None, max_retries: Optional[int] = 0) -> str: """Write the media stream to disk. :param output_path: (optional) Output path for writing media file. If one is not specified, defaults to the current working directory. :type output_path: str or None :param filename: (optional) Output filename (stem only) for writing media file. If one is not specified, the default filename is used. :type filename: str or None :param filename_prefix: (optional) A string that will be prepended to the filename. For example a number in a playlist or the name of a series. If one is not specified, nothing will be prepended This is separate from filename so you can use the default filename but still add a prefix. :type filename_prefix: str or None :param skip_existing: (optional) Skip existing files, defaults to True :type skip_existing: bool :param timeout: (optional) Request timeout length in seconds. Uses system default. :type timeout: int :param max_retries: (optional) Number of retries to attempt after socket timeout. Defaults to 0. :type max_retries: int :returns: Path to the saved video :rtype: str """ file_path = self.get_file_path( filename=filename, output_path=output_path, filename_prefix=filename_prefix, ) if skip_existing and self.exists_at_path(file_path): logger.debug(f'file {file_path} already exists, skipping') self.on_complete(file_path) return file_path bytes_remaining = self.filesize logger.debug( f'downloading ({self.filesize} total bytes) file to {file_path}') with open(file_path, "wb") as fh: try: for chunk in request.stream(self.url, timeout=timeout, max_retries=max_retries): # reduce the (bytes) remainder by the length of the chunk. bytes_remaining -= len(chunk) # send to the on_progress callback. self.on_progress(chunk, fh, bytes_remaining) except HTTPError as e: if e.code != 404: raise # Some adaptive streams need to be requested with sequence numbers for chunk in request.seq_stream(self.url, timeout=timeout, max_retries=max_retries): # reduce the (bytes) remainder by the length of the chunk. bytes_remaining -= len(chunk) # send to the on_progress callback. self.on_progress(chunk, fh, bytes_remaining) self.on_complete(file_path) return file_path
def test_timeout(mock_urlopen): exc = URLError(reason=socket.timeout('timed_out')) mock_urlopen.side_effect = exc generator = request.stream('http://fakeassurl.gov/timeout_test', timeout=1) with pytest.raises(MaxRetriesExceeded): next(generator)