YouTube-Downloader: Simpel, kostenlos, ohne Limits, Open Source

20. März 2025 (zuletzt aktualisiert am 24. März 2025)

Ein zuverlässiger YouTube-Downloader ist heutzutage schwer zu finden – viele kostenlose Tools funktionieren nicht mehr, sind eingeschränkt oder gar nicht kostenlos. Deshalb habe ich ein eigenes Python-Skript entwickelt, das YouTube-Videos als MP4 oder MP3 herunterlädt, mit einer einfachen GUI und ohne Einschränkungen. Hier erzähle ich, wie es entstanden ist, wie es funktioniert und was du brauchst, um es selbst zu nutzen.

Bildschirmfoto zu 2025 03 20 16 58 50
Bis jetzt als Python-Skript auf Linux getestet. Bedienung 1. Youtube-URL eingeben 2. Zielordner auswählen. 3. Gewünschten Dateinamen eintragen ohne Dateiendung. 4. MP4 (Video) oder MP3 (nur Ton) auswählen. 5. Download starten.

Bedienung: Bisher getestet mit Python 3 auf Ubuntu Mate und Windows 7 (32 Bit).

1. Youtube-URL eingeben
2. Zielordner des Downloads bestimmen
3. Gewünschten Dateinamen eintragen (ohne Endung .mp3 oder .mp4)
4. MP3 (Nur Musik) oder MP4 (Video mit Ton) auswählen
5. Download starten
6. Fortschrittsbalken verfolgen
7. Hinweisfenster abwarten, der den Download bestätigt

Der Download der Youtube-Videos ist also denkbar einfach einzleiten.

Skript zum Download in einer Zip-Datei : yt-mp4-mp3-downloader.py.zip

Abhängigkeiten unter Linux (Debian, Ubuntu) installieren: Python 3 muss natürlich installiert sein, was in der Regel auf Linux-Distrubitionen der Fall ist.

sudo apt update 
sudo apt install ffmpeg -y 
pip3 install yt-dlp

Download (etwa 31 MByte) des Skripts als ausführbare Datei für Linux (Debian / Ubuntu): http://www.janson-soft.de/ubuntu/yt-playlist-downloader.zip

Diese ausführbare Datei benötigt nur noch ffmpeg für die Umwandlung von mp4 nach mp3. So installierst du ffmpeg unter Linux:

sudo apt update 
sudo apt install ffmpeg -y

Mehr dazu weiter unten im Artikel.

Installation unter Windows: Bis jetzt mit Windows 7 32 Bit getestet. Anleitung: https://grok.com/share/bGVnYWN5_9f3b39b5-48ea-4b7a-a57e-142f0289c35a. MP4 und MP3 funktionieren. Bei MP3 blieben noch ein paar temporäre Dateien auf den Desktop übrig, die sich erst nach dem Neustart von Windows verschwanden.

Übrigens ist es nicht empfehlenswert zum Beispiel mit PyInstaller aus dem Python-Script eine EXE-Datei zu erzeugen. Es geht im Prinzip und sie lässt sich auch auf Windows 7 abspielen.  Aber nun kommt das bekannte Problem. Windows glaubt es würde Viren enthalten. Windows 7 warnt davor. Windows 10 weigert sich die EXE abzuspielen und löscht sie sogar. Bei Windows 11  habe ich es erst garnicht probiert.

Youtube video downloader win7 32bit
Erster Test unter Windows 7. MP4-Download und die Erzeugung von MP3-Dateien funktionieren.

Das auf Windows 7 heruntergeladene Video konnte mit VLC (VideoLan) hochauflösend abgespielt werden. Die erzeugte MP3-Datei ist ebenfalls in sehr guter Tonqualität.

Bildschirmfoto zu 2025 03 21 18 24 05
Codec-Informationen des heruntergeladenen Videos
Bildschirmfoto zu 2025 03 21 18 35 01
Codec der erzeugten MP3-Datei.

