I am trying to download youtube videos / audio files and upload them to Azure Blob Storage without downloading them locally. I am using yt-dlp as it seems to be the most robust tool for my task. I've been trying an approach like below: import io from yt_dlp import YoutubeDL from azure.storage.blob import BlobServiceClient video_url = 'https://www.youtube.com/watch?v=<video> connect_str = 'DefaultEndpointsProtocol=https;AccountName=accountname;AccountKey=accountkey;EndpointSuffix=core.windows.net' container_name = 'container_name' blob_name = 'video_name.mp4' blob_service_client = BlobServiceClient.from_connection_string(connect_str) blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob_name) ydl_opts = { 'format': 'best', 'quiet': True, 'outtmpl': '-', # Output to stdout } with YoutubeDL(ydl_opts) as ydl, io.BytesIO() as byte_stream: ydl.download([video_url]) byte_stream.seek(0) blob_client.upload_blob(byte_stream, overwrite=True) print(f'Uploaded {blob_name} to Azure Blob Storage.') but it throws TypeError: write() argument must be str, not <class 'bytes'> I would appreciate any help. EDIT: Complete traceback: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[4], line 27 24 # Download video and upload to Azure Blob Storage 25 with YoutubeDL(ydl_opts) as ydl, io.BytesIO() as byte_stream: 26 # Redirect yt-dlp's stdout to the byte stream ---> 27 ydl.download([video_url]) 28 byte_stream.seek(0) 29 blob_client.upload_blob(byte_stream, overwrite=True) File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:3618, in YoutubeDL.download(self, url_list) 3615 raise SameFileError(outtmpl) 3617 for url in url_list: -> 3618 self.__download_wrapper(self.extract_info)( 3619 url, force_generic_extractor=self.params.get('force_generic_extractor', False)) 3621 return self._download_retcode File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:3591, in YoutubeDL.__download_wrapper.<locals>.wrapper(*args, **kwargs) 3588 @functools.wraps(func) 3589 def wrapper(*args, **kwargs): 3590 try: -> 3591 res = func(*args, **kwargs) 3592 except CookieLoadError: 3593 raise File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:1626, in YoutubeDL.extract_info(self, url, download, ie_key, extra_info, process, force_generic_extractor) 1624 raise ExistingVideoReached 1625 break -> 1626 return self.__extract_info(url, self.get_info_extractor(key), download, extra_info, process) 1627 else: 1628 extractors_restricted = self.params.get('allowed_extractors') not in (None, ['default']) File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:1637, in YoutubeDL._handle_extraction_exceptions.<locals>.wrapper(self, *args, **kwargs) 1635 while True: 1636 try: -> 1637 return func(self, *args, **kwargs) 1638 except (CookieLoadError, DownloadCancelled, LazyList.IndexError, PagedList.IndexError): 1639 raise File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:1793, in YoutubeDL.__extract_info(self, url, ie, download, extra_info, process) 1791 if process: 1792 self._wait_for_video(ie_result) -> 1793 return self.process_ie_result(ie_result, download, extra_info) 1794 else: 1795 return ie_result File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:1852, in YoutubeDL.process_ie_result(self, ie_result, download, extra_info) 1850 if result_type == 'video': 1851 self.add_extra_info(ie_result, extra_info) -> 1852 ie_result = self.process_video_result(ie_result, download=download) 1853 self._raise_pending_errors(ie_result) 1854 additional_urls = (ie_result or {}).get('additional_urls') File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:3024, in YoutubeDL.process_video_result(self, info_dict, download) 3022 downloaded_formats.append(new_info) 3023 try: -> 3024 self.process_info(new_info) 3025 except MaxDownloadsReached: 3026 max_downloads_reached = True File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:177, in _catch_unsafe_extension_error.<locals>.wrapper(self, *args, **kwargs) 174 @functools.wraps(func) 175 def wrapper(self, *args, **kwargs): 176 try: --> 177 return func(self, *args, **kwargs) 178 except _UnsafeExtensionError as error: 179 self.report_error( 180 f'The extracted extension ({error.extension!r}) is unusual ' 181 'and will be skipped for safety reasons. ' 182 f'If you believe this is an error{bug_reports_message(",")}') File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:3492, in YoutubeDL.process_info(self, info_dict) 3488 dl_filename = existing_video_file(full_filename, temp_filename) 3489 if dl_filename is None or dl_filename == temp_filename: 3490 # dl_filename == temp_filename could mean that the file was partially downloaded with --no-part. 3491 # So we should try to resume the download -> 3492 success, real_download = self.dl(temp_filename, info_dict) 3493 info_dict['__real_download'] = real_download 3494 else: File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/YoutubeDL.py:3212, in YoutubeDL.dl(self, name, info, subtitle, test) 3210 if new_info.get('http_headers') is None: 3211 new_info['http_headers'] = self._calc_headers(new_info) -> 3212 return fd.download(name, new_info, subtitle) File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/downloader/common.py:464, in FileDownloader.download(self, filename, info_dict, subtitle) 461 self.to_screen(f'[download] Sleeping {sleep_interval:.2f} seconds ...') 462 time.sleep(sleep_interval) --> 464 ret = self.real_download(filename, info_dict) 465 self._finish_multiline_status() 466 return ret, True File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/downloader/http.py:368, in HttpFD.real_download(self, filename, info_dict) 366 try: 367 establish_connection() --> 368 return download() 369 except RetryDownload as err: 370 retry.error = err.source_error File ~/.virtualenvs/myenv/lib/python3.12/site-packages/yt_dlp/downloader/http.py:279, in HttpFD.real_download.<locals>.download() 276 self.report_error(f'unable to set filesize xattr: {err}') 278 try: --> 279 ctx.stream.write(data_block) 280 except OSError as err: 281 self.to_stderr('\n') File ~/.virtualenvs/myenv/lib/python3.12/site-packages/ipykernel/iostream.py:668, in OutStream.write(self, string) 666 if not isinstance(string, str): 667 msg = f"write() argument must be str, not {type(string)}" # type:ignore[unreachable] --> 668 raise TypeError(msg) 670 if self.echo is not None: 671 try: TypeError: write() argument must be str, not <class 'bytes'> Continue reading...