Files
ai-video-fullstack/backend/routes/input_assets.py
Xin Wang e36ca308b8 feat: support uploaded images in debug voice preview
Allow paste/drag temporary image assets so vision turns work without a live camera frame.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 19:52:37 +08:00

60 lines
1.8 KiB
Python

"""Authenticated upload endpoint for pending debug-chat image attachments."""
from __future__ import annotations
import asyncio
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from pydantic import BaseModel
import settings
from services.auth import require_admin
from services.input_assets import discard_input_image, store_input_image
router = APIRouter(
prefix="/api/input-assets",
tags=["input-assets"],
dependencies=[Depends(require_admin)],
)
class InputImageAssetOut(BaseModel):
assetToken: str
width: int
height: int
sizeBytes: int
@router.post("/image", response_model=InputImageAssetOut)
async def upload_input_image(file: UploadFile = File(...)):
data = await file.read(settings.INPUT_IMAGE_MAX_BYTES + 1)
if len(data) > settings.INPUT_IMAGE_MAX_BYTES:
limit_mb = settings.INPUT_IMAGE_MAX_BYTES // 1024 // 1024
raise HTTPException(413, f"图片不能超过 {limit_mb} MB")
if not data:
raise HTTPException(400, "图片文件不能为空")
try:
stored = await asyncio.to_thread(store_input_image, data)
except ValueError as exc:
raise HTTPException(400, str(exc)) from exc
except Exception as exc:
raise HTTPException(503, "图片暂时无法上传,请确认对象存储可用") from exc
return InputImageAssetOut(
assetToken=stored.token,
width=stored.width,
height=stored.height,
sizeBytes=stored.size_bytes,
)
@router.delete("/{asset_token}")
async def delete_input_image(asset_token: str):
try:
await asyncio.to_thread(discard_input_image, asset_token)
except ValueError as exc:
raise HTTPException(400, str(exc)) from exc
except Exception as exc:
raise HTTPException(503, "图片附件暂时无法清理") from exc
return {"ok": True}