auto-save 2026-05-14 13:32 (~4)
This commit is contained in:
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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=
|
||||
|
||||
31
api/main.py
31
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")))
|
||||
|
||||
|
||||
@@ -919,6 +919,19 @@ SubjectAsset {
|
||||
<h2>变更记录</h2>
|
||||
<p>这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。</p>
|
||||
<div class="changelog">
|
||||
<article class="change">
|
||||
<header>
|
||||
<h3>2026-05-14 · 修正 SKG 豆包视频网关路径</h3>
|
||||
<span class="tag orange">Video Gen</span>
|
||||
<span class="tag blue">Seedance</span>
|
||||
</header>
|
||||
<div class="body">
|
||||
<p><strong>问题:</strong>产品融合视频能进入队列,但后台任务 5% 后失败,错误为 <code>/contents/generations/tasks</code> 返回 404。</p>
|
||||
<p><strong>根因:</strong><code>https://ai.skg.com/doubao</code> 这个 SKG 豆包网关的真实视频入口是 <code>/api/v3/contents/generations/tasks</code>,不是火山方舟直连 base 下使用的 <code>/contents/generations/tasks</code>。</p>
|
||||
<p><strong>改动:</strong>后端默认路径识别 <code>ai.skg.com/doubao</code> 并自动使用 <code>/api/v3/contents/generations/tasks</code>、<code>/api/v3/contents/generations/tasks/{id}</code>、<code>/api/v3/contents/generations/tasks/{id}/content</code>;本机 <code>api/.env</code> 和 <code>api/.env.example</code> 同步更新。</p>
|
||||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env</code>、<code>api/.env.example</code>、<code>docs/source-analysis.html</code>。</p>
|
||||
</div>
|
||||
</article>
|
||||
<article class="change">
|
||||
<header>
|
||||
<h3>2026-05-14 · 产品融合改为内置角色 + 产品 + 描述生成</h3>
|
||||
@@ -1076,7 +1089,7 @@ SubjectAsset {
|
||||
</header>
|
||||
<div class="body">
|
||||
<p><strong>问题:</strong>用户提供 <code>https://ai.skg.com/doubao</code> 作为视频模型网关;该网关应按 Seedance / 方舟内容生成任务格式提交,而不能误走普通 multipart 上传。</p>
|
||||
<p><strong>改动:</strong><code>video_uses_ark()</code> 现在同时识别火山方舟域名和 <code>ai.skg.com/doubao</code>,统一使用 <code>content</code> JSON:文本 prompt、首帧、尾帧和产品参考图作为不同 role 传入,再按 <code>/contents/generations/tasks/{id}</code> 轮询。<code>api/.env.example</code> 增加 SKG 豆包视频网关配置示例;生视频轮询上限改为 <code>VIDEO_POLL_TIMEOUT_SECONDS</code>,默认 900 秒,避免慢任务过早失败。</p>
|
||||
<p><strong>改动:</strong><code>video_uses_ark()</code> 现在同时识别火山方舟域名和 <code>ai.skg.com/doubao</code>,统一使用 <code>content</code> JSON:文本 prompt、首帧、尾帧和产品参考图作为不同 role 传入。火山方舟直连按 <code>/contents/generations/tasks/{id}</code> 轮询;SKG 豆包网关按 <code>/api/v3/contents/generations/tasks/{id}</code> 轮询。<code>api/.env.example</code> 增加 SKG 豆包视频网关配置示例;生视频轮询上限改为 <code>VIDEO_POLL_TIMEOUT_SECONDS</code>,默认 900 秒,避免慢任务过早失败。</p>
|
||||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env.example</code>、<code>docs/source-analysis.html</code>。本机 <code>api/.env</code> 已配置 <code>VIDEO_API_BASE_URL=https://ai.skg.com/doubao</code> 和视频专用 key。</p>
|
||||
</div>
|
||||
</article>
|
||||
@@ -1696,7 +1709,7 @@ SubjectAsset {
|
||||
</header>
|
||||
<div class="body">
|
||||
<p><strong>问题:</strong>用户提供火山方舟 <code>https://ark.cn-beijing.volces.com/api/v3</code> 作为生视频通道;这个通道不是 Poe 的 <code>/videos</code> 形态,而是内容生成异步任务。</p>
|
||||
<p><strong>改动:</strong>后端识别 Ark base 后,提交改为 <code>POST /contents/generations/tasks</code>,请求体使用 <code>content</code> 数组:文本 prompt + 首帧 <code>image_url</code> data URL;轮询改为 <code>GET /contents/generations/tasks/{id}</code>,成功后读取 <code>content.video_url</code> 下载 MP4。本机默认 Seedance 模型改为 Ark 可见的 <code>doubao-seedance-2-0-fast-260128</code>。</p>
|
||||
<p><strong>改动:</strong>后端识别 Ark base 后,提交改为内容生成任务接口,火山方舟直连使用 <code>POST /contents/generations/tasks</code>,SKG 豆包网关使用 <code>POST /api/v3/contents/generations/tasks</code>。请求体使用 <code>content</code> 数组:文本 prompt + 首帧 <code>image_url</code> data URL;轮询对应的 <code>{id}</code> 任务地址,成功后读取 <code>content.video_url</code> 下载 MP4。本机默认 Seedance 模型改为 Ark 可见的 <code>doubao-seedance-2-0-fast-260128</code>。</p>
|
||||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env.example</code>、<code>docs/source-analysis.html</code>。本机 <code>api/.env</code> 需要把 <code>VIDEO_API_BASE_URL</code>/<code>VIDEO_API_KEY</code>/<code>VIDEO_CREATE_PATHS</code>/<code>VIDEO_STATUS_PATH</code> 指向 Ark。</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
Reference in New Issue
Block a user