|
|
import gradio as gr |
|
|
from yt_dlp import YoutubeDL |
|
|
import os |
|
|
from pydub import AudioSegment |
|
|
import re |
|
|
|
|
|
DOWNLOADS_FOLDER = "downloads" |
|
|
os.makedirs(DOWNLOADS_FOLDER, exist_ok=True) |
|
|
|
|
|
def sanitize_filename(filename): |
|
|
"""Remove invalid characters from filename""" |
|
|
return re.sub(r'[<>:"/\\|?*]', '', filename) |
|
|
|
|
|
def download_audio(url, file_format): |
|
|
try: |
|
|
if not url or not url.strip(): |
|
|
return None, "Error: Please enter a URL" |
|
|
|
|
|
|
|
|
ydl_opts = { |
|
|
'format': 'bestaudio/best', |
|
|
'outtmpl': os.path.join(DOWNLOADS_FOLDER, '%(title)s.%(ext)s'), |
|
|
'quiet': True, |
|
|
'no_warnings': True |
|
|
} |
|
|
|
|
|
with YoutubeDL(ydl_opts) as ydl: |
|
|
info = ydl.extract_info(url, download=True) |
|
|
original_filename = ydl.prepare_filename(info) |
|
|
|
|
|
|
|
|
if os.path.exists(original_filename): |
|
|
downloaded_file = original_filename |
|
|
else: |
|
|
|
|
|
base_name = os.path.splitext(original_filename)[0] |
|
|
for ext in ['.m4a', '.webm', '.mp3', '.opus', '.flac', '.wav']: |
|
|
possible_file = base_name + ext |
|
|
if os.path.exists(possible_file): |
|
|
downloaded_file = possible_file |
|
|
break |
|
|
else: |
|
|
downloaded_file = original_filename |
|
|
|
|
|
|
|
|
if file_format.lower() != "original": |
|
|
target_ext = f".{file_format.lower()}" |
|
|
current_ext = os.path.splitext(downloaded_file)[1].lower() |
|
|
|
|
|
if current_ext != target_ext: |
|
|
|
|
|
base_name = os.path.splitext(downloaded_file)[0] |
|
|
sanitized_base = sanitize_filename(os.path.basename(base_name)) |
|
|
output_file = os.path.join(DOWNLOADS_FOLDER, sanitized_base + target_ext) |
|
|
|
|
|
try: |
|
|
|
|
|
audio = AudioSegment.from_file(downloaded_file) |
|
|
audio.export(output_file, format=file_format.lower()) |
|
|
|
|
|
|
|
|
downloaded_file = output_file |
|
|
except Exception as e: |
|
|
print(f"Conversion failed: {e}") |
|
|
|
|
|
pass |
|
|
|
|
|
return downloaded_file, "Download completed successfully!" |
|
|
|
|
|
except Exception as e: |
|
|
return None, f"Error: {str(e)}" |
|
|
|
|
|
|
|
|
iface = gr.Interface( |
|
|
fn=download_audio, |
|
|
inputs=[ |
|
|
gr.Textbox(label="YouTube or SoundCloud URL", placeholder="Enter URL here..."), |
|
|
gr.Dropdown(["original", "mp3", "m4a", "wav"], value="mp3", label="Output Format") |
|
|
], |
|
|
outputs=[ |
|
|
gr.File(label="Download Audio"), |
|
|
gr.Textbox(label="Status") |
|
|
], |
|
|
title="🎵 Audio Downloader", |
|
|
description="Download audio from YouTube or SoundCloud. Supports MP3, M4A, WAV formats.", |
|
|
examples=[ |
|
|
["https://www.youtube.com/watch?v=dQw4w9WgXcQ", "mp3"], |
|
|
["https://soundcloud.com/aviciiofficial/levels", "mp3"], |
|
|
] |
|
|
) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
iface.launch(share=False, show_error=True) |