Wie das Programm entstanden ist? Die Idee kam aus der Frustration: Viele YouTube-Downloader, die ich früher genutzt habe, funktionierten plötzlich nicht mehr – YouTube ändert ständig seine Technik, um Downloads zu erschweren. Browser-Plugins waren eingeschränkt, kostenlose Programme hatten Werbung oder Paywalls, und die Kommandozeilen-Tools waren für viele zu kompliziert. Also habe ich mich hingesetzt und ein Python-Skript geschrieben, das nicht nur zuverlässig lädt, sondern auch eine einfache grafische Oberfläche bietet. Entwickelt wurde es mit Hilfe von Grok 3 (von xAI), das mir bei der Feinabstimmung und Optimierung geholfen hat. Getestet habe ich es auf Ubuntu, aber eine Windows-Adaption ist geplant.

Das Skript für Python 3:

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import yt_dlp
import os
import threading
import time
import subprocess

class YouTubeDownloader:
    def __init__(self, root):
        self.root = root
        self.root.title("YouTube Downloader")
        self.root.geometry("500x450")
        self.root.configure(bg="#A3B7C2")  # Graublau als Hintergrund

        # GUI-Elemente
        self.create_widgets()

    def create_widgets(self):
        style = ttk.Style()
        style.configure("TProgressbar", background="#6B8799")
        style.configure("TButton", background="#8FA3B2", foreground="#2F3D4A")
        style.configure("TCombobox", fieldbackground="#C2D3DE", foreground="#2F3D4A")

        url_label = tk.Label(self.root, text="YouTube URL:", bg="#A3B7C2", fg="#2F3D4A")
        url_label.pack(pady=10, anchor="center")
        self.url_entry = tk.Entry(self.root, width=50, bg="#C2D3DE", fg="#2F3D4A", insertbackground="#2F3D4A")
        self.url_entry.pack(pady=5, anchor="center")

        save_label = tk.Label(self.root, text="Speicherort:", bg="#A3B7C2", fg="#2F3D4A")
        save_label.pack(pady=10, anchor="center")
        save_frame = tk.Frame(self.root, bg="#A3B7C2")
        save_frame.pack(anchor="center")
        self.save_path_var = tk.StringVar(value=os.getcwd())
        self.save_path_entry = tk.Entry(save_frame, textvariable=self.save_path_var, width=40, bg="#C2D3DE", fg="#2F3D4A", insertbackground="#2F3D4A")
        self.save_path_entry.pack(side=tk.LEFT, pady=5)
        browse_button = tk.Button(save_frame, text="Durchsuchen", command=self.browse_save_path, bg="#8FA3B2", fg="#2F3D4A")
        browse_button.pack(side=tk.LEFT, padx=5)

        filename_label = tk.Label(self.root, text="Dateiname (ohne Endung):", bg="#A3B7C2", fg="#2F3D4A")
        filename_label.pack(pady=10, anchor="center")
        self.filename_entry = tk.Entry(self.root, width=50, bg="#C2D3DE", fg="#2F3D4A", insertbackground="#2F3D4A")
        self.filename_entry.pack(pady=5, anchor="center")

        format_label = tk.Label(self.root, text="Format wählen:", bg="#A3B7C2", fg="#2F3D4A")
        format_label.pack(pady=10, anchor="center")
        self.format_var = tk.StringVar(value="MP4")
        format_combo = ttk.Combobox(self.root, textvariable=self.format_var, values=["MP4", "MP3"], state="readonly", style="TCombobox")
        format_combo.pack(pady=5, anchor="center")

        self.download_button = tk.Button(self.root, text="Download starten", command=self.start_download, bg="#8FA3B2", fg="#2F3D4A")
        self.download_button.pack(pady=15, anchor="center")

        self.progress = ttk.Progressbar(self.root, length=400, mode="determinate", style="TProgressbar")
        self.progress.pack(pady=10, anchor="center")

        self.status_label = tk.Label(self.root, text="Bereit", bg="#A3B7C2", fg="#2F3D4A")
        self.status_label.pack(pady=10, anchor="center")

    def browse_save_path(self):
        folder = filedialog.askdirectory()
        if folder:
            self.save_path_var.set(folder)

    def download_video(self, url, save_path, filename):
        format_choice = self.format_var.get()
        mp4_file = os.path.join(save_path, f"{filename}.mp4")
        mp3_file = os.path.join(save_path, f"{filename}.mp3")
        output_template = os.path.join(save_path, f"{filename}.%(ext)s")

        # Immer zuerst als MP4 herunterladen
        ydl_opts = {
            "format": "bestvideo+bestaudio/best",
            "outtmpl": output_template,
            "merge_output_format": "mp4",
            "quiet": True,
            "progress_hooks": [self.progress_hook],
            "nopart": False,
        }

        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                self.status_label.config(text="Download läuft...")
                self.download_button.config(state="disabled")
                ydl.download([url])
                if not os.path.exists(mp4_file):
                    raise Exception("MP4-Datei wurde nicht erstellt")

            if format_choice == "MP3":
                self.status_label.config(text="Konvertiere zu MP3...")
                # MP4 zu MP3 umwandeln mit ffmpeg
                ffmpeg_cmd = [
                    "ffmpeg", "-i", mp4_file, "-vn", "-acodec", "mp3", "-ab", "192k", "-y", mp3_file
                ]
                result = subprocess.run(ffmpeg_cmd, capture_output=True, text=True)
                if result.returncode != 0:
                    raise Exception(f"Konvertierung fehlgeschlagen: {result.stderr}")
                # Temporäre MP4-Datei löschen
                os.remove(mp4_file)
                final_file = mp3_file
                file_extension = "mp3"
            else:
                final_file = mp4_file
                file_extension = "mp4"

            self.status_label.config(text=f"Download abgeschlossen: {filename}.{file_extension}")
            self.progress["value"] = 100
            messagebox.showinfo("Erfolg", f"Datei wurde als {filename}.{file_extension} gespeichert!")
        except Exception as e:
            messagebox.showerror("Fehler", f"Download oder Konvertierung fehlgeschlagen: {str(e)}")
            self.status_label.config(text="Fehler beim Download/Konvertierung")
        finally:
            time.sleep(2)
            self.cleanup_temp_files(save_path, filename)
            self.download_button.config(state="normal")

    def progress_hook(self, d):
        if d["status"] == "downloading":
            total = d.get("total_bytes") or d.get("total_bytes_estimate", 0)
            downloaded = d.get("downloaded_bytes", 0)
            if total > 0:
                percentage = (downloaded / total) * 100
                self.progress["value"] = percentage
                self.root.update_idletasks()
        elif d["status"] == "finished":
            self.progress["value"] = 100

    def cleanup_temp_files(self, save_path, filename):
        self.status_label.config(text="Bereinige temporäre Dateien...")
        temp_extensions = [".part", ".f[0-9]*", ".ytdl"]
        for file in os.listdir(save_path):
            if file.startswith(filename) and any(file.endswith(ext) or "Frag" in file for ext in temp_extensions):
                file_path = os.path.join(save_path, file)
                for _ in range(5):
                    try:
                        os.remove(file_path)
                        self.status_label.config(text=f"Gelöscht: {file}")
                        break
                    except PermissionError:
                        time.sleep(1)
                    except Exception as e:
                        self.status_label.config(text=f"Konnte {file} nicht löschen: {str(e)}")
                        break
        self.status_label.config(text="Bereinigung abgeschlossen")

    def start_download(self):
        url = self.url_entry.get().strip()
        save_path = self.save_path_var.get().strip()
        filename = self.filename_entry.get().strip()

        if not url:
            messagebox.showwarning("Eingabe fehlt", "Bitte gib eine YouTube-URL ein!")
            return
        if not save_path:
            messagebox.showwarning("Eingabe fehlt", "Bitte wähle einen Speicherort!")
            return
        if not filename:
            messagebox.showwarning("Eingabe fehlt", "Bitte gib einen Dateinamen ein!")
            return

        self.progress["value"] = 0
        threading.Thread(target=self.download_video, args=(url, save_path, filename), daemon=True).start()

    def on_closing(self):
        self.root.destroy()

