From 51a0fdef26b9a32f2b476fada1b2ad69691d4316 Mon Sep 17 00:00:00 2001 From: moshferatu Date: Fri, 1 Sep 2023 13:46:59 -0700 Subject: [PATCH] Initial commit of video downloader app --- download.py | 62 +++++++++++++++++++++++++++++++++++++++++++++ downloader.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + 3 files changed, 129 insertions(+) create mode 100644 download.py create mode 100644 downloader.py create mode 100644 requirements.txt diff --git a/download.py b/download.py new file mode 100644 index 0000000..5711322 --- /dev/null +++ b/download.py @@ -0,0 +1,62 @@ +import os +import subprocess +import re + +def download(video_url, output_file_name, dest_dir='./', audio_only=False, progress_callback=None): + # Ensure the destination directory exists + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + + # Prepare the command to predict filename extension + if audio_only: + predict_command = ['yt-dlp', '--newline', '-x', '--audio-format', 'mp3', '--get-filename', '-o', f'{output_file_name}.%(ext)s', video_url] + else: + predict_command = ['yt-dlp', '--newline', '--get-filename', '-o', f'{output_file_name}.%(ext)s', video_url] + + try: + # Using yt-dlp with --get-filename to predict the output filename + result = subprocess.check_output(predict_command) + file_extension = os.path.splitext(result.decode('utf-8').strip())[1] + except Exception as e: + print(f'Unexpected error when getting filename: {e}') + return + + # Prepare the command to download the media + if audio_only: + download_command = [ + 'yt-dlp', + '-x', '--audio-format', 'mp3', + '-o', f'{dest_dir}/{output_file_name}{file_extension}', + video_url + ] + else: + download_command = [ + 'yt-dlp', + '-o', f'{dest_dir}/{output_file_name}{file_extension}', + video_url + ] + + try: + # Execute the download command and capture stdout in real-time + process = subprocess.Popen(download_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) + while True: + line = process.stdout.readline() + if not line: + break + if '[download]' in line: + # Parse the progress from the output + match = re.search(r'\[download\]\s+(\d+\.\d+|\d+)%', line) + if match: + percentage = int(float(match.group(1))) + if progress_callback: + progress_callback(percentage) # Call the callback with the parsed progress value + process.communicate() # Wait for the process to finish if it hasn't yet + except subprocess.CalledProcessError: + print('Error occurred while downloading the video/audio.') + except Exception as e: + print(f'Unexpected error: {e}') + +if __name__ == '__main__': + def update_progress_bar(percentage): + print(percentage) + download('https://www.youtube.com/watch?v=ON7QQtF-RNA', 'Khonsu - A Jhator Ascension', progress_callback=update_progress_bar) \ No newline at end of file diff --git a/downloader.py b/downloader.py new file mode 100644 index 0000000..223c4ec --- /dev/null +++ b/downloader.py @@ -0,0 +1,66 @@ +import tkinter as tk +from tkinter import ttk, filedialog, messagebox +from download import download + +def update_progress_bar(percentage): + progress_var.set(percentage) + +def start_download(): + url = url_entry.get() + filename = filename_entry.get() + dest_dir = directory_var.get() + audio_only = audio_only_var.get() + + if not url or not filename or not dest_dir: + messagebox.showerror("Error", "Please fill in all required fields!") + return + + download(url, filename, dest_dir=dest_dir, audio_only=audio_only, progress_callback=update_progress_bar) + +def select_directory(): + directory = filedialog.askdirectory() + directory_var.set(directory) + +# GUI Setup +app = tk.Tk() +app.title("yt-dlp Downloader") + +frame = ttk.Frame(app, padding="10") +frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) + +# URL input +url_label = ttk.Label(frame, text="Video URL:") +url_label.grid(row=0, column=0, sticky=tk.W, pady=5) +url_entry = ttk.Entry(frame, width=40) +url_entry.grid(row=0, column=1, pady=5) + +# Filename input +filename_label = ttk.Label(frame, text="Filename (without extension):") +filename_label.grid(row=1, column=0, sticky=tk.W, pady=5) +filename_entry = ttk.Entry(frame, width=40) +filename_entry.grid(row=1, column=1, pady=5) + +# Directory chooser +directory_var = tk.StringVar() +directory_label = ttk.Label(frame, text="Destination Directory:") +directory_label.grid(row=2, column=0, sticky=tk.W, pady=5) +directory_entry = ttk.Entry(frame, width=30, textvariable=directory_var) +directory_entry.grid(row=2, column=1, pady=5, sticky=tk.W) +directory_btn = ttk.Button(frame, text="Browse", command=select_directory) +directory_btn.grid(row=2, column=2, pady=5, sticky=tk.W) + +# Audio only checkbox +audio_only_var = tk.BooleanVar() +audio_only_checkbox = ttk.Checkbutton(frame, text="Audio Only", variable=audio_only_var) +audio_only_checkbox.grid(row=3, column=1, sticky=tk.W, pady=5) + +# Download button +download_btn = ttk.Button(frame, text="Download", command=start_download) +download_btn.grid(row=4, column=1, pady=10) + +# Progress bar +progress_var = tk.DoubleVar() +progress_bar = ttk.Progressbar(frame, orient="horizontal", length=300, variable=progress_var, maximum=100) +progress_bar.grid(row=5, column=0, columnspan=3, pady=5) + +app.mainloop() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e563797 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +tkinter \ No newline at end of file