import subprocess, os, asyncio from yt_dlp import YoutubeDL from yt_dlp.utils import DownloadError # # The download folder. # It goes: # FOLDER// # DOWNLOAD_FOLDER = os.environ.get("DOWNLOAD_FOLDER","/tmp/downloads") # Where the converted files will be saved if not os.path.exists(DOWNLOAD_FOLDER): os.makedirs(DOWNLOAD_FOLDER) # Throw error if the env is incorrect try: AUTODELETE_DELAY_SECS = int(os.environ.get("FILE_AUTODELETE_DELAY_SECS", 0)) except ValueError: raise EnvironmentError("You must set AUTODELETE_DELAY_SECS to a valid number (int) of seconds! To disable auto delete (not recommended), set it to 0") # # Asyncioway of scheduling a file delete with asyncio.sleep() and os.unlink() # async def delay_delete_file(file:str): if (AUTODELETE_DELAY_SECS > 0): await asyncio.sleep(AUTODELETE_DELAY_SECS) if os.path.exists(file): os.unlink(file) # # Downloads the video and extracts the audio # def download_audio(video_url: str, output_folder: str, kbps:int) -> str: ydl_opts = { 'format': 'bestaudio/best', 'outtmpl': os.path.join(output_folder, '%(title)s.%(ext)s'), 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': str(kbps), }, { 'key': 'FFmpegMetadata', 'add_metadata': True, }], 'quiet': True, 'noplaylist': True } with YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(video_url, download=True) filename = ydl.prepare_filename(info) return os.path.splitext(filename)[0] + ".mp3" # path to final MP3 # # Uses FFmpeg to edit the artist and album if specified # def set_metadata_and_rename(mp3_file: str, name: str, artist: str = None, album: str = None) -> str: new_file = os.path.abspath(os.path.join(os.path.dirname(mp3_file), f"{name}.mp3")) cmd = ["ffmpeg", "-y", "-i", mp3_file] # Only add metadata if provided cmd += ["-metadata", f"title={name}"] if artist: cmd += ["-metadata", f"artist={artist}"] if album: cmd += ["-metadata", f"album={album}"] cmd += [new_file] subprocess.run(cmd, check=True) os.remove(mp3_file) # clean original return new_file