if __name__ == "__main__":
    root = tk.Tk()
    app = YouTubeDownloader(root)
    root.protocol("WM_DELETE_WINDOW", app.on_closing)
    root.mainloop()

Wie das Python-Skript funktioniert? Das Skript ist eine Kombination aus moderner Technik und simpler Bedienung. Die GUI basiert auf `tkinter`, einer Standard-Python-Bibliothek, die ich mit einem graublauen Farbschema verschönert habe. Du gibst eine YouTube-URL ein, wählst einen Speicherort und Dateinamen, und entscheidest, ob du MP4 (Video + Audio) oder MP3 (nur Audio) willst. Der Download läuft über `yt-dlp`, das die Videodaten holt. Für MP4 wird das Video direkt gespeichert, für MP3 wird es zuerst als MP4 geladen und dann mit `ffmpeg` in MP3 umgewandelt. Ein Fortschrittsbalken zeigt den Status, und temporäre Dateien werden automatisch bereinigt. Alles läuft in einem Hintergrund-Thread, damit die Oberfläche reaktiv bleibt.

Abhängigkeiten: yt-dlp und ffmpeg: Damit das Skript funktioniert, brauchst du neben Python 3 zwei externe Tools: `yt-dlp` und `ffmpeg`. `yt-dlp` ist eine Weiterentwicklung von `youtube-dl` und holt die Inhalte von YouTube, während `ffmpeg` für die Konvertierung von MP4 zu MP3 und das Mergen von Video- und Audiospuren zuständig ist. Installation unter Ubuntu ist einfach:

