#!/usr/bin/env python3 """H3 Console:给 gateway.py 加一层 Web UI + 上传 + 任务持久化。 不重做调度——gateway.py 已经做了选后端/分区路由/限流,这里只反代它的 /v1/videos* 接口,加三样它没有的东西:文件上传(返回可喂给 api.py 的 URL)、 SQLite 任务影子记录(gateway.py 的 JOBS 在后端进程内存里,进程重启就丢)、 静态前端。 弹性 partition 调度器(kill+restart 某个 GPU 后端切 fl2va/ref2va)只在 H3_ENABLE_SUPERVISOR=1 时启用——这一层直接操作服务器上的真实进程,本地 Mac 开发环境没有意义,见 DESIGN.md 「四点五」。 """ import os, re, sqlite3, time, uuid, json, asyncio, subprocess from pathlib import Path from typing import Optional import hmac import httpx from fastapi import APIRouter, Depends, FastAPI, HTTPException, UploadFile, File, Request from fastapi.responses import StreamingResponse, FileResponse, HTMLResponse, Response from fastapi.staticfiles import StaticFiles from PIL import Image BASE = Path(__file__).resolve().parent ASSETS = BASE / "assets" ASSETS.mkdir(exist_ok=True) DB_PATH = BASE / "console.sqlite3" GATEWAY_URL = os.environ.get("H3_GATEWAY_URL", "http://192.168.110.67:8000") CONSOLE_PUBLIC_BASE = os.environ.get("H3_CONSOLE_PUBLIC_BASE") # 供后端 worker 回读上传图片用;见 README MAX_UPLOAD_BYTES = 20 * 1024 * 1024 # 20MB,够单张参考图/首尾帧,防止占满磁盘 MAX_VIDEO_UPLOAD_BYTES = 100 * 1024 * 1024 # 100MB,参考视频(2-15秒)比图片大得多 MAX_AUDIO_UPLOAD_BYTES = 30 * 1024 * 1024 # 30MB,独立音频参考 ENABLE_SUPERVISOR = os.environ.get("H3_ENABLE_SUPERVISOR") == "1" # 部署在共享域名的子路径下时设这个(比如挂在 qwen.wudaima.com/console 而不是独立域名), # 见 README「子路径部署」。留空就是原来的行为,挂在根路径,本地/局域网直连不受影响。 BASE_PATH = os.environ.get("H3_CONSOLE_BASE_PATH", "").rstrip("/") # 公网直接可达(qwen.wudaima.com/console 无需登录就能提交任务/看到所有历史任务),设了这个 # 才校验 /v1/* 接口;留空等于原来的行为(局域网/本地开发不用配)。`