import subprocess import yt_dlp import boto3 from urllib.error import HTTPError from botocore.exceptions import ClientError from yt_dlp_stream_to_s3.client import s3, create_presigned_url from yt_dlp_stream_to_s3.utils import remove_queries_from_url from yt_dlp_stream_to_s3.config import AWS_S3_BUCKET_NAME from yt_dlp_stream_to_s3.errors import YtDlpStreamToS3Error def yt_dlp_stream_to_s3( url: str, expiration=86400 * 7, # 7 days s3_extra_args: dict = (), ) -> None: media_url = remove_queries_from_url(url) ydl_opts = { "outtmpl": "%(title)s-%(id)s.%(ext)s", } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: info_dict = ydl.extract_info(media_url, download=False) video_title = info_dict.get("title", None) video_id = info_dict.get("id", None) video_ext = info_dict.get("ext", None) filename = f"{video_title}-{video_id}.{video_ext}" yt_dlp_process = subprocess.Popen( [ "yt-dlp", media_url, "--downloader", "ffmpeg", "--hls-use-mpegts", "--no-part", "-o", "-", ], stdout=subprocess.PIPE, ) s3.upload_fileobj( yt_dlp_process.stdout, AWS_S3_BUCKET_NAME, filename, ExtraArgs=s3_extra_args, ) yt_dlp_process.wait() return create_presigned_url(AWS_S3_BUCKET_NAME, filename, expiration) except HTTPError: raise YtDlpStreamToS3Error("Could not connect to the media resource.") except yt_dlp.utils.ExtractorError: raise YtDlpStreamToS3Error("Could not extra info from media.") except yt_dlp.utils.DownloadError: raise YtDlpStreamToS3Error("Could not download media. Check logs.") except ClientError: raise YtDlpStreamToS3Error("Error communicating with the S3 service.")