sudo apt update
sudo apt install ffmpeg -y
pip3 install yt-dlp

Das installiert alles, was du brauchst: Python, `tkinter`, `ffmpeg` und `yt-dlp`. Teste es mit `yt-dlp –version` und `ffmpeg -version`, um sicherzugehen.

Python 3 und Plattform: Das Skript setzt Python 3 voraus, das auf den meisten modernen Systemen vorinstalliert ist. Entwickelt und getestet wurde es auf Ubuntu, einer weit verbreiteten Linux-Distribution. Es sollte auch auf anderen Linux-Systemen laufen, solange die Abhängigkeiten erfüllt sind. Eine Adaption für Windows ist in Planung – die Herausforderung liegt hier in der Anpassung der Pfade und der Audiowiedergabe, aber mit `ffmpeg` und `yt-dlp` sollte der Kern auch dort funktionieren.

Bildschirmfoto zu 2025 03 19 22 14 06
Das Skript lässt sich unter Linux auch mit der Python-IDE Thonny aufrufen. Dann sieht man weitere Informationen über den Verlauf des Downloads

Motivation: Warum das Ganze? :Die Motivation war klar: Die meisten YouTube-Downloader sind entweder kaputt oder eingeschränkt. Kostenlose Versionen funktionieren oft nicht mehr, weil YouTube seine API oder Streaming-Techniken ändert. Programme mit GUI kosten schnell Geld, und Kommandozeilen-Tools wie `youtube-dl` sind für Laien schwer zugänglich. Mein Skript ist kostenlos, open-source, und dank `yt-dlp` bleibt es aktuell, da die Entwickler regelmäßig Updates liefern. Es ist eine einfache, flexible Lösung für alle, die Videos oder Audios schnell offline haben wollen.

Rechtliche Hinweise: Ein wichtiger Punkt: Beim Herunterladen von YouTube-Inhalten musst du die Nutzungs- und Urheberrechte beachten. YouTube erlaubt das Herunterladen nur für persönliche Nutzung, wenn der Uploader es gestattet – alles andere kann rechtliche Konsequenzen haben, und die werden teuer. Die Gesetzeslage unterscheidet sich von Land zu Land: In Deutschland ist das private Kopieren von urheberrechtlich geschütztem Material unter Umständen erlaubt, aber das Verbreiten oder kommerzielle Nutzen strikt verboten. Informiere dich über die Regeln in deinem Land, bevor du loslegst!

Fazit und Ausblick: Dieser YouTube-Downloader ist eine kleine Bastellösung mit großem Nutzen. Er kombiniert Zuverlässigkeit mit Benutzerfreundlichkeit und bleibt dank `yt-dlp` anpassungsfähig an YouTubes Änderungen. Für mich war es ein spannendes Projekt, um eine Lücke zu schließen, die viele nervt. Geplant ist noch eine Windows-Version und vielleicht eine Option für Qualitätsauswahl (z. B. 720p oder 1080p). Wenn du Vorschläge hast, lass es mich wissen – der Code ist offen für Erweiterungen. Bis dahin: Viel Spaß beim Herunterladen – aber immer mit Blick auf die rechtlichen Grenzen!