Downloader / app.py
darkvibe314's picture
Create app.py
9ee5c88 verified
Raw
History Blame Contribute Delete
4.24 kB
import gradio as gr
from pytubefix import YouTube
import os
# --- SILENT TECH THEME ---
# A minimalist, dark, high-contrast monochrome theme.
silent_theme = gr.themes.Monochrome(
primary_hue="slate",
secondary_hue="gray",
neutral_hue="zinc",
font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"],
).set(
body_background_fill="#0a0a0a",
body_background_fill_dark="#0a0a0a",
body_text_color="#e5e5e5",
body_text_color_dark="#e5e5e5",
button_primary_background_fill="#ffffff",
button_primary_background_fill_hover="#cccccc",
button_primary_text_color="#000000",
border_color_primary="#262626",
block_background_fill="#171717",
block_background_fill_dark="#171717",
input_background_fill="#0a0a0a",
input_background_fill_dark="#0a0a0a",
)
# Custom CSS for sharper edges and minimal styling
custom_css = """
.container { max-width: 700px; margin: 40px auto; font-family: 'Inter', sans-serif; }
h1 { text-align: center; letter-spacing: 0.2em; font-weight: 300; }
.subtext { text-align: center; color: #737373; font-size: 0.9em; letter-spacing: 0.05em; margin-bottom: 30px; }
"""
def get_video_info(url):
try:
if not url:
return "Awaiting input...", gr.update(choices=[], value=None)
yt = YouTube(url)
info = f"""
### {yt.title}
* **AUTHOR:** {yt.author}
* **DURATION:** {yt.length}s
* **VIEWS:** {yt.views:,}
"""
# Extract available progressive resolutions (mp4 with audio/video combined)
resolutions = list(set([
stream.resolution
for stream in yt.streams.filter(progressive=True, file_extension='mp4')
if stream.resolution
]))
sorted_res = sorted(resolutions, key=lambda x: int(x.replace('p', '')) if x else 0, reverse=True)
default_res = sorted_res[0] if sorted_res else None
return info, gr.update(choices=sorted_res, value=default_res, interactive=True)
except Exception as e:
return f"ERROR: {str(e)}", gr.update(choices=[], value=None)
def download_video(url, resolution):
try:
if not url or not resolution:
return None, "ERROR: Target URL or Resolution missing."
yt = YouTube(url)
stream = yt.streams.filter(progressive=True, file_extension='mp4', resolution=resolution).first()
if not stream:
# Fallback if specific resolution drops
stream = yt.streams.filter(progressive=True, file_extension='mp4').first()
out_dir = "./downloads"
os.makedirs(out_dir, exist_ok=True)
# Download the file
file_path = stream.download(output_path=out_dir)
return file_path, "STATUS: ACQUISITION COMPLETE."
except Exception as e:
return None, f"ERROR: {str(e)}"
# --- BUILD THE UI ---
with gr.Blocks(theme=silent_theme, css=custom_css) as demo:
with gr.Column(elem_classes="container"):
gr.Markdown("# SILENT // TECH")
gr.Markdown("<div class='subtext'>VIDEO EXTRACTION PROTOCOL</div>")
with gr.Group():
url_input = gr.Textbox(label="TARGET URL", placeholder="Insert YouTube link here...", lines=1, show_label=True)
analyze_btn = gr.Button("ANALYZE STREAM", variant="primary")
info_output = gr.Markdown("Awaiting input...")
with gr.Group():
res_dropdown = gr.Dropdown(label="SELECT RESOLUTION", choices=[], interactive=False)
dl_btn = gr.Button("INITIALIZE DOWNLOAD")
status_output = gr.Textbox(label="SYSTEM STATUS", interactive=False)
file_output = gr.File(label="OUTPUT ARTIFACT")
# Wire up the buttons
analyze_btn.click(
fn=get_video_info,
inputs=[url_input],
outputs=[info_output, res_dropdown]
)
dl_btn.click(
fn=download_video,
inputs=[url_input, res_dropdown],
outputs=[file_output, status_output]
)
if __name__ == "__main__":
# Run the server on 0.0.0.0 to work properly inside HF Docker Spaces
demo.launch(server_name="0.0.0.0", server_port=7860)