101 lines
2.9 KiB
Python
101 lines
2.9 KiB
Python
from flask import Flask, render_template, request, jsonify
|
||
import yt_dlp
|
||
import os
|
||
import threading
|
||
|
||
app = Flask(__name__)
|
||
|
||
DOWNLOAD_DIR = os.path.join(os.path.dirname(__file__), "downloads")
|
||
os.makedirs(DOWNLOAD_DIR, exist_ok=True)
|
||
|
||
download_status = {}
|
||
|
||
|
||
def do_download(task_id, url, artist, title, album):
|
||
try:
|
||
download_status[task_id] = {"status": "running", "message": "Download läuft..."}
|
||
|
||
ydl_opts = {
|
||
"format": "bestaudio/best",
|
||
"outtmpl": os.path.join(DOWNLOAD_DIR, "%(title)s.%(ext)s"),
|
||
"postprocessors": [
|
||
{
|
||
"key": "FFmpegExtractAudio",
|
||
"preferredcodec": "mp3",
|
||
"preferredquality": "192",
|
||
},
|
||
{
|
||
"key": "FFmpegMetadata",
|
||
"add_metadata": True,
|
||
},
|
||
],
|
||
# Scoped to FFmpegMetadata so tags are set correctly
|
||
"postprocessor_args": {
|
||
"ffmpegmetadata": [
|
||
"-metadata", f"artist={artist}",
|
||
"-metadata", f"title={title}",
|
||
"-metadata", f"album={album}",
|
||
]
|
||
},
|
||
"quiet": True,
|
||
"no_warnings": True,
|
||
}
|
||
|
||
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||
info = ydl.extract_info(url, download=True)
|
||
|
||
# extract_info kann eine Playlist zurückgeben – dann erstes Entry nehmen
|
||
if info is None:
|
||
raise RuntimeError("yt-dlp hat keine Informationen zurückgegeben. Bitte URL prüfen.")
|
||
if "entries" in info:
|
||
info = info["entries"][0]
|
||
|
||
filename = ydl.prepare_filename(info)
|
||
mp3_name = os.path.splitext(os.path.basename(filename))[0] + ".mp3"
|
||
|
||
download_status[task_id] = {
|
||
"status": "done",
|
||
"message": f"Fertig! Gespeichert als: {mp3_name}",
|
||
"filename": mp3_name,
|
||
}
|
||
|
||
except Exception as e:
|
||
download_status[task_id] = {
|
||
"status": "error",
|
||
"message": f"Fehler: {str(e)}",
|
||
}
|
||
|
||
|
||
@app.route("/")
|
||
def index():
|
||
return render_template("index.html")
|
||
|
||
|
||
@app.route("/download", methods=["POST"])
|
||
def download():
|
||
data = request.get_json()
|
||
url = data.get("url", "").strip()
|
||
artist = data.get("artist", "").strip()
|
||
title = data.get("title", "").strip()
|
||
album = data.get("album", "").strip()
|
||
|
||
if not url:
|
||
return jsonify({"error": "URL fehlt"}), 400
|
||
|
||
import uuid
|
||
task_id = str(uuid.uuid4())
|
||
thread = threading.Thread(target=do_download, args=(task_id, url, artist, title, album))
|
||
thread.daemon = True
|
||
thread.start()
|
||
|
||
return jsonify({"task_id": task_id})
|
||
|
||
|
||
@app.route("/status/<task_id>")
|
||
def status(task_id):
|
||
result = download_status.get(task_id, {"status": "unknown", "message": "Unbekannte Task-ID"})
|
||
return jsonify(result)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
app.run(debug=True, port=5000)
|