Spaces:
Paused
Paused
| 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() | |