This commit is contained in:
2026-02-22 20:27:16 +01:00
commit 0d55e301a5
8 changed files with 468 additions and 0 deletions

69
main.py Normal file
View File

@@ -0,0 +1,69 @@
import os
import uuid
import uvicorn
from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.responses import FileResponse
from pydantic import BaseModel
from yt_dlp import YoutubeDL
app = FastAPI()
# Input schema because we aren't savages
class VideoRequest(BaseModel):
url: str
def cleanup(path: str):
"""Deletes the file after serving because I know you won't."""
try:
os.remove(path)
print(f"Deleted trash: {path}")
except Exception as e:
print(f"Failed to delete {path}: {e}")
@app.post("/audio")
async def download_audio(req: VideoRequest, background_tasks: BackgroundTasks):
# Random ID so concurrent requests don't overwrite each other
file_id = str(uuid.uuid4())
output_template = f"/tmp/{file_id}.%(ext)s"
# yt-dlp config: best audio, force mp3 because whisper hates weird codecs
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': output_template,
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'quiet': True,
'no_warnings': True,
}
try:
with YoutubeDL(ydl_opts) as ydl:
print(f"Yoinking audio from: {req.url}")
info = ydl.extract_info(req.url, download=True)
# yt-dlp might change extension post-processing, so we find the actual file
# usually it's .mp3 if we forced it, but let's be safe
filename = ydl.prepare_filename(info).rsplit('.', 1)[0] + '.mp3'
if not os.path.exists(filename):
raise HTTPException(status_code=500, detail="Download failed, file missing. Blame YouTube.")
# queue the deletion so it happens AFTER the response is sent
background_tasks.add_task(cleanup, filename)
return FileResponse(
path=filename,
filename=f"{file_id}.mp3",
media_type='audio/mpeg'
)
except Exception as e:
print(f"L: {str(e)}")
raise HTTPException(status_code=400, detail=f"Failed to download: {str(e)}")
if __name__ == "__main__":
# Host on 0.0.0.0 so your docker container isn't useless
uvicorn.run(app, host="0.0.0.0", port=8000)