From 31cb874028f38d58d451b73ff8b819b356bd9014 Mon Sep 17 00:00:00 2001 From: kang Date: Thu, 14 May 2026 13:32:50 +0800 Subject: [PATCH] auto-save 2026-05-14 13:32 (~4) --- .memory/worklog.json | 27 +++++++++++++-------------- api/.env.example | 4 ++++ api/main.py | 31 +++++++++++++++++++++++++++---- docs/source-analysis.html | 17 +++++++++++++++-- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/.memory/worklog.json b/.memory/worklog.json index 7c6179d..4e1c284 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,19 +1,5 @@ { "entries": [ - { - "files_changed": 1, - "hash": "686baa1", - "message": "auto-save 2026-05-13 08:51 (~1)", - "ts": "2026-05-13T08:52:11+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "hash": "afab4bc", - "message": "auto-save 2026-05-13 08:57 (~1)", - "ts": "2026-05-13T08:57:46+08:00", - "type": "commit" - }, { "files_changed": 1, "hash": "d6a5223", @@ -3278,6 +3264,19 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 1 项未提交变更 · 最近提交:auto-save 2026-05-14 13:21 (~3)", "files_changed": 1 + }, + { + "ts": "2026-05-14T13:27:18+08:00", + "type": "commit", + "message": "auto-save 2026-05-14 13:27 (~1)", + "hash": "00435b2", + "files_changed": 1 + }, + { + "ts": "2026-05-14T05:28:40Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 2 项未提交变更 · 最近提交:auto-save 2026-05-14 13:27 (~1)", + "files_changed": 2 } ] } diff --git a/api/.env.example b/api/.env.example index a49662b..7dba4ed 100644 --- a/api/.env.example +++ b/api/.env.example @@ -36,6 +36,10 @@ POE_API_KEY= # SKG 豆包/Seedance 视频网关也使用同一套 content JSON 提交格式: # VIDEO_API_BASE_URL=https://ai.skg.com/doubao # VIDEO_API_KEY= +# VIDEO_MODEL_SEEDANCE=doubao-seedance-2-0-fast-260128 +# VIDEO_CREATE_PATHS=/api/v3/contents/generations/tasks +# VIDEO_STATUS_PATH=/api/v3/contents/generations/tasks/{id} +# VIDEO_CONTENT_PATH=/api/v3/contents/generations/tasks/{id}/content # # 自定义视频网关覆盖;留空时如配置 POE_API_KEY,则走 Poe。 VIDEO_API_BASE_URL= diff --git a/api/main.py b/api/main.py index 14e179b..3f8a770 100644 --- a/api/main.py +++ b/api/main.py @@ -91,14 +91,37 @@ VIDEO_MODEL_ALIASES = { } 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" + + +def default_video_gateway_paths(base_url: str) -> tuple[str, str, str]: + base = base_url.strip().rstrip("/").lower() + if "ai.skg.com/doubao" in base: + return ( + "/api/v3/contents/generations/tasks", + "/api/v3/contents/generations/tasks/{id}", + "/api/v3/contents/generations/tasks/{id}/content", + ) + if "ark.cn-beijing.volces.com" in base: + return ( + "/contents/generations/tasks", + "/contents/generations/tasks/{id}", + "/contents/generations/tasks/{id}/content", + ) + return ("/videos", "/videos/{id}", "/videos/{id}/content") + + +DEFAULT_VIDEO_CREATE_PATH, DEFAULT_VIDEO_STATUS_PATH, DEFAULT_VIDEO_CONTENT_PATH = default_video_gateway_paths(VIDEO_API_BASE_URL) +VIDEO_CREATE_PATH = os.getenv("VIDEO_CREATE_PATH", DEFAULT_VIDEO_CREATE_PATH).strip() or DEFAULT_VIDEO_CREATE_PATH VIDEO_CREATE_PATHS = [ p.strip() - for p in os.getenv("VIDEO_CREATE_PATHS", f"{VIDEO_CREATE_PATH},/videos/generations,/video/generations").split(",") + for p in os.getenv( + "VIDEO_CREATE_PATHS", + VIDEO_CREATE_PATH if VIDEO_CREATE_PATH != "/videos" else 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_STATUS_PATH = os.getenv("VIDEO_STATUS_PATH", DEFAULT_VIDEO_STATUS_PATH).strip() or DEFAULT_VIDEO_STATUS_PATH +VIDEO_CONTENT_PATH = os.getenv("VIDEO_CONTENT_PATH", DEFAULT_VIDEO_CONTENT_PATH).strip() or DEFAULT_VIDEO_CONTENT_PATH VIDEO_DURATION_FIELD = os.getenv("VIDEO_DURATION_FIELD", "seconds").strip() or "seconds" VIDEO_POLL_TIMEOUT_SECONDS = max(60, int(os.getenv("VIDEO_POLL_TIMEOUT_SECONDS", "900"))) diff --git a/docs/source-analysis.html b/docs/source-analysis.html index 109eec0..2f2b461 100644 --- a/docs/source-analysis.html +++ b/docs/source-analysis.html @@ -919,6 +919,19 @@ SubjectAsset {

