Youtube-Music / app.py
GilbertClaus's picture
Not Share
61c3048
import os
import re
import yt_dlp
import requests
import subprocess
import gradio as gr
from urllib.parse import urlparse
# Deteksi orientasi video berdasarkan URL atau metadata
def get_orientation(url):
result = subprocess.run(['yt-dlp', '--get-filename', '-o', '%(width)sx%(height)s', url], capture_output=True, text=True)
resolution = result.stdout.strip()
if 'x' in resolution:
width, height = map(int, resolution.split('x'))
return 'landscape' if width >= height else 'portrait'
else:
return None
# Fungsi download video
def video_download(url):
domain = urlparse(url).hostname.split('.')[-2].title()
try:
result = subprocess.run(['yt-dlp', '--print', '%(title)s\n%(uploader)s\n%(thumbnail)s', '--skip-download', url], capture_output=True, text=True, check=True)
title, uploader, thumbnail_url = result.stdout.strip().split('\n')
uploader = re.sub(r'[\\/:*?"<>|]', ' ', uploader)
title = re.sub(r'[\\/:*?"<>|]', ' ', title)
if "ytimg" in thumbnail_url and thumbnail_url.endswith(".webp"):
thumbnail_url = thumbnail_url.replace("_webp", "").replace(".webp", ".jpg")
# print(f'Channel: {uploader}\nTitle: {title}\nThumbnail: {thumbnail_url}')
if not title:
raise ValueError("Tidak dapat mendapatkan judul video.")
orientation = get_orientation(url)
if orientation == 'landscape':
format_filter = 'bestvideo[ext=mp4][height<=720]+bestaudio[ext=m4a]/best[ext=mp4][height<=720]'
elif orientation == 'portrait':
format_filter = 'bestvideo[ext=mp4][width<=720]+bestaudio[ext=m4a]/best[ext=mp4][width<=720]'
else:
print("Gagal mendeteksi orientasi video.")
return None
video_folder = os.path.join("/home/user/app/Gradio", domain, uploader, "Video")
if not os.path.exists(video_folder):
os.makedirs(video_folder)
video_file = os.path.join(video_folder, f"{uploader} - {title}.mp4")
thumbnail_folder = os.path.join("/home/user/app/Gradio", domain, uploader, "Thumbnail")
if not os.path.exists(thumbnail_folder):
os.makedirs(thumbnail_folder)
thumbnail_file = os.path.join(thumbnail_folder, f"{uploader} - {title}.jpg")
if not os.path.exists(thumbnail_file):
subprocess.run(['wget', '-O', thumbnail_file, thumbnail_url])
if not os.path.exists(video_file):
subprocess.run(['python', '-m', 'yt_dlp', '-f', format_filter, '-o', video_file, url], check=True)
return video_file, thumbnail_file
except subprocess.CalledProcessError as e:
return "", ""
except Exception as e:
return "", ""
# Fungsi download MP3
def audio_download(url):
domain = urlparse(url).hostname.split('.')[-2].title()
try:
result = subprocess.run(['yt-dlp', '--print', '%(title)s\n%(uploader)s\n%(thumbnail)s', '--skip-download', url], capture_output=True, text=True, check=True)
title, uploader, thumbnail_url = result.stdout.strip().split('\n')
uploader = re.sub(r'[\\/:*?"<>|]', ' ', uploader)
title = re.sub(r'[\\/:*?"<>|]', ' ', title)
if "ytimg" in thumbnail_url and thumbnail_url.endswith(".webp"):
thumbnail_url = thumbnail_url.replace("_webp", "").replace(".webp", ".jpg")
# print(f'Channel: {uploader}\nTitle: {title}\nThumbnail: {thumbnail_url}')
if not title:
raise ValueError("Tidak dapat mendapatkan judul audio.")
audio_folder = os.path.join("/home/user/app/Gradio", domain, uploader, "Audio")
if not os.path.exists(audio_folder):
os.makedirs(audio_folder)
audio_file = os.path.join(audio_folder, f"{uploader} - {title}.mp3")
thumbnail_folder = os.path.join("/home/user/app/Gradio", domain, uploader, "Thumbnail")
if not os.path.exists(thumbnail_folder):
os.makedirs(thumbnail_folder)
thumbnail_file = os.path.join(thumbnail_folder, f"{uploader} - {title}.jpg")
if not os.path.exists(thumbnail_file):
subprocess.run(['wget', '-O', thumbnail_file, thumbnail_url])
if not os.path.exists(audio_file):
subprocess.run(['python', '-m', 'yt_dlp', '-x', '--audio-format', 'mp3', '--embed-thumbnail', '-o', audio_file, url], check=True)
return audio_file, thumbnail_file
except subprocess.CalledProcessError as e:
return "", ""
except Exception as e:
return "", ""
# Fungsi proses input untuk Gradio
def process_input(url, download_type):
if download_type == "Video":
file, thumbnail = video_download(url.split("&")[0])
else:
file, thumbnail = audio_download(url.split("&")[0])
return (
gr.update(label=download_type, value=file, visible=True),
thumbnail,
gr.update(label=f"Download {download_type}", value=file, visible=True),
gr.update(label="Download Thumbnail", value=thumbnail, visible=True)
)
# Gradio interface
css_url = "https://gilbertclaus.pythonanywhere.com/templates/gradio.css"
with gr.Blocks(title="Video/Audio Downloader", css=requests.get(css_url).text) as youtube:
gr.Markdown("# YouTube Downloader - Video dan Audio")
with gr.Row():
input_text = gr.Textbox(label="Masukkan URL YouTube")
download_type = gr.Radio(["Video", "Audio"], label="Pilih Format Download", value="Video")
download_button = gr.Button("Download")
with gr.Row():
thumbnail_file = gr.Image(label="Thumbnail")
with gr.Column():
output_file = gr.File(visible=False)
with gr.Row():
download_thumbnail = gr.DownloadButton(visible=False)
download_file = gr.DownloadButton(visible=False)
download_button.click(
process_input,
inputs=[input_text, download_type],
outputs=[output_file, thumbnail_file, download_file, download_thumbnail]
)
youtube.launch()