73 lines
2.9 KiB
Python
73 lines
2.9 KiB
Python
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:
|
|
flash(f'Ein Fehler ist aufgetreten: {str(e)}', 'error')
|
|
|
|
return redirect(url_for('index'))
|
|
|
|
@app.route('/play/<filename>')
|
|
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 |