User Tools

Site Tools


ytdl

This is an old revision of the document!


Mikos Batch Downloader

This tool provides a graphical interface for batch downloading videos or audio using yt-dlp. It supports playlists, format selection, cookie authentication, and live progress display.

Features

  • Add multiple video or playlist URLs
  • Choose output directory and optional cookies file
  • Select download format (best, mp4, bestaudio, mp3)
  • Start and cancel downloads with progress feedback
  • View live output from yt-dlp in a text box

Requirements

  • Python 3.x
  • yt-dlp installed and available in system PATH
  • Standard Python libraries:
    • tkinter
    • subprocess
    • threading
    • os
    • re

Usage

  1. Start the GUI by running the script.
  2. Paste a video or playlist URL into the input field.
  3. Click Add Link to queue it.
  4. Choose an output folder and optionally a cookies.txt file.
  5. Select desired format from the dropdown.
  6. Click Start Downloads to begin.
  7. Use Cancel Downloads to stop the current process.

GUI Overview

  • 'URL Entry': Input field for video/playlist links
  • 'Listbox': Displays queued URLs
  • 'Format Dropdown': Choose download format
  • 'Buttons':
    • Add Link
    • Clear List
    • Choose Folder
    • Choose Cookies
    • Start Downloads
    • Cancel Downloads
  • 'Progress Bar': Shows download percentage
  • 'Text Output': Displays live yt-dlp output

Notes

  • Downloads run in a separate thread to keep the GUI responsive.
  • Progress is parsed from yt-dlp output using regular expressions.
  • Audio extraction is supported via –extract-audio for MP3.

License

This script is provided as-is. Feel free to modify and redistribute under an open-source license of your choice.

Code

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import subprocess
import threading
import os
import re
 
download_queue = []
current_process = None
 
# ---------------- GUI ----------------
root = tk.Tk()
root.title("Mikos Batch Downloader")
 
cookies_file = tk.StringVar(master=root)  # für den Cookies-Dateipfad
output_dir = tk.StringVar(master=root)    # Ausgabeverzeichnis
 
def add_link():
    url = url_entry.get()
    if url:
        download_queue.append(url)
        url_listbox.insert(tk.END, url)
        url_entry.delete(0, tk.END)
 
def clear_links():
    download_queue.clear()
    url_listbox.delete(0, tk.END)
 
def choose_directory():
    folder = filedialog.askdirectory()
    if folder:
        output_dir.set(folder)
 
def choose_cookies():
    file = filedialog.askopenfilename(
        title="Choose cookies.txt",
        filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]
    )
    if file:
        cookies_file.set(file)
        status_label.config(text=f"Cookies loaded: {os.path.basename(file)}")
 
def cancel_download():
    global current_process
    if current_process and current_process.poll() is None:
        confirm = messagebox.askyesno("Cancel Download", "Are you sure you want to cancel?")
        if confirm:
            current_process.terminate()
            cancel_button.config(state="disabled")
            status_label.config(text="Download cancelled.")
            progress_text.insert(tk.END, "\nDownload was manually cancelled.\n")
            progress_text.see(tk.END)
 
def start_downloads():
    format_choice = format_var.get()
    out_dir = output_dir.get()
    cookies_path = cookies_file.get()  # ✅ Zugriff im Hauptthread
 
    if not download_queue:
        messagebox.showwarning("No Links", "Please add at least one URL.")
        return
 
    threading.Thread(target=run_downloads, args=(format_choice, out_dir, cookies_path), daemon=True).start()
 
def run_downloads(format_choice, out_dir, cookies_path):
    global current_process
    idx = 0
    cancel_button.config(state="normal")
 
    while idx < len(download_queue):
        url = download_queue[idx]
        status_label.config(text=f"Downloading {idx+1}/{len(download_queue)}…")
        cmd = ["yt-dlp"]
 
        if cookies_path:
            cmd += ["--cookies", cookies_path]
 
        if format_choice == "mp3":
            cmd += ["--extract-audio", "--audio-format", "mp3"]
        else:
            cmd += ["-f", format_choice]
 
        if out_dir:
            cmd += ["-o", os.path.join(out_dir, "%(title)s.%(ext)s")]
 
        cmd.append(url)
 
        try:
            current_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
        except FileNotFoundError:
            messagebox.showerror("Error", "yt-dlp not found. Please ensure it is installed and in PATH.")
            cancel_button.config(state="disabled")
            return
 
        progress_text.delete("1.0", tk.END)
 
        for line in current_process.stdout:
            progress_text.insert(tk.END, line)
            progress_text.see(tk.END)
 
            match = re.search(r"(\d{1,3}(?:\.\d+)?)%", line)
            if match:
                percent = float(match.group(1))
                progress_bar["value"] = percent
 
        current_process.wait()
        progress_bar["value"] = 0  # ✅ Reset nach Abschluss
 
        if current_process.returncode == 0:
            url_listbox.delete(idx)
            download_queue.pop(idx)
        else:
            idx += 1
 
    current_process = None
    cancel_button.config(state="disabled")
    status_label.config(text="All downloads completed.")
    messagebox.showinfo("Done", "All videos have been processed.")
 
# ---------------- GUI Layout ----------------
tk.Label(root, text="Video or Playlist URL:").pack()
url_entry = tk.Entry(root, width=80)
url_entry.pack()
 
button_frame = tk.Frame(root)
button_frame.pack(pady=5)
 
tk.Button(button_frame, text="Add Link", command=add_link).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="Clear List", command=clear_links).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="Choose Folder", command=choose_directory).pack(side=tk.LEFT, padx=5)
tk.Button(button_frame, text="Choose Cookies", command=choose_cookies).pack(side=tk.LEFT, padx=5)
 
url_listbox = tk.Listbox(root, width=80, height=5)
url_listbox.pack(pady=5)
 
tk.Label(root, text="Select Format:").pack()
format_var = tk.StringVar(value="best")
format_dropdown = ttk.Combobox(root, textvariable=format_var, values=["best", "mp4", "bestaudio", "mp3"], width=20)
format_dropdown.pack()
 
tk.Label(root, textvariable=output_dir).pack()
 
action_frame = tk.Frame(root)
action_frame.pack(pady=10)
 
tk.Button(action_frame, text="Start Downloads", command=start_downloads).pack(side=tk.LEFT, padx=10)
cancel_button = tk.Button(action_frame, text="Cancel Downloads", command=cancel_download, state="disabled")
cancel_button.pack(side=tk.LEFT, padx=10)
 
status_label = tk.Label(root, text="Ready")
status_label.pack()
 
progress_bar = ttk.Progressbar(root, length=400, mode="determinate")
progress_bar.pack(pady=5)
 
progress_text = tk.Text(root, height=10, width=80)
progress_text.pack()
 
root.mainloop()
ytdl.1760805315.txt.gz · Last modified: (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki