from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash from pytube import YouTube import os import re # Für das Bereinigen von Dateinamen app = Flask(__name__) app.secret_key = 'dein_super_geheimer_schlüssel' # Wichtig für Flash-Nachrichten DOWNLOAD_FOLDER = 'downloads' if not os.path.exists(DOWNLOAD_FOLDER): os.makedirs(DOWNLOAD_FOLDER) def sanitize_filename(filename): """Entfernt ungültige Zeichen aus Dateinamen.""" return re.sub(r'[\\/*?:"<>|]', "", filename) @app.route('/') def index(): try: # Liste nur .mp4 Dateien auf downloaded_files = [f for f in os.listdir(DOWNLOAD_FOLDER) if f.endswith('.mp4')] except FileNotFoundError: downloaded_files = [] return render_template('index.html', files=downloaded_files) @app.route('/download', methods=['POST']) def download_video(): video_url = request.form.get('youtube_url') if not video_url: flash('Bitte gib eine YouTube URL ein.', 'error') return redirect(url_for('index')) try: yt = YouTube(video_url) # Wähle den Stream mit der höchsten Auflösung, der progressiv ist (Audio+Video) und mp4 ist stream = yt.streams.filter(progressive=True, file_extension='mp4')\ .order_by('resolution')\ .desc()\ .first() if not stream: flash(f'Kein passender MP4 Stream für {yt.title} gefunden.', 'error') return redirect(url_for('index')) # Bereinige den Titel für den Dateinamen filename = sanitize_filename(yt.title) + ".mp4" filepath = os.path.join(DOWNLOAD_FOLDER, filename) # Überprüfen, ob die Datei bereits existiert if os.path.exists(filepath): flash(f'Video "{yt.title}" wurde bereits heruntergeladen.', 'info') return redirect(url_for('index')) flash(f'Starte Download für: {yt.title}...', 'info') # Wichtig: Um Flask nicht zu blockieren, könnte man hier Threading/Async verwenden, # aber für ein "einfaches" Skript ist dies der direkteste Weg. # Bei langen Downloads kann der Browser einen Timeout anzeigen, obwohl der Download im Hintergrund läuft. stream.download(output_path=DOWNLOAD_FOLDER, filename=filename) flash(f'Video "{yt.title}" erfolgreich heruntergeladen!', 'success') except Exception as e: import traceback print("---------- ERROR DETAILS ----------") print(f"Error type: {type(e)}") print(f"Error message: {str(e)}") print("Traceback:") traceback.print_exc() # Gibt den kompletten Traceback auf der Konsole aus print("---------------------------------") flash(f'Ein Fehler ist aufgetreten: {str(e)}', 'error') return redirect(url_for('index')) return redirect(url_for('index')) @app.route('/play/') def play_video(filename): # send_from_directory ermöglicht das direkte Abspielen/Herunterladen der Datei return send_from_directory(DOWNLOAD_FOLDER, filename, as_attachment=False) # as_attachment=False versucht, es im Browser abzuspielen if __name__ == '__main__': app.run(debug=True, host='0.0.0.0', port=5555) # host='0.0.0.0' macht es im lokalen Netzwerk erreichbar