Files
he d01228a21e feat(GUI): web interface for install and pos commands
- gui/main.py: FastAPI app with Jinja2 templates and static files
- gui/state.py: shared application state (runner, template env)
- gui/services/pos_runner.py: abstracted command execution layer
  with subprocess, SSE streaming, and sudo support
- gui/routes/: 8 route modules (dashboard, install, compose,
  network, vbox, system, media, ssh)
- gui/templates/: Bulma-based layout with sidebar navigation +
  section templates for all routes
- gui/static/css/style.css: dark theme styling
- gui/requirements.txt: fastapi, uvicorn, jinja2, python-multipart
- 1- Start_GUI.sh: entry point with sudo cache, pip install, uvicorn launch

Architecture: routes delegate to pos_runner which shells out to
actual pos-* scripts — no logic duplication. SSE streaming for
real-time output (install, compose up/down/logs, network scan, media).
2026-07-28 11:47:48 -04:00

40 lines
1.3 KiB
Python

from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse, StreamingResponse
from gui.state import runner, templates
router = APIRouter(prefix="/media")
@router.get("", response_class=HTMLResponse)
async def media_page(request: Request):
return templates.TemplateResponse(
"media/index.html", {"request": request, "active": "media"}
)
@router.post("/mp3/stream")
async def media_mp3_stream(url: str = Form(...)):
async def generate():
async for event in runner.stream(f"pos media mp3 {url}"):
yield f"event: {event['event']}\ndata: {event['data']}\n\n"
return StreamingResponse(generate(), media_type="text/event-stream")
@router.post("/mp4/formats")
async def media_mp4_formats(url: str = Form(...)):
code, out, err = await runner.run(f"yt-dlp -F {url}")
return {"ok": code == 0, "output": out or err}
@router.post("/mp4/stream")
async def media_mp4_stream(url: str = Form(...), format_id: str = Form(...)):
async def generate():
async for event in runner.stream(
f"yt-dlp -f {format_id} --merge-output-format mp4 --embed-thumbnail --add-metadata -o '~/Videos/%(title)s.%(ext)s' {url}"
):
yield f"event: {event['event']}\ndata: {event['data']}\n\n"
return StreamingResponse(generate(), media_type="text/event-stream")