变更记录

这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。

+
+
+

2026-05-14 · 修正 SKG 豆包视频网关路径

+ Video Gen + Seedance +
+
+

问题:产品融合视频能进入队列,但后台任务 5% 后失败,错误为 /contents/generations/tasks 返回 404。

+

根因:https://ai.skg.com/doubao 这个 SKG 豆包网关的真实视频入口是 /api/v3/contents/generations/tasks,不是火山方舟直连 base 下使用的 /contents/generations/tasks

+

改动:后端默认路径识别 ai.skg.com/doubao 并自动使用 /api/v3/contents/generations/tasks/api/v3/contents/generations/tasks/{id}/api/v3/contents/generations/tasks/{id}/content;本机 api/.envapi/.env.example 同步更新。

+

影响:api/main.pyapi/.envapi/.env.exampledocs/source-analysis.html

+
+

2026-05-14 · 产品融合改为内置角色 + 产品 + 描述生成

@@ -1076,7 +1089,7 @@ SubjectAsset {

问题:用户提供 https://ai.skg.com/doubao 作为视频模型网关;该网关应按 Seedance / 方舟内容生成任务格式提交,而不能误走普通 multipart 上传。

-

改动:video_uses_ark() 现在同时识别火山方舟域名和 ai.skg.com/doubao,统一使用 content JSON:文本 prompt、首帧、尾帧和产品参考图作为不同 role 传入,再按 /contents/generations/tasks/{id} 轮询。api/.env.example 增加 SKG 豆包视频网关配置示例;生视频轮询上限改为 VIDEO_POLL_TIMEOUT_SECONDS,默认 900 秒,避免慢任务过早失败。

+

改动:video_uses_ark() 现在同时识别火山方舟域名和 ai.skg.com/doubao,统一使用 content JSON:文本 prompt、首帧、尾帧和产品参考图作为不同 role 传入。火山方舟直连按 /contents/generations/tasks/{id} 轮询;SKG 豆包网关按 /api/v3/contents/generations/tasks/{id} 轮询。api/.env.example 增加 SKG 豆包视频网关配置示例;生视频轮询上限改为 VIDEO_POLL_TIMEOUT_SECONDS,默认 900 秒,避免慢任务过早失败。

影响:api/main.pyapi/.env.exampledocs/source-analysis.html。本机 api/.env 已配置 VIDEO_API_BASE_URL=https://ai.skg.com/doubao 和视频专用 key。

@@ -1696,7 +1709,7 @@ SubjectAsset {

问题:用户提供火山方舟 https://ark.cn-beijing.volces.com/api/v3 作为生视频通道;这个通道不是 Poe 的 /videos 形态,而是内容生成异步任务。

-

改动:后端识别 Ark base 后,提交改为 POST /contents/generations/tasks,请求体使用 content 数组:文本 prompt + 首帧 image_url data URL;轮询改为 GET /contents/generations/tasks/{id},成功后读取 content.video_url 下载 MP4。本机默认 Seedance 模型改为 Ark 可见的 doubao-seedance-2-0-fast-260128

+

改动:后端识别 Ark base 后,提交改为内容生成任务接口,火山方舟直连使用 POST /contents/generations/tasks,SKG 豆包网关使用 POST /api/v3/contents/generations/tasks。请求体使用 content 数组:文本 prompt + 首帧 image_url data URL;轮询对应的 {id} 任务地址,成功后读取 content.video_url 下载 MP4。本机默认 Seedance 模型改为 Ark 可见的 doubao-seedance-2-0-fast-260128

影响:api/main.pyapi/.env.exampledocs/source-analysis.html。本机 api/.env 需要把 VIDEO_API_BASE_URL/VIDEO_API_KEY/VIDEO_CREATE_PATHS/VIDEO_STATUS_PATH 指向 Ark。