auto-save 2026-05-13 20:56 (~7)
This commit is contained in:
44
api/main.py
44
api/main.py
@@ -35,10 +35,17 @@ VIDEO_MODEL_ALIASES = {
|
||||
"seedance": os.getenv("VIDEO_MODEL_SEEDANCE", "seedance").strip() or "seedance",
|
||||
"kling": os.getenv("VIDEO_MODEL_KLING", "kling").strip() or "kling",
|
||||
"veo3": os.getenv("VIDEO_MODEL_VEO3", "veo3").strip() or "veo3",
|
||||
"veo": os.getenv("VIDEO_MODEL_VEO3", "veo3").strip() or "veo3",
|
||||
"voe": os.getenv("VIDEO_MODEL_VEO3", "veo3").strip() or "veo3",
|
||||
}
|
||||
VIDEO_API_BASE_URL = os.getenv("VIDEO_API_BASE_URL", "").strip()
|
||||
VIDEO_API_KEY = os.getenv("VIDEO_API_KEY", "").strip()
|
||||
VIDEO_CREATE_PATH = os.getenv("VIDEO_CREATE_PATH", "/videos").strip() or "/videos"
|
||||
VIDEO_CREATE_PATHS = [
|
||||
p.strip()
|
||||
for p in os.getenv("VIDEO_CREATE_PATHS", f"{VIDEO_CREATE_PATH},/videos/generations,/video/generations").split(",")
|
||||
if p.strip()
|
||||
]
|
||||
VIDEO_STATUS_PATH = os.getenv("VIDEO_STATUS_PATH", "/videos/{id}").strip() or "/videos/{id}"
|
||||
VIDEO_CONTENT_PATH = os.getenv("VIDEO_CONTENT_PATH", "/videos/{id}/content").strip() or "/videos/{id}/content"
|
||||
VIDEO_DURATION_FIELD = os.getenv("VIDEO_DURATION_FIELD", "seconds").strip() or "seconds"
|
||||
@@ -210,14 +217,6 @@ def video_path(template: str, **values: str) -> str:
|
||||
|
||||
|
||||
def ensure_video_api_configured() -> None:
|
||||
base = video_api_base()
|
||||
# 已探测:SKG ezlink 当前只开了 chat/images,/videos 返回 404。
|
||||
# 没有显式 VIDEO_API_BASE_URL 时,不再把这个 404 伪装成一次“生成失败”。
|
||||
if not VIDEO_API_BASE_URL and "ai.skg.com/ezlink" in base:
|
||||
raise HTTPException(
|
||||
503,
|
||||
"当前 SKG ezlink baseurl 已连通,但这把 key 未开通生视频 /videos 端点;需要 IT 给该分组开通视频端点,或改用真实 Seedance/Kling/Veo 3 视频 API。",
|
||||
)
|
||||
if not video_api_key():
|
||||
raise HTTPException(503, "VIDEO_API_KEY 或 LLM_API_KEY 未配置,无法调用生视频 API")
|
||||
|
||||
@@ -790,7 +789,8 @@ def health() -> dict:
|
||||
"video": VIDEO_MODEL,
|
||||
"video_aliases": VIDEO_MODEL_ALIASES,
|
||||
"video_base_url": video_api_base() if VIDEO_API_BASE_URL else "",
|
||||
"video_configured": bool(VIDEO_API_BASE_URL and video_api_key()),
|
||||
"video_configured": bool(video_api_key()),
|
||||
"video_create_paths": VIDEO_CREATE_PATHS,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1694,14 +1694,24 @@ def render_storyboard_video(job_id: str, local_id: str, provider_id: str, ref_pa
|
||||
with httpx.Client(timeout=120) as client:
|
||||
payload = {"model": model, "prompt": prompt, "size": size}
|
||||
payload[VIDEO_DURATION_FIELD] = seconds
|
||||
with ref_img.open("rb") as fh:
|
||||
create = client.post(
|
||||
f"{base}{video_path(VIDEO_CREATE_PATH)}",
|
||||
headers=headers,
|
||||
data=payload,
|
||||
files={"input_reference": ("reference.jpg", fh, "image/jpeg")},
|
||||
)
|
||||
create.raise_for_status()
|
||||
create = None
|
||||
create_errors: list[str] = []
|
||||
for create_path in VIDEO_CREATE_PATHS:
|
||||
with ref_img.open("rb") as fh:
|
||||
resp = client.post(
|
||||
f"{base}{video_path(create_path)}",
|
||||
headers=headers,
|
||||
data=payload,
|
||||
files={"input_reference": ("reference.jpg", fh, "image/jpeg")},
|
||||
)
|
||||
if resp.status_code < 400:
|
||||
create = resp
|
||||
break
|
||||
create_errors.append(f"{video_path(create_path)} -> HTTP {resp.status_code}: {resp.text[:160]}")
|
||||
if resp.status_code not in {400, 404, 405}:
|
||||
resp.raise_for_status()
|
||||
if create is None:
|
||||
raise RuntimeError("视频模型已选择,但当前网关视频生成入口不可用;已尝试 " + " | ".join(create_errors))
|
||||
data = create.json()
|
||||
video_api_id = data.get("id") or provider_id or local_id
|
||||
status = normalize_video_status(data.get("status"))
|
||||
|
||||
Reference in New Issue
Block a user