test / app.py
NeoPy's picture
Update app.py
4bd3ced verified
from __future__ import annotations
from typing import Iterable
import gradio as gr
from gradio.themes.base import Base
from gradio.themes.utils import colors, fonts, sizes
class ShadowTheHedgehog(Base):
def __init__(
self,
*,
primary_hue: colors.Color | str = colors.red, # Red for Shadow's stripes
secondary_hue: colors.Color | str = colors.amber, # Gold for Chaos Emeralds
neutral_hue: colors.Color | str = colors.gray, # Dark grays for edgy vibe
spacing_size: sizes.Size | str = sizes.spacing_md,
radius_size: sizes.Size | str = sizes.radius_md,
text_size: sizes.Size | str = sizes.text_lg,
font: fonts.Font | str | Iterable[fonts.Font | str] = (
fonts.GoogleFont("Orbitron"), # Futuristic font for Shadow's vibe
"ui-sans-serif",
"system-ui",
),
font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (
"ui-monospace",
fonts.GoogleFont("Roboto Mono"),
),
):
super().__init__(
primary_hue=primary_hue,
secondary_hue=secondary_hue,
neutral_hue=neutral_hue,
spacing_size=spacing_size,
radius_size=radius_size,
text_size=text_size,
font=font,
font_mono=font_mono,
)
self.name = "ShadowTheHedgehog"
# Primary palette (red, for main accents)
self.primary_50 = "#fff5f5"
self.primary_100 = "#ffe4e4"
self.primary_200 = "#ffbfbf"
self.primary_300 = "#ff9999"
self.primary_400 = "#ff6666"
self.primary_500 = "#ff0000" # Shadow's iconic red
self.primary_600 = "#e60000"
self.primary_700 = "#cc0000"
self.primary_800 = "#b30000"
self.primary_900 = "#990000"
# Secondary palette (gold, for accents)
self.secondary_50 = "#fffbeb"
self.secondary_100 = "#fef3c7"
self.secondary_200 = "#fde68a"
self.secondary_300 = "#fcd34d"
self.secondary_400 = "#fbbf24"
self.secondary_500 = "#FFD700" # Gold for Chaos Emeralds
self.secondary_600 = "#d4af37"
self.secondary_700 = "#b8860b"
self.secondary_800 = "#9c6d00"
self.secondary_900 = "#7f5500"
# Neutral palette (dark grays/black for background)
self.neutral_50 = "#f7f7f7"
self.neutral_100 = "#e5e5e5"
self.neutral_200 = "#cccccc"
self.neutral_300 = "#b3b3b3"
self.neutral_400 = "#999999"
self.neutral_500 = "#808080"
self.neutral_600 = "#666666"
self.neutral_700 = "#4d4d4d"
self.neutral_800 = "#333333"
self.neutral_900 = "#1C2526" # Shadow's dark aesthetic
self.neutral_950 = "#141414"
super().set(
# Backgrounds
background_fill_primary="#1C2526", # Dark black/gray
background_fill_primary_dark="#1C2526",
background_fill_secondary="#333333", # Slightly lighter for panels
background_fill_secondary_dark="#333333",
block_background_fill="#000000",
block_background_fill_dark="#000000",
block_border_color="*neutral_700",
block_border_width="1px", # thiner borders
block_info_text_color="*neutral_400",
block_info_text_size="*text_sm",
block_info_text_weight="400",
block_label_background_fill="#000000",
block_label_background_fill_dark="#000000",
block_label_border_color="*neutral_700",
block_label_border_width="1px",
block_label_margin="0",
block_label_padding="*spacing_sm *spacing_lg",
block_label_radius="*radius_md",
block_label_right_radius="*radius_md",
block_label_shadow="*shadow_drop_lg",
block_label_text_color="white",
block_label_text_color_dark="white",
block_label_text_weight="400",
block_padding="*spacing_xl",
block_radius="*radius_md",
block_shadow="*shadow_drop_lg", # Bold shadow for depth
block_title_background_fill="*neutral_800",
block_title_border_color="none",
block_title_border_width="0px",
block_title_padding="*spacing_md *spacing_lg",
block_title_radius="*radius_md",
block_title_text_color="#ffffff", # Gold titles
block_title_text_size="*text_xl", # Larger for hierarchy
block_title_text_weight="700", # Bold for Shadow's presence
body_background_fill="#1C2526",
body_text_color="white",
body_text_color_subdued="#b3b3b3",
body_text_size="*text_md",
body_text_weight="400",
border_color_accent="*secondary_500", # Gold accents
border_color_primary="*neutral_700",
# Buttons
button_border_width="2px",
button_cancel_background_fill="*neutral_800",
button_cancel_border_color="*neutral_700",
button_cancel_text_color="white",
button_large_padding="*spacing_lg calc(2 * *spacing_lg)",
button_large_radius="*radius_md",
button_large_text_size="*text_lg",
button_large_text_weight="600",
button_primary_background_fill="*primary_500", # Red buttons
button_primary_background_fill_hover="*primary_400",
button_primary_border_color="*primary_500",
button_primary_border_color_hover="*primary_400",
button_primary_text_color="white",
button_primary_text_color_hover="*secondary_400", # Gold text on hover
button_secondary_background_fill="*neutral_800",
button_secondary_background_fill_hover="*neutral_700",
button_secondary_border_color="*neutral_700",
button_secondary_text_color="white",
button_small_padding="*spacing_sm calc(2 * *spacing_sm)",
button_small_radius="*radius_md",
button_small_text_size="*text_md",
button_small_text_weight="400",
button_transition="0.3s ease all",
# Checkboxes
checkbox_background_color="*neutral_800",
checkbox_background_color_selected="*primary_500", # Red when selected
checkbox_border_color="*neutral_700",
checkbox_border_color_focus="*primary_500",
checkbox_border_color_selected="*primary_500",
checkbox_border_radius="*radius_sm",
checkbox_border_width="2px",
checkbox_check="url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e\")",
checkbox_label_background_fill="transparent",
checkbox_label_border_color="transparent",
checkbox_label_border_width="0px",
checkbox_label_gap="*spacing_lg",
checkbox_label_padding="*spacing_md calc(2 * *spacing_md)",
checkbox_label_shadow="none",
checkbox_label_text_color="white",
checkbox_label_text_size="*text_md",
checkbox_label_text_weight="400",
checkbox_shadow="*shadow_drop",
color_accent="*primary_500",
color_accent_soft="*primary_100",
container_radius="*radius_lg",
embed_radius="*radius_md",
# Errors
error_background_fill="*neutral_900",
error_border_color="*primary_700",
error_border_width="2px",
error_text_color="*primary_400",
error_text_color_dark="*primary_300",
form_gap_width="0px",
# Inputs
input_background_fill="*neutral_900",
input_background_fill_focus="*primary_100",
input_border_color="*neutral_700",
input_border_color_focus="*primary_500",
input_border_width="2px",
input_padding="*spacing_xl adulta",
input_placeholder_color="*neutral_500",
input_radius="*radius_md",
input_shadow="*shadow_drop_lg",
input_text_size="*text_md",
input_text_weight="400",
layout_gap="*spacing_xxl",
# Links
link_text_color="*secondary_500", # Gold links
link_text_color_active="*secondary_400",
link_text_color_hover="*secondary_300",
link_text_color_visited="*secondary_600",
loader_color="*primary_500",
panel_background_fill="*neutral_900",
panel_border_color="*neutral_700",
panel_border_width="2px",
prose_header_text_weight="600",
prose_text_size="*text_md",
prose_text_weight="400",
radio_circle="url(\"data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e\")",
section_header_text_size="*text_lg",
section_header_text_weight="600",
shadow_drop="rgba(0,0,0,0.2) 0px 2px 4px 0px",
shadow_drop_lg="0 4px 6px -1px rgb(0 0 0 / 0.3), 0 2px 4px -2px rgb(0 0 0 / 0.2)",
shadow_inset="rgba(0,0,0,0.2) 0px 2px 4px 0px inset",
shadow_spread="4px",
slider_color="*primary_500", # Red slider
stat_background_fill="*primary_500",
table_border_color="*neutral_600", # Improved contrast
table_even_background_fill="*neutral_850", # Slightly lighter
table_odd_background_fill="*neutral_800",
table_radius="*radius_md",
table_row_focus="*primary_100",
)
theme = ShadowTheHedgehog()
import os
import subprocess
def download_audio(youtube_url):
output_dir = "downloads"
os.makedirs(output_dir, exist_ok=True)
output_file = os.path.join(output_dir, "audio.%(ext)s")
audio_file = os.path.join(output_dir, "audio.mp3")
command = [
"yt-dlp",
"--format", "bestaudio/best",
"--output", output_file,
"--cookies", "./ytdlp.txt",
"--extract-audio",
"--audio-format", "mp3",
"--audio-quality", "192K",
youtube_url
]
try:
result = subprocess.run(command, capture_output=True, text=True)
if result.returncode == 0 and os.path.exists(audio_file):
return audio_file, "Audio downloaded successfully."
else:
return None, f"Error: {result.stderr.strip() or 'Unknown error.'}"
except Exception as e:
return None, f"Exception during download: {str(e)}"
# Chatbot function to display audio and message
def chatbot_response(youtube_url):
audio_file, message = download_audio(youtube_url)
if audio_file:
return [(message, gr.Audio(audio_file))]
else:
return [(message, None)]
# Gradio Blocks UI
with gr.Blocks(theme=theme) as demo:
gr.Markdown("# YouTube Audio Downloader Chatbot")
with gr.Row(equal_height=True):
youtube_input = gr.Textbox(label="Enter YouTube URL", placeholder="https://www.youtube.com/watch?v=...")
submit_button = gr.Button("Download and Display")
chatbot = gr.Chatbot(label="Chatbot Output")
submit_button.click(
fn=chatbot_response,
inputs=youtube_input,
outputs=chatbot
)
# Launch the Gradio app
demo.launch()