Upload 2 files
Browse files- app.py +96 -0
- requirements.txt +2 -0
app.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import os
|
| 3 |
+
import subprocess
|
| 4 |
+
import random
|
| 5 |
+
import time
|
| 6 |
+
|
| 7 |
+
DOWNLOAD_DIR = os.path.join(os.getcwd(), "downloads")
|
| 8 |
+
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
|
| 9 |
+
|
| 10 |
+
USER_AGENTS = [
|
| 11 |
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
| 12 |
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
|
| 13 |
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
| 14 |
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
def get_random_user_agent():
|
| 18 |
+
return random.choice(USER_AGENTS)
|
| 19 |
+
|
| 20 |
+
def run_command(command):
|
| 21 |
+
try:
|
| 22 |
+
result = subprocess.run(
|
| 23 |
+
command,
|
| 24 |
+
capture_output=True,
|
| 25 |
+
text=True,
|
| 26 |
+
timeout=600,
|
| 27 |
+
encoding='utf-8',
|
| 28 |
+
errors='ignore'
|
| 29 |
+
)
|
| 30 |
+
if result.returncode == 0:
|
| 31 |
+
return True, result.stdout
|
| 32 |
+
else:
|
| 33 |
+
return False, result.stderr
|
| 34 |
+
except subprocess.TimeoutExpired:
|
| 35 |
+
return False, "⏰ Timeout: demorou muito."
|
| 36 |
+
except Exception as e:
|
| 37 |
+
return False, f"Erro: {str(e)}"
|
| 38 |
+
|
| 39 |
+
def download_media(url, tipo="audio", qualidade="best", formato="mp3"):
|
| 40 |
+
if not url.strip():
|
| 41 |
+
return "❌ URL inválida!", None
|
| 42 |
+
|
| 43 |
+
filepath = os.path.join(DOWNLOAD_DIR, "%(title)s.%(ext)s")
|
| 44 |
+
|
| 45 |
+
if tipo == "audio":
|
| 46 |
+
cmd = [
|
| 47 |
+
"yt-dlp",
|
| 48 |
+
"--user-agent", get_random_user_agent(),
|
| 49 |
+
"--extract-audio", "-x",
|
| 50 |
+
"--audio-format", formato,
|
| 51 |
+
"--audio-quality", qualidade,
|
| 52 |
+
"-o", filepath,
|
| 53 |
+
url
|
| 54 |
+
]
|
| 55 |
+
else:
|
| 56 |
+
format_string = 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best'
|
| 57 |
+
if qualidade != "best":
|
| 58 |
+
format_string = f'bestvideo[height<=?{qualidade}][ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best'
|
| 59 |
+
cmd = [
|
| 60 |
+
"yt-dlp",
|
| 61 |
+
"--user-agent", get_random_user_agent(),
|
| 62 |
+
"-f", format_string,
|
| 63 |
+
"--merge-output-format", "mp4",
|
| 64 |
+
"-o", filepath,
|
| 65 |
+
url
|
| 66 |
+
]
|
| 67 |
+
|
| 68 |
+
ok, log = run_command(cmd)
|
| 69 |
+
if ok:
|
| 70 |
+
files = sorted(os.listdir(DOWNLOAD_DIR), key=lambda x: os.path.getctime(os.path.join(DOWNLOAD_DIR, x)))
|
| 71 |
+
last_file = os.path.join(DOWNLOAD_DIR, files[-1]) if files else None
|
| 72 |
+
return f"✅ Download concluído!\n{log}", last_file
|
| 73 |
+
else:
|
| 74 |
+
return f"❌ Erro:\n{log}", None
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def app_fn(url, tipo, qualidade, formato):
|
| 78 |
+
msg, arquivo = download_media(url, tipo, qualidade, formato)
|
| 79 |
+
return msg, arquivo
|
| 80 |
+
|
| 81 |
+
with gr.Blocks() as demo:
|
| 82 |
+
gr.Markdown("# 🚀 YouTube Downloader (Vídeo & Áudio)")
|
| 83 |
+
|
| 84 |
+
url = gr.Textbox(label="Cole o link do YouTube", placeholder="https://youtube.com/...")
|
| 85 |
+
tipo = gr.Radio(["audio", "video"], value="audio", label="Tipo de Download")
|
| 86 |
+
formato = gr.Dropdown(["mp3", "m4a", "wav", "flac"], value="mp3", label="Formato de Áudio")
|
| 87 |
+
qualidade = gr.Dropdown(["best", "0", "5", "9", "1080", "720", "480"], value="best", label="Qualidade")
|
| 88 |
+
|
| 89 |
+
btn = gr.Button("📥 Baixar")
|
| 90 |
+
log = gr.Textbox(label="Log", lines=10)
|
| 91 |
+
file_out = gr.File(label="Arquivo Gerado")
|
| 92 |
+
|
| 93 |
+
btn.click(app_fn, inputs=[url, tipo, qualidade, formato], outputs=[log, file_out])
|
| 94 |
+
|
| 95 |
+
if __name__ == "__main__":
|
| 96 |
+
demo.launch(server_name="0.0.0.0", server_port=7860)
|
requirements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
yt-dlp
|