commit 3b5621142cd1800b7807c9a6c8a4fa4347199b35 Author: TylerCG <117808427+TylerCG@users.noreply.github.com> Date: Sun Jun 22 17:24:57 2025 -0400 Created files diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..bc052c3 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.11-slim + +RUN apt-get update && apt-get install -y ffmpeg + +WORKDIR /app + +COPY . . + +RUN pip install --no-cache-dir -r requirements.txt + +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/backend/main.py b/backend/main.py new file mode 100644 index 0000000..8968dac --- /dev/null +++ b/backend/main.py @@ -0,0 +1,57 @@ +from fastapi import FastAPI, UploadFile, File, Form, HTTPException +from fastapi.responses import FileResponse +from fastapi.middleware.cors import CORSMiddleware +import yaml +import os +import subprocess +from pathlib import Path +from utils import parse_yaml_config, get_presets_dir + +app = FastAPI() + +# Allow CORS (frontend access) +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_methods=["*"], + allow_headers=["*"], +) + +@app.post("/upload-config/") +async def upload_config(file: UploadFile = File(...)): + config_data = yaml.safe_load(await file.read()) + return {"parsed": config_data} + +@app.post("/transcode/") +async def transcode(yaml_config: dict): + try: + ffmpeg_cmd = parse_yaml_config(yaml_config) + subprocess.run(ffmpeg_cmd, check=True) + return {"status": "success", "cmd": ffmpeg_cmd} + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +@app.get("/browse/") +def browse(path: str = "/data"): + if not os.path.exists(path): + raise HTTPException(status_code=404, detail="Path not found") + entries = [{"name": f, "is_dir": os.path.isdir(os.path.join(path, f))} for f in os.listdir(path)] + return {"path": path, "entries": entries} + +@app.post("/save-preset/") +def save_preset(name: str = Form(...), file: UploadFile = File(...)): + path = get_presets_dir() / f"{name}.yml" + with open(path, "wb") as f: + f.write(file.file.read()) + return {"message": "Preset saved"} + +@app.get("/list-presets/") +def list_presets(): + return {"presets": [p.stem for p in get_presets_dir().glob("*.yml")]} + +@app.get("/preset/{name}") +def get_preset(name: str): + path = get_presets_dir() / f"{name}.yml" + if not path.exists(): + raise HTTPException(status_code=404, detail="Preset not found") + return FileResponse(path) diff --git a/backend/requirements.txt b/backend/requirements.txt new file mode 100644 index 0000000..fc1a57d --- /dev/null +++ b/backend/requirements.txt @@ -0,0 +1,3 @@ +fastapi +uvicorn +pyyaml diff --git a/backend/utils.py b/backend/utils.py new file mode 100644 index 0000000..ba8ad34 --- /dev/null +++ b/backend/utils.py @@ -0,0 +1,30 @@ +from pathlib import Path + +def get_presets_dir() -> Path: + Path("./presets").mkdir(exist_ok=True) + return Path("./presets") + +def parse_yaml_config(config: dict) -> list: + in_file = config.get("input_file") + out_file = config.get("output_file") + video = config.get("video", {}) + audio = config.get("audio", {}) + + cmd = ["ffmpeg", "-y", "-i", in_file] + + if video: + cmd += ["-c:v", video.get("codec", "libx264")] + if "bitrate" in video: + cmd += ["-b:v", video["bitrate"]] + if "preset" in video: + cmd += ["-preset", video["preset"]] + + if audio: + cmd += ["-c:a", audio.get("codec", "aac")] + if "bitrate" in audio: + cmd += ["-b:a", audio["bitrate"]] + if "channels" in audio: + cmd += ["-ac", str(audio["channels"])] + + cmd += [out_file] + return cmd diff --git a/docker-compoe.yml b/docker-compoe.yml new file mode 100644 index 0000000..eda13da --- /dev/null +++ b/docker-compoe.yml @@ -0,0 +1,12 @@ +version: "3.8" + +services: + backend: + build: ./backend + volumes: + - ./data:/data + - ./backend/presets:/app/presets + ports: + - "8000:8000" + + # (Frontend to be added here)