2448 lines
193 KiB
HTML
2448 lines
193 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>SKG TK 二创验证 · 源码解析与协作地图</title>
|
||
<style>
|
||
:root {
|
||
--bg: #f8fafc;
|
||
--panel: #ffffff;
|
||
--panel-soft: #f1f5f9;
|
||
--ink: #0f172a;
|
||
--muted: #64748b;
|
||
--line: #dbe3ed;
|
||
--blue: #2563eb;
|
||
--violet: #7c3aed;
|
||
--orange: #ea580c;
|
||
--green: #059669;
|
||
--rose: #e11d48;
|
||
--code: #111827;
|
||
--shadow: 0 18px 50px rgba(15, 23, 42, 0.08);
|
||
}
|
||
|
||
* { box-sizing: border-box; }
|
||
html { scroll-behavior: smooth; }
|
||
body {
|
||
margin: 0;
|
||
color: var(--ink);
|
||
background:
|
||
linear-gradient(180deg, rgba(37, 99, 235, 0.06), transparent 340px),
|
||
var(--bg);
|
||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
a { color: inherit; }
|
||
code, pre {
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
|
||
}
|
||
|
||
.shell {
|
||
display: grid;
|
||
grid-template-columns: 280px minmax(0, 1fr);
|
||
min-height: 100vh;
|
||
}
|
||
|
||
aside {
|
||
position: sticky;
|
||
top: 0;
|
||
height: 100vh;
|
||
overflow: auto;
|
||
padding: 24px 18px;
|
||
border-right: 1px solid var(--line);
|
||
background: rgba(255, 255, 255, 0.82);
|
||
backdrop-filter: blur(16px);
|
||
}
|
||
|
||
main {
|
||
width: min(1180px, calc(100vw - 320px));
|
||
padding: 34px 40px 72px;
|
||
}
|
||
|
||
.brand {
|
||
margin-bottom: 18px;
|
||
padding-bottom: 18px;
|
||
border-bottom: 1px solid var(--line);
|
||
}
|
||
.brand h1 {
|
||
margin: 0 0 8px;
|
||
font-size: 18px;
|
||
line-height: 1.25;
|
||
letter-spacing: 0;
|
||
}
|
||
.brand p {
|
||
margin: 0;
|
||
color: var(--muted);
|
||
font-size: 13px;
|
||
}
|
||
|
||
nav a {
|
||
display: block;
|
||
padding: 8px 10px;
|
||
margin: 2px 0;
|
||
border-radius: 8px;
|
||
color: #334155;
|
||
text-decoration: none;
|
||
font-size: 13px;
|
||
}
|
||
nav a:hover,
|
||
nav a:focus {
|
||
color: var(--blue);
|
||
background: #eff6ff;
|
||
outline: none;
|
||
}
|
||
|
||
.toolbar {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1fr) auto;
|
||
gap: 12px;
|
||
margin-top: 18px;
|
||
}
|
||
.search {
|
||
width: 100%;
|
||
min-height: 42px;
|
||
padding: 0 14px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 10px;
|
||
background: #fff;
|
||
color: var(--ink);
|
||
font-size: 14px;
|
||
outline: none;
|
||
}
|
||
.search:focus {
|
||
border-color: rgba(37, 99, 235, 0.55);
|
||
box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.12);
|
||
}
|
||
.button {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 42px;
|
||
padding: 0 14px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 10px;
|
||
background: #fff;
|
||
color: #334155;
|
||
font-size: 13px;
|
||
cursor: pointer;
|
||
}
|
||
.button:hover { border-color: #94a3b8; color: var(--ink); }
|
||
|
||
.hero {
|
||
padding: 28px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 18px;
|
||
background: var(--panel);
|
||
box-shadow: var(--shadow);
|
||
}
|
||
.hero .eyebrow {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-bottom: 12px;
|
||
color: var(--blue);
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
}
|
||
.hero h2 {
|
||
margin: 0 0 12px;
|
||
max-width: 980px;
|
||
font-size: clamp(30px, 5vw, 54px);
|
||
line-height: 1.04;
|
||
letter-spacing: 0;
|
||
}
|
||
.hero p {
|
||
max-width: 880px;
|
||
margin: 0;
|
||
color: #475569;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.meta-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||
gap: 12px;
|
||
margin-top: 18px;
|
||
}
|
||
.meta {
|
||
padding: 13px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 12px;
|
||
background: #f8fafc;
|
||
}
|
||
.meta b {
|
||
display: block;
|
||
margin-bottom: 4px;
|
||
font-size: 12px;
|
||
color: #334155;
|
||
}
|
||
.meta span {
|
||
color: var(--muted);
|
||
font-size: 12px;
|
||
word-break: break-word;
|
||
}
|
||
|
||
section {
|
||
margin-top: 28px;
|
||
padding: 24px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 18px;
|
||
background: rgba(255, 255, 255, 0.86);
|
||
box-shadow: 0 10px 35px rgba(15, 23, 42, 0.045);
|
||
}
|
||
section h2 {
|
||
margin: 0 0 12px;
|
||
font-size: 24px;
|
||
letter-spacing: 0;
|
||
}
|
||
section > p {
|
||
margin-top: 0;
|
||
color: #475569;
|
||
}
|
||
|
||
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
|
||
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
|
||
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
|
||
|
||
.card {
|
||
padding: 16px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 14px;
|
||
background: #fff;
|
||
}
|
||
.card h3 {
|
||
margin: 0 0 8px;
|
||
font-size: 16px;
|
||
}
|
||
.card p,
|
||
.card li {
|
||
color: #475569;
|
||
font-size: 14px;
|
||
}
|
||
.card p:last-child { margin-bottom: 0; }
|
||
|
||
.tag {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
min-height: 24px;
|
||
padding: 0 8px;
|
||
border-radius: 999px;
|
||
background: #e2e8f0;
|
||
color: #334155;
|
||
font-size: 12px;
|
||
font-weight: 650;
|
||
}
|
||
.tag.blue { background: #dbeafe; color: #1d4ed8; }
|
||
.tag.violet { background: #ede9fe; color: #6d28d9; }
|
||
.tag.orange { background: #ffedd5; color: #c2410c; }
|
||
.tag.green { background: #d1fae5; color: #047857; }
|
||
.tag.rose { background: #ffe4e6; color: #be123c; }
|
||
.tag.gray { background: #e2e8f0; color: #475569; }
|
||
|
||
.pipeline {
|
||
display: grid;
|
||
grid-template-columns: repeat(8, minmax(120px, 1fr));
|
||
gap: 10px;
|
||
overflow-x: auto;
|
||
padding-bottom: 4px;
|
||
}
|
||
.step {
|
||
min-width: 138px;
|
||
padding: 14px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 14px;
|
||
background: #fff;
|
||
}
|
||
.step .num {
|
||
width: 26px;
|
||
height: 26px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 10px;
|
||
border-radius: 8px;
|
||
background: #eff6ff;
|
||
color: var(--blue);
|
||
font-weight: 800;
|
||
font-size: 12px;
|
||
}
|
||
.step h3 {
|
||
margin: 0 0 6px;
|
||
font-size: 14px;
|
||
}
|
||
.step p {
|
||
margin: 0;
|
||
color: #64748b;
|
||
font-size: 12px;
|
||
line-height: 1.45;
|
||
}
|
||
|
||
table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
overflow: hidden;
|
||
border: 1px solid var(--line);
|
||
border-radius: 12px;
|
||
background: #fff;
|
||
}
|
||
th,
|
||
td {
|
||
padding: 11px 12px;
|
||
border-bottom: 1px solid var(--line);
|
||
text-align: left;
|
||
vertical-align: top;
|
||
font-size: 13px;
|
||
}
|
||
th {
|
||
background: #f8fafc;
|
||
color: #334155;
|
||
font-size: 12px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.06em;
|
||
}
|
||
tr:last-child td { border-bottom: 0; }
|
||
td code {
|
||
color: #0f172a;
|
||
background: #f1f5f9;
|
||
border: 1px solid #e2e8f0;
|
||
border-radius: 6px;
|
||
padding: 2px 5px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
pre {
|
||
margin: 12px 0 0;
|
||
padding: 14px;
|
||
overflow: auto;
|
||
border-radius: 12px;
|
||
background: var(--code);
|
||
color: #e5e7eb;
|
||
font-size: 12px;
|
||
line-height: 1.55;
|
||
}
|
||
|
||
.callout {
|
||
padding: 14px 16px;
|
||
border-radius: 14px;
|
||
border: 1px solid #bfdbfe;
|
||
background: #eff6ff;
|
||
color: #1e3a8a;
|
||
}
|
||
.callout.warn {
|
||
border-color: #fed7aa;
|
||
background: #fff7ed;
|
||
color: #9a3412;
|
||
}
|
||
.callout.good {
|
||
border-color: #bbf7d0;
|
||
background: #f0fdf4;
|
||
color: #166534;
|
||
}
|
||
.callout p { margin: 0; }
|
||
|
||
.flow {
|
||
display: grid;
|
||
gap: 10px;
|
||
}
|
||
.flow-row {
|
||
display: grid;
|
||
grid-template-columns: 170px minmax(0, 1fr) minmax(0, 1fr);
|
||
gap: 10px;
|
||
align-items: stretch;
|
||
}
|
||
.flow-row > div {
|
||
padding: 12px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 12px;
|
||
background: #fff;
|
||
font-size: 13px;
|
||
}
|
||
.flow-row strong { display: block; margin-bottom: 4px; }
|
||
.flow-row span { color: var(--muted); }
|
||
|
||
.todo {
|
||
display: grid;
|
||
gap: 10px;
|
||
counter-reset: todo;
|
||
}
|
||
.todo-item {
|
||
position: relative;
|
||
padding: 14px 14px 14px 46px;
|
||
border: 1px solid var(--line);
|
||
border-radius: 14px;
|
||
background: #fff;
|
||
}
|
||
.todo-item::before {
|
||
counter-increment: todo;
|
||
content: counter(todo);
|
||
position: absolute;
|
||
left: 14px;
|
||
top: 14px;
|
||
width: 22px;
|
||
height: 22px;
|
||
display: grid;
|
||
place-items: center;
|
||
border-radius: 7px;
|
||
background: #f1f5f9;
|
||
color: #475569;
|
||
font-size: 12px;
|
||
font-weight: 800;
|
||
}
|
||
.todo-item h3 { margin: 0 0 4px; font-size: 14px; }
|
||
.todo-item p { margin: 0; color: var(--muted); font-size: 13px; }
|
||
|
||
.changelog {
|
||
display: grid;
|
||
gap: 12px;
|
||
}
|
||
.change {
|
||
border: 1px solid var(--line);
|
||
border-radius: 14px;
|
||
background: #fff;
|
||
overflow: hidden;
|
||
}
|
||
.change header {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 10px;
|
||
padding: 12px 14px;
|
||
border-bottom: 1px solid var(--line);
|
||
background: #f8fafc;
|
||
}
|
||
.change h3 { margin: 0; font-size: 14px; }
|
||
.change .body { padding: 14px; }
|
||
.change .body p { margin: 0 0 8px; color: #475569; font-size: 13px; }
|
||
.change .body p:last-child { margin-bottom: 0; }
|
||
|
||
.hidden-by-search { display: none !important; }
|
||
|
||
@media (max-width: 980px) {
|
||
.shell { display: block; }
|
||
aside {
|
||
position: static;
|
||
height: auto;
|
||
border-right: 0;
|
||
border-bottom: 1px solid var(--line);
|
||
}
|
||
main {
|
||
width: 100%;
|
||
padding: 24px 18px 56px;
|
||
}
|
||
.meta-grid,
|
||
.grid-2,
|
||
.grid-3,
|
||
.grid-4,
|
||
.flow-row {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
|
||
@media print {
|
||
aside, .toolbar { display: none; }
|
||
.shell { display: block; }
|
||
main { width: 100%; padding: 0; }
|
||
section, .hero { box-shadow: none; break-inside: avoid; }
|
||
body { background: #fff; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="shell">
|
||
<aside>
|
||
<div class="brand">
|
||
<h1>SKG TK 二创验证</h1>
|
||
<p>源码解析与协作地图。用于把产品需求准确映射到代码位置。</p>
|
||
</div>
|
||
<nav aria-label="页面目录">
|
||
<a href="#purpose">为什么有这页</a>
|
||
<a href="#how-to-use">怎么用它描述需求</a>
|
||
<a href="#runtime">运行与入口</a>
|
||
<a href="#pipeline">业务管线</a>
|
||
<a href="#source-map">源码结构地图</a>
|
||
<a href="#ui-map">界面区域到源码</a>
|
||
<a href="#data-model">数据模型</a>
|
||
<a href="#api-map">接口地图</a>
|
||
<a href="#node-contract">节点职责边界</a>
|
||
<a href="#current-state">当前已通与阻塞</a>
|
||
<a href="#request-language">需求描述模板</a>
|
||
<a href="#change-log">变更记录</a>
|
||
<a href="#update-rule">更新规则</a>
|
||
</nav>
|
||
<div class="toolbar">
|
||
<input id="search" class="search" type="search" placeholder="搜索:节点 / 文件 / 接口 / 功能" />
|
||
<button class="button" type="button" onclick="window.print()">打印</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<main>
|
||
<div class="hero" id="purpose" data-search>
|
||
<div class="eyebrow">Source Analysis · 2026-05-13</div>
|
||
<h2>这个页面是产品协作地图,不是应用功能页。</h2>
|
||
<p>
|
||
它把“你看到的界面、你想改的功能、实际要动的源码、可能影响的数据和接口”放在同一个地方。
|
||
后续描述需求时,可以直接说“改素材输入列 / 音频解析工作表 / 某个接口行为”,这样改动范围会更准,也更容易追踪每次变更带来的影响。
|
||
</p>
|
||
<div class="meta-grid">
|
||
<div class="meta"><b>项目路径</b><span>/Users/kangwan/Projects/business/20260512-20260512-skg-tk-二创验证</span></div>
|
||
<div class="meta"><b>前端</b><span>Next.js 16 · 端口 4290 · web/app/page.tsx</span></div>
|
||
<div class="meta"><b>后端</b><span>FastAPI · 端口 4291 · api/main.py</span></div>
|
||
<div class="meta"><b>本文档位置</b><span>docs/source-analysis.html · 独立文件,不接入应用</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<section id="how-to-use" data-search>
|
||
<h2>怎么用它描述需求</h2>
|
||
<div class="grid-3">
|
||
<div class="card">
|
||
<h3>1. 先说你在改哪个产品区</h3>
|
||
<p>例如“素材输入列”、“音频解析工作表”、“逐句时间轴 / 讲话人分析 / 背景音分析”。不要只说“这里乱”,要指向页面里的功能区。</p>
|
||
</div>
|
||
<div class="card">
|
||
<h3>2. 再说这个区应该承担什么职责</h3>
|
||
<p>例如“Vision 只给候选元素,用户必须能编辑、删除、重新提取”,这会直接落到 <code>FrameLightbox</code> 和元素接口。</p>
|
||
</div>
|
||
<div class="card">
|
||
<h3>3. 最后说不希望发生什么</h3>
|
||
<p>例如“点击元素不要跳页面”、“不要直接进入编排打断思路”、“不要把参考视频复刻成一样的东西”。这能约束交互和文案。</p>
|
||
</div>
|
||
</div>
|
||
<div class="callout good" style="margin-top:14px">
|
||
<p>建议表达格式:我要改「功能区」;当前问题是「行为」;正确职责是「业务目的」;不要影响「已有流程」。</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="runtime" data-search>
|
||
<h2>运行与入口</h2>
|
||
<table>
|
||
<thead>
|
||
<tr><th>项目</th><th>命令 / 入口</th><th>说明</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>本地后台启动</td>
|
||
<td><code>./scripts/start-dev-background.sh</code></td>
|
||
<td>不弹出 macOS Terminal 窗口;自动检查 4290 / 4291,缺哪个启动哪个,日志写入 <code>.logs/</code>,PID 写入 <code>.pids/</code>。</td>
|
||
</tr>
|
||
<tr>
|
||
<td>本地后台停止</td>
|
||
<td><code>./scripts/stop-dev-background.sh</code></td>
|
||
<td>按 <code>.pids/</code> 里的 PID 停止后台前端 / 后端进程。</td>
|
||
</tr>
|
||
<tr>
|
||
<td>生产站点</td>
|
||
<td><code>https://marketing.skg.com</code></td>
|
||
<td>公司域名已解析到 VPS <code>76.13.31.179</code>。线上由既有 Coolify / Traefik 负责 HTTPS 入口,项目 <code>web</code> 容器用 Nginx 承载静态前端;<code>/login/</code>、<code>/_next/</code>、<code>/assets/</code>、<code>/skg-logo-black.svg</code>、<code>/oasis-source/</code> 为公开登录页资源,未登录访问工作台跳转 <code>/login/</code>,<code>/api/</code> 通过 <code>auth_request</code> 校验 FastAPI 会话 Cookie 后再反代。</td>
|
||
</tr>
|
||
<tr>
|
||
<td>生产部署</td>
|
||
<td><code>docker compose -f docker-compose.prod.yml --env-file deploy/.env.production up -d --build</code></td>
|
||
<td>服务器目录为 <code>/opt/skg-marketing-studio</code>;后端任务文件挂载到 <code>./data/jobs</code>,真实 Key 只放服务器 <code>deploy/.env.production</code>。</td>
|
||
</tr>
|
||
<tr>
|
||
<td>前端开发服务</td>
|
||
<td><code>cd web && npm run dev</code></td>
|
||
<td>Next.js App Router,主页面是 <code>web/app/page.tsx</code>,默认端口 4290。</td>
|
||
</tr>
|
||
<tr>
|
||
<td>后端开发服务</td>
|
||
<td><code>cd api && source .venv/bin/activate && uvicorn main:app --host 127.0.0.1 --port 4291</code></td>
|
||
<td>FastAPI,所有任务状态、视频、关键帧、清洗、元素、分镜保存都在 <code>api/main.py</code>。长下载 / 抽帧 / 音频处理期间不要带 <code>--reload</code>,否则 reload 会等待后台任务结束并让新请求卡住。</td>
|
||
</tr>
|
||
<tr>
|
||
<td>测试页面</td>
|
||
<td><code>http://localhost:4290/?job=c6767f3a166b</code></td>
|
||
<td>URL 里可放多个 job id:<code>?job=id1,id2,id3</code>,前端会恢复多个任务并激活最后一个。</td>
|
||
</tr>
|
||
<tr>
|
||
<td>源码解析页</td>
|
||
<td><code>open docs/source-analysis.html</code></td>
|
||
<td>独立静态 HTML,不被 Next 构建、不影响产品工作台。</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<section id="pipeline" data-search>
|
||
<h2>业务管线</h2>
|
||
<p>当前产品方向已收窄为“信息流广告快速复刻第一步”:主界面左侧是素材输入列,右侧是音频解析工作表。用户粘贴 TK 链接或上传视频后点击“开始”,系统自动下载源视频;下载完成后优先提取原音频文案/字幕,并分析讲话人、语速节奏、背景音乐/环境声/音效。抽帧、分镜规划、产品融入、元素 6 视图和视频合成暂作为后续能力保留,不在当前开始流程里自动触发。</p>
|
||
<div class="pipeline">
|
||
<div class="step"><div class="num">1</div><h3>导入素材</h3><p>粘贴 TK / 信息流视频链接或上传本地视频;“开始”只把任务放入第一步队列。</p></div>
|
||
<div class="step"><div class="num">2</div><h3>下载源视频</h3><p>后端用 yt-dlp 或本地上传文件落 <code>source.mp4</code>,记录时长、尺寸和视频只读地址。</p></div>
|
||
<div class="step"><div class="num">3</div><h3>解析音频</h3><p>从 <code>source.mp4</code> 提取 <code>audio.wav</code>,ASR 提取原文案,翻译成中文,并写入逐句时间轴。</p></div>
|
||
<div class="step"><div class="num">4</div><h3>声音分析</h3><p>用音频模型分析讲话人、口播节奏、停顿、背景音乐/环境声/音效;不默认改写配音或生成视频。</p></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="source-map" data-search>
|
||
<h2>源码结构地图</h2>
|
||
<div class="grid-2">
|
||
<div class="card">
|
||
<h3>前端核心</h3>
|
||
<table>
|
||
<tbody>
|
||
<tr><td><code>web/next.config.mjs</code></td><td>Next.js 构建配置:静态导出、图片不走优化、禁用开发环境左下角 Next Dev Indicator,并移除 Next 16 已不支持的 <code>eslint</code> 顶层配置,避免本地 dev 出现配置 Issue 提示。</td></tr>
|
||
<tr><td><code>web/app/globals.css</code></td><td>全局主题变量、登录页视觉样式、ReactFlow 样式引用,以及本地开发态 <code>nextjs-portal</code> 遮挡隐藏规则。</td></tr>
|
||
<tr><td><code>web/app/page.tsx</code></td><td>产品工作台主状态:jobs、activeJobId、生成任务状态;主渲染为全屏素材输入列 + 音频解析工作表;“开始”编排状态只负责在下载完成后自动触发 <code>triggerTranscribe</code>,不再默认触发抽帧、Vision 扫描或分镜初稿保存;底部吸附音频条不再从主界面渲染。</td></tr>
|
||
<tr><td><code>web/components/ad-recreation-board.tsx</code></td><td>信息流广告音频解析工作表:左侧素材输入;右侧展示视频下载状态、原文案/中文翻译、讲话人/节奏/背景音分析和逐句时间轴。旧分镜卡、抽帧控制和视频生成组件仍保留在文件里,但当前主路径不渲染。</td></tr>
|
||
<tr><td><code>web/app/login/page.tsx</code></td><td>生产登录页:访问账号/访问密钥表单、保持登录、错误/成功状态;当前只在原版 Digital Oasis 动态背景上叠加一个组合登录框,桌面端左侧是动态角色,右侧是图标化登录表单;面板左上角展示官网 SKG 字标和中文“营销内容工作台”系统标识。</td></tr>
|
||
<tr><td><code>web/app/login/layout.tsx</code></td><td>登录路由专属 layout:覆盖全站默认网页标题和描述为空,避免 <code>/login</code> 继承工作台 metadata 后在页面源码里继续出现登录界面文字以外的文案。</td></tr>
|
||
<tr><td><code>web/components/login/oasis-canvas.tsx</code></td><td>登录页全屏动态视觉层:用 iframe 直接承载下载包 <code>web/public/oasis-source/index.html</code> 的原 WebGPU / Three.js 草场源码;父级登录页只覆盖自己的文案和表单,并在捕获阶段把全局鼠标坐标同时用原生事件和 <code>postMessage</code> 转发给 iframe,避免登录面板或输入框遮挡时草地失去鼠标响应。</td></tr>
|
||
<tr><td><code>web/public/oasis-source/index.html</code></td><td>从下载包 <code>remix-3d-website-the-digital-o</code> 复制来的原始视觉源码。嵌入登录页时会隐藏 demo 站自己的导航、文字和设置面板,保留原多段滚动背景变化、WebGPU 草场、景深、风动和鼠标交互源码;末端阶段保留,只禁用原 footer 出现时把 canvas 上移的逻辑,避免底部露黑边。</td></tr>
|
||
<tr><td><code>web/public/skg-logo-black.svg</code></td><td>从官网 <code>https://cn.skg.com/logo-black.svg</code> 获取的 SKG 官方黑色 SVG 字标;登录页通过 CSS 反相成白色玻璃标识使用。</td></tr>
|
||
<tr><td><code>web/components/login/animated-login-characters.tsx</code></td><td>登录页四个几何动态角色组件:当前嵌入登录框顶部,去掉独立网格背景,保留鼠标眼神跟随、输入、显示密码、错误和成功状态反馈。</td></tr>
|
||
<tr><td><code>web/components/nodes/index.tsx</code></td><td>旧 DAG 节点和深度素材面板定义仍保留,当前主界面不再把这些节点挂到画布上。</td></tr>
|
||
<tr><td><code>web/components/audio-strip.tsx</code></td><td>旧底部吸附音频条组件:当前主界面不再渲染,音频文案、翻译、讲话人、节奏和背景音统一在右侧音频解析工作表里查看。</td></tr>
|
||
<tr><td><code>web/components/lightbox.tsx</code></td><td>关键帧素材准备面板:清洗、统一主体候选、参考帧网格、六张主体重绘图、每帧去主体场景图、纵向 6 行产品融合镜头工作表和审核。</td></tr>
|
||
<tr><td><code>web/components/product-library-picker.tsx</code></td><td>SKG 内置白底产品图库选择器:搜索、品类筛选、预览尺寸,并把库内图片复制为当前 job 的 <code>asset</code>。</td></tr>
|
||
<tr><td><code>web/components/storyboard-bar.tsx</code></td><td>顶部分镜编排条:展示选入编排的关键帧,并作为唯一分镜导航。</td></tr>
|
||
<tr><td><code>web/components/storyboard-workbench.tsx</code></td><td>顶部分镜编排条下方的明细区:4 图槽、改造目标、时长、自动保存。</td></tr>
|
||
<tr><td><code>web/lib/api.ts</code></td><td>前端类型和 API client,是前后端数据契约镜像。</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="card">
|
||
<h3>后端核心</h3>
|
||
<table>
|
||
<tbody>
|
||
<tr><td><code>api/main.py</code></td><td>FastAPI 单文件后端:登录会话、状态模型、任务恢复、下载、抽帧、Vision、清洗、元素、分镜、原音频转写/翻译、声音与背景音分析、后续口播改写/TTS、文件返回。</td></tr>
|
||
<tr><td><code>api/product_library/skg-products</code></td><td>内置 SKG 白底产品图库:<code>manifest.json</code> 记录从桌面产品图筛出的 gallery 白底图和桌面 4 张产品角度图,<code>images/</code> 存 45 张参考图。</td></tr>
|
||
<tr><td><code>jobs/<jobId>/state.json</code></td><td>运行时状态文件,不在源码列表里,但刷新恢复依赖它。</td></tr>
|
||
<tr><td><code>jobs/<jobId>/audio.wav</code></td><td>拆轨得到的原始音频,底部 Audio Strip 会通过只读接口拉取并在浏览器里解码成波形峰值。</td></tr>
|
||
<tr><td><code>jobs/<jobId>/frames</code></td><td>关键帧 jpg。注意 frame.index 是稳定 ID,不等于数组下标。</td></tr>
|
||
<tr><td><code>jobs/<jobId>/cleaned</code></td><td>清洗后待应用图片。</td></tr>
|
||
<tr><td><code>jobs/<jobId>/elements</code></td><td>元素提取图,多版本命名:<code>idx_elementId_cutoutId.jpg</code>。</td></tr>
|
||
<tr><td><code>jobs/<jobId>/gen</code></td><td>关键帧生图结果。</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<pre>前端主链路:
|
||
web/app/page.tsx
|
||
-> 音频解析工作表:web/components/ad-recreation-board.tsx
|
||
-> 开始:创建/激活 job → 下载完成后自动触发音频处理
|
||
-> 左侧素材输入列 + 右侧原文案/中文翻译/声音背景音分析/逐句时间轴
|
||
-> 底部音频条:不再渲染,音频结果集中到右侧工作表
|
||
-> 旧节点/深度素材面板:web/components/nodes/index.tsx、web/components/lightbox.tsx、web/components/storyboard-workbench.tsx(底层保留,当前不作为主入口)
|
||
-> API 契约:web/lib/api.ts
|
||
|
||
后端主链路:
|
||
api/main.py
|
||
-> Job / KeyFrame / KeyElement / StoryboardScene / AudioScript
|
||
-> 下载 / 上传 / 音频提取 / ASR / 翻译 / 声音背景音分析 / 抽帧 / Vision / 清洗 / 元素提取 / 分镜保存 / 后续音频改写与 MiniMax 英文配音
|
||
-> jobs/<jobId>/state.json + 图片文件落盘</pre>
|
||
</section>
|
||
|
||
<section id="ui-map" data-search>
|
||
<h2>界面区域到源码</h2>
|
||
<div class="flow">
|
||
<div class="flow-row">
|
||
<div><strong>你看到的区域</strong><span>信息流广告音频解析工作表</span></div>
|
||
<div><strong>主要源码</strong><span><code>AdRecreationBoard</code> in <code>web/components/ad-recreation-board.tsx</code>;状态、轮询和接口回写仍在 <code>web/app/page.tsx</code>。</span></div>
|
||
<div><strong>适合怎么描述</strong><span>“素材输入列、开始后的自动下载/音频解析、原文案/翻译/声音背景音结果怎么展示”。</span></div>
|
||
</div>
|
||
<div class="flow-row">
|
||
<div><strong>你看到的区域</strong><span>音频解析结果表</span></div>
|
||
<div><strong>主要源码</strong><span><code>AudioIntakePanel</code> / <code>AudioIntakeStatus</code> in <code>web/components/ad-recreation-board.tsx</code>;复用 <code>triggerTranscribe</code> 和 <code>AudioScript</code>。</span></div>
|
||
<div><strong>适合怎么描述</strong><span>“原始文案、中文翻译、讲话人、节奏、背景音、逐句时间轴还需要哪些字段”。</span></div>
|
||
</div>
|
||
<div class="flow-row">
|
||
<div><strong>你看到的区域</strong><span>旧深度素材面板(当前不作为主路径)</span></div>
|
||
<div><strong>主要源码</strong><span><code>FrameLightbox</code>;按“原图/清洗、主体资产、首尾帧、产品融合、审核”五个页签组织;左侧只放主图/框选画布,但主体资产页左侧改为全部已清洗/已选参考帧网格,首尾帧页左侧显示全部关键帧并可勾选人物/机位参考。主体识别页会显示透明骨架人目标和 Vision 验收分数。清洗页右侧支持一键清洗未处理帧、单张替换清洗版和一键替换全部待应用清洗版;批量替换顺序调用 <code>applyCleanedFrame</code>,不新增后端接口。产品融合页左侧是纵向 6 行镜头工作表:顶部选择 5 个内置透明骨架人角色之一,并常驻显示桌面四张真实 SKG 产品角度图;每行只显示已预填场景/产品使用/享受描述、秒数、生成按钮和可横向追加的视频历史结果,产品图和结果视频都支持鼠标停留放大预览。描述词内置 36 条镜头语言模板,按“建立出场、产品入画、佩戴贴合、使用感受、生活延展、收尾记忆”排列,并且会按角色自动改写场景气质、使用动作和享受状态。每行还内置角色参考图调度:例如正面/半身用于出场,侧面/背部特写用于佩戴贴合,半身/背部特写用于收尾产品记忆点。点击“换一组”只刷新 6 行描述词。四张桌面 SKG 产品图是真实产品真源,所选角色 7 张参考图是人物身份参考,生成时分别通过 <code>copyProductLibraryAsset</code> 与 <code>copyCharacterLibraryAssets</code> 自动写入当前 job;视频 prompt 要求产品作为外置刚性实物合成到后颈外侧,禁止穿模、融进透明身体或重绘产品。不再暴露产品角度槽、产品融合辅助栏、产品图库选择器或首尾帧槽。主体资产页只确认一个统一主体,后端按参考重绘六张纯背景、占满画面的标准站立透明骨架人资产图;首尾帧页保留给旧流程/单独生图,不再是产品融合必填步骤。相关接口包括 <code>cleanupFrame</code>、<code>applyCleanedFrame</code>、<code>addElement</code>、<code>generateSubjectAssets</code>、<code>generateSceneAsset</code>、<code>copyProductLibraryAsset</code> 和 <code>copyCharacterLibraryAssets</code>。</span></div>
|
||
<div><strong>适合怎么描述</strong><span>“这一组关键帧如何共同生成一个统一主体包;某张关键帧的水印、去主体场景图、产品融合镜头组和质量风险应该如何审核”。</span></div>
|
||
</div>
|
||
<div class="flow-row">
|
||
<div><strong>你看到的区域</strong><span>旧分镜明细区(底层保留)</span></div>
|
||
<div><strong>主要源码</strong><span><code>StoryboardWorkbench</code>;保存到 <code>frame.storyboard</code>;接口 <code>PUT /storyboard</code>。SKG 产品参考区同时支持上传、剪贴板和内置白底产品库。</span></div>
|
||
<div><strong>适合怎么描述</strong><span>“每个分镜需要哪些图片槽、哪些改造说明,哪些 SKG 产品图要作为视频生成参考”。</span></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="data-model" data-search>
|
||
<h2>数据模型</h2>
|
||
<div class="grid-2">
|
||
<div class="card">
|
||
<h3>Job</h3>
|
||
<p>一个视频任务。前端维护多个 <code>jobs[]</code>,当前激活的是 <code>activeJobId</code>。URL 查询参数会持久化多个 job。</p>
|
||
<pre>Job {
|
||
id, url, status, progress, message,
|
||
video_url, source_audio_url, duration, width, height,
|
||
frames: KeyFrame[],
|
||
transcript: TranscriptSegment[],
|
||
audio_script: AudioScript,
|
||
storyboard_images?: StoryboardImage[]
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>KeyFrame</h3>
|
||
<p>关键帧是整个产品的核心单位。<code>index</code> 是稳定 ID,手动加帧后不连续,不能用数组下标代替。</p>
|
||
<pre>KeyFrame {
|
||
index, timestamp, url,
|
||
description,
|
||
transparent_human_score,
|
||
cleaned_url, cleaned_applied,
|
||
quality_report,
|
||
scene_assets: SceneAsset[],
|
||
elements: KeyElement[],
|
||
storyboard: StoryboardScene,
|
||
generated_images: GeneratedImage[]
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>TransparentHumanFrameScore</h3>
|
||
<p>透明骨架人主题的抽帧验收结果。只有 <code>target=transparent_human</code> 时会在抽帧阶段写入;普通抽帧目标不要求该字段。</p>
|
||
<pre>TransparentHumanFrameScore {
|
||
transparent_body_score: 0-25,
|
||
skeleton_visible_score: 0-25,
|
||
human_prominence_score: 0-15,
|
||
clarity_score: 0-15,
|
||
commercial_style_score: 0-10,
|
||
product_usefulness_score: 0-10,
|
||
total_score,
|
||
qualified,
|
||
reject_reason
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>KeyElement</h3>
|
||
<p>从关键帧识别结果里确认出来的主体候选。当前素材准备流程只保留一个统一主体;多张关键帧通过 <code>source_frame_indices</code> 作为该主体的参考帧。</p>
|
||
<pre>KeyElement {
|
||
id,
|
||
name_zh, name_en, position,
|
||
source: auto | manual | region,
|
||
region,
|
||
cutouts: string[],
|
||
cutout_id,
|
||
subject_kind: object | living,
|
||
subject_assets: SubjectAsset[]
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>AudioScript</h3>
|
||
<p>第一步音频解析的结构化产物。<code>pipeline_transcribe</code> 提取 <code>audio.wav</code> 后先保存原始转写、中文翻译、讲话人画像、口播节奏和背景音乐/环境声/音效分析。<code>rewritten_text</code>、<code>voice_url</code> 等字段仍保留给后续新配音阶段,当前第一步不默认写入。</p>
|
||
<pre>AudioScript {
|
||
status: idle | rewriting | completed | failed,
|
||
source_text,
|
||
source_zh,
|
||
rewritten_text,
|
||
speaker_profile,
|
||
rhythm_profile,
|
||
background_audio_profile,
|
||
product_brief,
|
||
rewrite_model,
|
||
voice_provider: minimax,
|
||
voice_model,
|
||
voice_id,
|
||
voice_url,
|
||
error
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>SceneAsset / SubjectAsset</h3>
|
||
<p>画面工作台素材准备阶段生成的组图资产。实际图片保存在 <code>jobs/<jobId>/assets</code>,可作为 <code>asset</code> 类型复制到分镜槽位。</p>
|
||
<pre>SceneAsset {
|
||
id, label, url,
|
||
width, height, quality, size,
|
||
scene_mode: remove_subject | similar | style,
|
||
scene_style,
|
||
quality_report
|
||
}
|
||
|
||
SubjectAsset {
|
||
id, view, label, url,
|
||
background: white | black,
|
||
width, height, size,
|
||
source_frame_indices[]
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>ProductLibraryItem</h3>
|
||
<p>内置 SKG 白底图库条目。实际图片保存在 <code>api/product_library/skg-products/images</code>,被选中时会复制到 <code>jobs/<jobId>/assets</code>,再以普通 <code>ImageRef(kind="asset")</code> 进入产品参考组。</p>
|
||
<pre>ProductLibraryItem {
|
||
id, handle, title, product_type,
|
||
image_index, filename, url,
|
||
width, height,
|
||
white_score,
|
||
source_path,
|
||
tags[]
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>ProductFusionShot</h3>
|
||
<p>产品融合镜头组的单行数据。每个关键帧最多 6 行,用户选择一个内置角色后只微调场景/产品使用/享受描述和秒数;四张桌面 SKG 产品角度图会在顶部显式展示为真实产品真源,所选角色 7 张参考图作为人物身份参考,生成时作为 Seedance 参考图提交。</p>
|
||
<pre>ProductFusionShot {
|
||
id,
|
||
first_image,
|
||
last_image,
|
||
product_images[4],
|
||
action_text,
|
||
duration,
|
||
image_model: gpt-image-2,
|
||
video_model: seedance,
|
||
// legacy: product_image, person_image, product_region, scene_image, guide_image
|
||
}</pre>
|
||
</div>
|
||
<div class="card">
|
||
<h3>StoryboardScene</h3>
|
||
<p>分镜编排结果,不是复刻说明。它把参考图和 SKG 改造方向绑定到一个分镜上。</p>
|
||
<pre>StoryboardScene {
|
||
duration,
|
||
subject_image,
|
||
scene_image,
|
||
product_image,
|
||
action_image,
|
||
subject,
|
||
product,
|
||
scene,
|
||
action
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="api-map" data-search>
|
||
<h2>接口地图</h2>
|
||
<table>
|
||
<thead>
|
||
<tr><th>功能</th><th>接口</th><th>前端调用</th><th>说明</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>网页登录</td><td><code>POST /auth/login</code>、<code>GET /auth/check</code>、<code>POST /auth/logout</code></td><td><code>web/app/login/page.tsx</code>、Nginx <code>auth_request</code></td><td>登录页提交账号密码到 <code>/api/auth/login</code>,后端设置 HttpOnly 会话 Cookie;生产 Nginx 对工作台和 <code>/api/</code> 调 <code>/auth/check</code> 做统一校验,未登录页面跳 <code>/login/</code>,API 返回 JSON 401。</td></tr>
|
||
<tr><td>历史列表</td><td><code>GET /jobs</code></td><td><code>listJobs</code></td><td>所有 job 精简列表(id/url/status/thumbnail/mtime…),按 state.json mtime 倒序。前端 URL 无 <code>?job=</code> 时拉它回填全部历史;带 <code>limit</code> 可截断。</td></tr>
|
||
<tr><td>创建任务</td><td><code>POST /jobs</code></td><td><code>createJob</code></td><td>提交 TK 链接,后台开始下载;前端“开始”队列会在 downloaded 后自动触发音频解析。</td></tr>
|
||
<tr><td>上传视频</td><td><code>POST /jobs/upload</code></td><td><code>uploadJob</code></td><td>保存 source.mp4,然后同样进入下载完成状态;当前上传后也加入第一步队列,下载完成后自动解析音频。</td></tr>
|
||
<tr><td>删除输入视频</td><td><code>DELETE /jobs/{id}</code></td><td><code>deleteJob</code></td><td>从任务队列、URL 和磁盘 <code>jobs/<id></code> 目录移除整个 job,包括源视频、关键帧、元素提取图和生成视频。</td></tr>
|
||
<tr><td>解析视频</td><td><code>POST /jobs/{id}/analyze?frames=&target=&mode=&quality=</code></td><td><code>analyzeJob</code></td><td>后续阶段保留的抽帧能力。默认 <code>frames=12</code>;<code>target</code> 支持透明骨架人、综合、清晰主体、转场变化、表情瞬间、动作峰值。当前第一步主流程不自动调用该接口。</td></tr>
|
||
<tr><td>音频文案轨</td><td><code>POST /jobs/{id}/transcribe</code></td><td><code>triggerTranscribe</code></td><td>若尚未拆轨,先从 <code>source.mp4</code> 提取 <code>audio.wav</code> 并回填 <code>source_audio_url</code>;随后用 ASR 提取原始文案,翻译成中文,写入 <code>audio_script.source_text</code>、<code>source_zh</code> 和逐句 <code>transcript</code>。<code>ASR_TIMEOUT_SECONDS</code> 默认 45 秒,<code>whisper-1</code> 超时或异常后自动 fallback 到 <code>ASR_FALLBACK_MODEL</code>。再用 <code>ASR_FALLBACK_MODEL</code> 多模态音频分析讲话人、语速节奏、停顿、背景音乐/环境声/音效,写入 <code>speaker_profile</code>、<code>rhythm_profile</code>、<code>background_audio_profile</code>。当前第一步不默认生成 SKG 新口播和 MiniMax 配音。</td></tr>
|
||
<tr><td>原始音频文件</td><td><code>GET /jobs/{id}/audio.wav</code></td><td><code>sourceAudioUrl</code></td><td>返回拆轨得到的 wav;当前主界面不再渲染底部音频条,右侧音频解析工作表直接使用 <code>transcript</code> 和 <code>audio_script</code> 展示文字与声音分析结果。</td></tr>
|
||
<tr><td>改写配音文件</td><td><code>GET /jobs/{id}/audio-script.mp3</code></td><td><code>apiAssetUrl(job.audio_script.voice_url)</code></td><td>后续新配音阶段保留的 MiniMax T2A 产物。当前第一步不默认生成该文件。</td></tr>
|
||
<tr><td>手动加帧</td><td><code>POST /jobs/{id}/frames?t=</code></td><td><code>addManualFrame</code></td><td>按视频时间戳抽一帧,index 递增但 frames 按 timestamp 排序。</td></tr>
|
||
<tr><td>Vision 识别</td><td><code>POST /frames/{idx}/describe</code></td><td><code>describeFrame</code></td><td>写入 frame.description,后续可从 objects 加候选元素。</td></tr>
|
||
<tr><td>清洗水印</td><td><code>POST /frames/{idx}/cleanup</code></td><td><code>cleanupFrame</code></td><td>支持全图和区域清洗,生成 cleaned 待应用版本;前端批量清洗会顺序调用该接口,不自动覆盖原图。单帧清洗状态按 frame.index 隔离,清洗某一张不会禁用其他关键帧的清洗按钮。</td></tr>
|
||
<tr><td>应用清洗版</td><td><code>POST /frames/{idx}/cleanup/apply</code></td><td><code>applyCleanedFrame</code></td><td>把 cleaned 待应用版本覆盖到原关键帧,并保留首次原图备份;前端“一键替换待应用”会顺序调用该接口应用所有已有清洗版。</td></tr>
|
||
<tr><td>应用清洗</td><td><code>POST /cleanup/apply</code></td><td><code>applyCleanedFrame</code></td><td>物理覆盖 frames/{idx}.jpg,并备份原图。</td></tr>
|
||
<tr><td>元素增改删</td><td><code>POST/PATCH/DELETE /elements</code></td><td><code>addElement/updateElement/deleteElement</code></td><td>让用户修正 Vision 错误,避免候选结果锁死。</td></tr>
|
||
<tr><td>元素提取</td><td><code>POST /elements/{element_id}/cutout</code></td><td><code>cutoutElement</code></td><td>调用图像模型生成独立白底素材图,每次累积一张 cutout。</td></tr>
|
||
<tr><td>主体资产包</td><td><code>POST /elements/{element_id}/subject-assets</code></td><td><code>generateSubjectAssets</code></td><td>根据参考帧重新绘制一个统一主体资产包;前端默认把全部关键帧作为 <code>source_frame_indices</code>,如果用户手动选择了关键帧则只传已选帧,后端拼参考板。人物默认输出六张身份标准图,另有表情补充和动作补充分组可选;纯白/黑背景,不含其他元素,并裁去空白让主体占满画面。</td></tr>
|
||
<tr><td>首尾帧资产</td><td><code>POST /frames/{idx}/scene-asset</code></td><td><code>generateSceneAsset</code></td><td>同一接口兼容旧场景图和新首尾帧;新流程传 <code>asset_role=first_frame/last_frame</code>,后端走文字生图,参考帧只用于理解透明骨架人形象、比例、机位和光线,生成结果仍保存在 <code>scene_assets</code> 并自动填入产品融合镜头。</td></tr>
|
||
<tr><td>产品图库</td><td><code>GET /product-library/skg</code></td><td><code>listProductLibrary</code></td><td>读取内置 SKG 白底图库 manifest,返回产品标题、品类、尺寸、白底评分和预览图 URL。</td></tr>
|
||
<tr><td>产品图入库到 job</td><td><code>POST /jobs/{id}/assets/product-library</code></td><td><code>copyProductLibraryAsset</code></td><td>把一个内置产品图库条目复制为当前 job 的普通 asset,返回 <code>ImageRef(kind="asset")</code>,用于画面工作台产品融合和分镜产品参考组。</td></tr>
|
||
<tr><td>角色库</td><td><code>GET /character-library/skg</code></td><td><code>listCharacterLibrary</code></td><td>读取内置 5 个透明骨架人角色 manifest,每个角色含正面、左右 45 度、侧面、背面、半身近景和背部特写 7 张参考图。</td></tr>
|
||
<tr><td>角色图入库到 job</td><td><code>POST /jobs/{id}/assets/character-library</code></td><td><code>copyCharacterLibraryAssets</code></td><td>把所选角色的 7 张参考图复制为当前 job asset,返回 <code>subject_images</code>,产品融合生成视频时作为人物身份参考图提交。</td></tr>
|
||
<tr><td>产品融合引导图</td><td><code>POST /jobs/{id}/product-fusion/guide</code></td><td><code>createProductFusionGuide</code></td><td>旧流程兼容接口:读取产品图和白底人物图,按 <code>product_region</code> 合成位置引导图。当前内置角色 + 产品 + 描述流程不再主动调用它。</td></tr>
|
||
<tr><td>产品融合描述词</td><td><code>POST /jobs/{id}/product-fusion/descriptions</code></td><td><code>generateProductFusionDescriptions</code></td><td>兼容接口:可生成产品融合动作描述库。当前前端默认直接用本地 36 条镜头语言模板预填 6 行镜头,并通过“换一组”按钮按 6 条一组轮换。</td></tr>
|
||
<tr><td>分镜保存</td><td><code>PUT /frames/{idx}/storyboard</code></td><td><code>updateStoryboard</code></td><td>保存 4 图槽、时长和改造说明。</td></tr>
|
||
<tr><td>生图</td><td><code>POST /frames/{idx}/generate</code></td><td><code>generateImage</code></td><td>基于关键帧或已选生成图做 image-to-image,目前可用。</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<section id="node-contract" data-search>
|
||
<h2>节点职责边界</h2>
|
||
<table>
|
||
<thead>
|
||
<tr><th>节点</th><th>当前职责</th><th>不该承担</th><th>改动主要文件</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="tag blue">音频解析工作表</span></td>
|
||
<td>承载当前第一步主路径:素材输入列按文件任务管理素材;点击“开始”后自动下载源视频,下载完成后只触发音频提取、原文案转写、中文翻译、讲话人/节奏/背景音分析,并以工作表方式展示。</td>
|
||
<td>不要在当前开始流程里自动抽帧、自动写分镜、自动生成元素或自动合成视频;不要恢复右侧空白画布占位。</td>
|
||
<td><code>web/components/ad-recreation-board.tsx</code>、<code>web/app/page.tsx</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="tag violet">旧节点 / 深度素材面板</span></td>
|
||
<td><code>InputNode</code>、<code>VisualLabNode</code>、<code>AudioNode</code>、<code>ComposeNode</code>、<code>FrameLightbox</code> 等底层能力暂保留,避免本次大改同时破坏抽帧、音频、素材处理和历史 job 数据。</td>
|
||
<td>不要作为当前用户主路径展示;后续迁移时按看板工作流重新整理。</td>
|
||
<td><code>web/components/nodes/index.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>web/components/storyboard-workbench.tsx</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="tag gray">音频条</span></td>
|
||
<td>音频解析工作表顶部触发音频解析,结果在右侧原文案、中文翻译、逐句时间轴和声音/背景音分析区展示;底部 <code>AudioStrip</code> 当前不渲染。</td>
|
||
<td>当前第一步不要默认展示底部音频条、新配音播放器,或把 MiniMax 配音当作已完成结果。</td>
|
||
<td><code>web/components/audio-strip.tsx</code>、<code>pipeline_transcribe</code>、<code>AudioScript</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="tag green">候选片段</span></td>
|
||
<td>后续阶段保留的生成视频能力,仍可通过底层接口和旧组件继续演进。</td>
|
||
<td>不要在第一步入口里露出“生成全部视频”或误导用户认为已进入视频合成。</td>
|
||
<td><code>/storyboard/video</code>、<code>generated_videos</code>、<code>AdRecreationBoard</code></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<section id="current-state" data-search>
|
||
<h2>当前已通与阻塞</h2>
|
||
<div class="grid-2">
|
||
<div class="card">
|
||
<h3>已通</h3>
|
||
<ul>
|
||
<li>TK 链接 / 上传创建 job。</li>
|
||
<li>视频下载或本地保存;后端会检测可用 ffmpeg/ffprobe,PATH 版本不可用时可 fallback 到本机静态 ffmpeg,避免 Homebrew 动态库损坏导致素材输入失败。</li>
|
||
<li>手动按时间戳加关键帧。</li>
|
||
<li>关键帧清洗水印,全图或区域清洗。</li>
|
||
<li>Vision 识别关键帧,输出 scene、objects、style、suggested_prompt,并作为主体候选来源。</li>
|
||
<li>“开始”会在下载完成后自动触发音频处理,不再默认自动抽帧、Vision 扫描或保存分镜初稿。</li>
|
||
<li>主体候选确认、改名、删除和主体资产包生成能力保留在底层旧面板和接口中,当前第一步主界面不主动展示。</li>
|
||
<li>分镜工作台 4 图槽和改造说明自动保存。</li>
|
||
<li>音频文案轨:点击开始或提取音频后提取原文案、中文翻译、讲话人、语速节奏、背景音乐/环境声/音效;结果集中在右侧工作表展示。</li>
|
||
<li>nano-banana-pro image-to-image 生图。</li>
|
||
</ul>
|
||
</div>
|
||
<div class="card">
|
||
<h3>阻塞 / 占位</h3>
|
||
<ul>
|
||
<li>ASR:优先走当前 OpenAI-compatible 音频转写入口;如果该网关没有 <code>/audio/transcriptions</code>,自动 fallback 到 <code>ASR_FALLBACK_MODEL</code>(默认 <code>gemini-2.5-flash</code>)的多模态音频识别。</li>
|
||
<li>MiniMax:当前接入的是官方 T2A 英文配音能力,不是 ASR;第一步暂不默认调用。默认随机音色池是 <code>English_magnetic_voiced_man</code>、<code>English_Upbeat_Woman</code>、<code>English_MaturePartner</code>。API Key 只能放本地环境变量,不能写入仓库。</li>
|
||
<li>Audio Product Brief:默认是通用 SKG 放松产品卖点;当前第一步只保留配置,后续分镜/新配音阶段再使用。</li>
|
||
<li>Video Gen:模型层按业务保留 Seedance / Kling / Veo/Voe 选择;后端已支持 Poe、火山方舟和 SKG 豆包视频网关。Seedance 可通过 <code>VIDEO_API_BASE_URL=https://ai.skg.com/doubao</code> 走 content JSON 异步任务,提交后写入候选片段并轮询到完成。</li>
|
||
<li>Compose:还没做本地 ffmpeg 字幕/TTS 合成。</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="callout warn" style="margin-top:14px">
|
||
<p>最重要的产品判断:当前先把“链接/上传 → 下载 → 音频原文案与声音背景音分析”跑顺;视觉抽帧、分镜和视频生成不要再反过来挤进第一步。</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="request-language" data-search>
|
||
<h2>需求描述模板</h2>
|
||
<div class="todo">
|
||
<div class="todo-item">
|
||
<h3>改音频解析工作表</h3>
|
||
<p>“我在素材输入列或右侧音频解析工作表,开始后下载、转写、翻译、讲话人/节奏/背景音哪些状态要怎么展示。”</p>
|
||
</div>
|
||
<div class="todo-item">
|
||
<h3>改音频字段</h3>
|
||
<p>“每条音频解析结果需要哪些字段,例如原文案、中文翻译、说话人、语速、停顿、BGM、环境声、音效、置信度。”</p>
|
||
</div>
|
||
<div class="todo-item">
|
||
<h3>进入下一步</h3>
|
||
<p>“音频解析完成后,什么时候才进入抽帧、分镜规划、产品融入、关键元素 6 视图或视频生成。”</p>
|
||
</div>
|
||
<div class="todo-item">
|
||
<h3>改数据/接口</h3>
|
||
<p>“这个动作需要持久化到 state.json,字段加在 Job/KeyFrame/KeyElement/StoryboardScene 哪一层,刷新后要恢复。”</p>
|
||
</div>
|
||
<div class="todo-item">
|
||
<h3>改工作区语义</h3>
|
||
<p>“这个工作区的业务职责要改,不只是 UI 文案;请同步更新标题、说明、可点击行为、状态推导和本源码解析页。”</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="change-log" data-search>
|
||
<h2>变更记录</h2>
|
||
<p>这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。</p>
|
||
<div class="changelog">
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-17 · 修复素材输入元数据解析并移除底部音频条</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag orange">Bugfix</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>粘贴 TK 链接后视频已经下载到 <code>source.mp4</code>,但本机 Homebrew <code>ffprobe</code>/<code>ffmpeg</code> 因缺少 <code>libx265.215.dylib</code> 直接崩溃,后端误显示为“下载失败”。同时用户不再需要底部音频展示。</p>
|
||
<p><strong>改动:</strong><code>api/main.py</code> 新增媒体二进制选择逻辑,先验证 PATH 里的 <code>ffmpeg/ffprobe</code> 是否可执行,失败时回退到本机静态 <code>ffmpeg</code>;没有可用 <code>ffprobe</code> 时用 <code>ffmpeg -i</code> 解析时长和分辨率。下载阶段把“元数据解析失败”和“下载失败”区分开。ASR 请求增加 <code>ASR_TIMEOUT_SECONDS</code>,<code>whisper-1</code> 长时间无响应时自动走 fallback。<code>web/app/page.tsx</code> 不再导入和渲染 <code>AudioStrip</code>,<code>AdRecreationBoard</code> 移除“打开音轨”按钮。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/app/page.tsx</code>、<code>web/components/ad-recreation-board.tsx</code>、<code>RULES.md</code>、<code>docs/source-analysis.html</code>。后续音频预览如果需要恢复,应先明确是否仍放在右侧工作表,而不是默认恢复底部浮层。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-17 · 收窄为第一步音频解析</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag cyan">Workflow</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>用户明确否定前一版“开始后自动抽帧、分镜、元素、合成”的推进方式,当前只需要把信息流广告快速复刻的第一步跑通:粘贴 TK 链接或上传视频,下载源视频,提取原音频文案,并分析讲话人、节奏和背景音。</p>
|
||
<p><strong>改动:</strong><code>web/app/page.tsx</code> 的开始流程改为下载完成后只自动触发 <code>triggerTranscribe</code>;上传视频也加入同一音频解析队列。<code>AdRecreationBoard</code> 主渲染改成左侧素材输入 + 右侧音频解析工作表,不再显示“追加分镜”“开始抽帧”“生成全部视频”。<code>AudioStrip</code> 右侧改为原文案/翻译/声音背景音分析。<code>AudioScript</code> 新增 <code>background_audio_profile</code>,后端 <code>pipeline_transcribe</code> 先保存原文案、中文翻译、讲话人、节奏和背景音分析,当前第一步不默认生成 SKG 新口播或 MiniMax 配音。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/ad-recreation-board.tsx</code>、<code>web/components/audio-strip.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>、<code>RULES.md</code>、<code>.project.json</code>、<code>docs/source-analysis.html</code>。后续需求应先描述“音频解析完成后是否进入下一步”,不要默认把抽帧/分镜/合成塞进开始动作。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-17 · 开始生产自动编排</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag cyan">Workflow</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>状态:</strong>已被上一条“收窄为第一步音频解析”覆盖;保留此记录用于解释旧代码和历史提交为什么存在。</p>
|
||
<p><strong>问题:</strong>用户希望粘贴视频链接后点击一次“开始”,系统就自动完成素材准备:抽帧、音频分析、关键元素扫描和分镜初稿;人工只负责判断规划是否合理、选择关键元素、再单条或全量生成视频。</p>
|
||
<p><strong>改动:</strong><code>web/app/page.tsx</code> 新增开始生产编排状态:创建/激活 job 后,下载完成自动触发 <code>analyzeJob</code> 与 <code>triggerTranscribe</code>,关键帧出来后逐帧调用 <code>describeFrame</code> 并用 <code>updateStoryboard</code> 保存分镜初稿。视频生成时若分镜未显式选择产品图,会自动复制四张 <code>desktop-skg-product-angle-01..04</code> 作为 SKG 产品真源,并把已生成的关键元素 6 视图作为主体参考。<code>AdRecreationBoard</code> 把导入按钮改为“开始”,分镜卡里的候选元素可点击生成提取图 + 6 视图,顶部新增“生成全部视频”。<code>AudioScript</code> 新增 <code>speaker_profile</code> 和 <code>rhythm_profile</code>,用于展示讲话人 / 节奏参考。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/ad-recreation-board.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>、<code>RULES.md</code>、<code>.project.json</code>、<code>docs/source-analysis.html</code>。后续需求应区分“开始生产自动编排”和“人工审核/选择/生成”的边界。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-17 · 合并为单一分镜生产板块</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag cyan">Workflow</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>四列横向生产流仍把音频文案、关键元素和视频生成拆开,用户真正需要的是每个分镜内部上下游一一对应,快速复刻信息流广告。</p>
|
||
<p><strong>改动:</strong><code>AdRecreationBoard</code> 改为左侧素材输入列 + 右侧单一分镜生产板块。右侧顶部保留音频解析、打开音轨、追加分镜和抽帧控制;下方每张 <code>StoryboardSegmentCard</code> 从上到下依次包含音频分镜文案、每个分镜需要的关键元素、视频生成候选。新增 <code>DraftSegmentCard</code> 支持先无限追加草稿分镜,再绑定关键帧后保存和生成候选视频。完整视频合成入口保留在底部,后端合成接口仍待接入。本地开发态隐藏 <code>nextjs-portal</code>,避免 Next Issue 浮层遮挡看板截图。</p>
|
||
<p><strong>影响:</strong><code>web/components/ad-recreation-board.tsx</code>、<code>web/app/globals.css</code>、<code>RULES.md</code>、<code>.project.json</code>、<code>docs/source-analysis.html</code>。后续需求应按“素材输入列 + 分镜生产板块 + 分镜卡片三层结构”描述。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-17 · 看板改为四列横向生产流</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag cyan">Workflow</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>左侧抽屉式看板仍像单点操作面板,不符合用户要的“从左往右推进”的广告生产逻辑。</p>
|
||
<p><strong>改动:</strong><code>AdRecreationBoard</code> 改为全屏横向四列:素材输入列按文件任务管理素材;音频解析 / 新分镜文案列把分镜从上到下排列;视频关键元素 / 抽帧生成列把关键帧横向排列,并在每张帧卡上直接生成元素和候选片段;视频合成列汇总音频、候选片段和待接入合成接口。<code>page.tsx</code> 不再渲染右侧空白 ReactFlow 画布。</p>
|
||
<p><strong>影响:</strong><code>web/components/ad-recreation-board.tsx</code>、<code>web/app/page.tsx</code>、<code>RULES.md</code>、<code>.project.json</code>、<code>docs/source-analysis.html</code>。该方向已被上方“单一分镜生产板块”取代,保留为历史记录。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-17 · 主界面改为左侧信息流广告复刻看板</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag cyan">Workflow</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>此前主界面把输入、画面、音频、合成组织成 ReactFlow 可视化节点,但当前目标已确认是“快速产出信息流广告复刻片段”,节点式展示增加理解成本。</p>
|
||
<p><strong>改动:</strong>新增 <code>web/components/ad-recreation-board.tsx</code>,把素材输入、视频抽帧、音频文案、关键帧选择、剧情规划/产品融入和候选片段选择合并到左侧工作表。<code>web/app/page.tsx</code> 主渲染改为左侧看板 + 右侧空白 ReactFlow 无限画布,画布节点和边暂不展示;<code>web/next.config.mjs</code> 清理 Next 16 已不支持的 <code>eslint</code> 配置,避免本地 dev 左下角 Issue 提示遮挡界面。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/ad-recreation-board.tsx</code>、<code>web/next.config.mjs</code>、<code>RULES.md</code>、<code>.project.json</code>、<code>docs/source-analysis.html</code>。后续需求应优先描述“左侧看板里的哪一段工作表”和“右侧空白画布未来要承载什么”。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-16 · 登录页 Logo 静态资源公开访问</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag cyan">Deploy</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>生产登录页引用 <code>/skg-logo-black.svg</code>,但 Nginx 只公开了 <code>/login/</code>、<code>/_next/</code>、<code>/assets/</code> 和 <code>/oasis-source/</code>,未登录访问该 SVG 会被重定向到 <code>/login/</code>,导致 logo 不显示。</p>
|
||
<p><strong>改动:</strong><code>deploy/nginx.conf</code> 新增 <code>location = /skg-logo-black.svg</code>,把官网 SKG 字标作为登录页必需静态资源公开;<code>RULES.md</code> 和本文档同步更新部署事实。</p>
|
||
<p><strong>影响:</strong><code>deploy/nginx.conf</code>、<code>RULES.md</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-16 · 登录页品牌文字和 Logo 水平对齐</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>SKG logo 放大后,右侧“营销内容工作台”的视觉水平线和 logo 内“未来健康”中文部分略有错位。</p>
|
||
<p><strong>改动:</strong><code>web/app/globals.css</code> 将系统标识连同分隔线整体下移,桌面端和移动端分别使用不同偏移,保持 logo 尺寸不变。</p>
|
||
<p><strong>影响:</strong><code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-16 · 登录页系统标识改中文并放大 Logo</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录页用户主要是华人,左上角系统标识继续使用英文 <code>Marketing Studio</code> 不够直接;SKG logo 在当前画面中略小,分隔线和文字需要更稳地水平对齐。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 将系统标识改为“营销内容工作台”;<code>web/app/globals.css</code> 放大桌面和移动端 logo,调整品牌组间距、分隔线高度、中文字号和字距。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录右侧表单下移并收紧按钮间距</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>错误感叹号去掉后,保持登录和提交按钮之间仍保留了旧状态区空位;右侧表单整体也显得偏高。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 只在成功态渲染状态图标,不再为空闲/错误态保留固定高度;<code>web/app/globals.css</code> 将桌面端右侧表单继续下移到更贴近截图反馈的位置,移动端保持原排列。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录错误状态去掉感叹号</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>密码输入错误时,保持登录和按钮之间会出现一个感叹号图标,视觉上干扰登录表单。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 删除错误态 <code>AlertCircle</code> 图标渲染;错误反馈仍由动态角色的 error 状态承担,成功态勾选图标保留。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页补系统标识和保持登录</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>只放 SKG 字标还缺少具体系统识别;保持会话复选框没有文字说明;表单上方单独的小锁图标占位多余。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 在 SKG 字标旁加入 <code>Marketing Studio</code> 系统标识,复选框旁恢复“保持登录”,并删除表单上方独立锁图标;<code>web/app/globals.css</code> 增加品牌标识组合布局与移动端尺寸。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页加入 SKG 字标并增强角色立体感</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录页缺少 SKG 品牌识别;动态角色仍偏扁平,和玻璃草场背景的空间感不够一致。</p>
|
||
<p><strong>改动:</strong>新增 <code>web/public/skg-logo-black.svg</code>,来源为官网 <code>cn.skg.com/logo-black.svg</code>;<code>web/app/login/page.tsx</code> 在组合登录框内加入 SKG 标识;<code>web/app/globals.css</code> 为标识做反相白色玻璃处理,并给四个动态角色加高光、暗边、内阴影、接触投影和透视层次。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>web/public/skg-logo-black.svg</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录框固定在视口中心</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>组合登录框仍放在普通文档流的居中容器里,背景滚动或视口变化时视觉上会偏离画面中心。</p>
|
||
<p><strong>改动:</strong><code>web/app/globals.css</code> 将 <code>login-source-overlay</code> 改为固定覆盖全屏层;组合登录框自身用 <code>position:fixed; left/top:50%; transform:translate(-50%,-50%)</code> 直接锚定视口中心,避免网格或背景滚动状态造成偏移。</p>
|
||
<p><strong>影响:</strong><code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录小人完整显示并恢复背景响应</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>左右排列后动态小人左侧区域偏窄,角色边缘被裁;上轮为处理底部黑边把 Oasis 背景硬锁成单屏,削弱了背景随鼠标和滚动变化的感觉。</p>
|
||
<p><strong>改动:</strong><code>web/app/globals.css</code> 扩大组合登录框和左侧角色列,提升角色区域高度与缩放比例;<code>web/components/login/oasis-canvas.tsx</code> 改为原生鼠标事件和 <code>postMessage</code> 双通道转发,输入框上移动鼠标也驱动草地;<code>web/public/oasis-source/index.html</code> 恢复完整滚动进度,保留末端阶段,只禁用原 footer 可见时的 canvas 上移逻辑来去除底部黑边。</p>
|
||
<p><strong>影响:</strong><code>web/app/globals.css</code>、<code>web/components/login/oasis-canvas.tsx</code>、<code>web/public/oasis-source/index.html</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页背景锁定单屏避免底部黑边</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>Oasis 原源码仍保留多段滚动页面高度,浏览器滚到最后一段或恢复 iframe 滚动位置时,相机会进入 footer 视角并在登录页底部露出黑边。</p>
|
||
<p><strong>改动:</strong><code>web/public/oasis-source/index.html</code> 的登录嵌入模式禁用 <code>html/body</code> 滚动,将隐藏的 <code>#scroll-container</code> 固定为单屏,并把隐藏 footer 固定到视口下方且高度归零,避免原脚本触发 canvas 上移。</p>
|
||
<p><strong>影响:</strong><code>web/public/oasis-source/index.html</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录框改为动画和表单左右排列</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录框内动画角色和账号/密码表单仍是上下堆叠,不符合“左右排列”的要求。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 给表单加独立布局类;<code>web/app/globals.css</code> 将桌面端组合登录框改为两列网格,左侧放大动画角色,右侧放账号、密码、复选框和提交图标;移动端继续上下排列避免挤压。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页路由文字彻底清空</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录框主体已经没有可见文字,但 <code>/login</code> 仍会继承全站 <code>title</code>/<code>description</code>,背景 iframe 也保留了描述性 <code>title</code>,导致检查页面源码时还能看到文字。</p>
|
||
<p><strong>改动:</strong>新增 <code>web/app/login/layout.tsx</code> 将登录路由 metadata 覆盖为空;<code>web/components/login/oasis-canvas.tsx</code> 删除 iframe 的 <code>title</code> 属性;<code>web/next.config.mjs</code> 禁用开发环境左下角 Next Dev Indicator。登录界面只保留动态图形、输入框、复选框和图标按钮。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/layout.tsx</code>、<code>web/components/login/oasis-canvas.tsx</code>、<code>web/next.config.mjs</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录框改为无可见文字</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>组合登录框内仍显示输入占位、保持会话、按钮文字和状态提示文字,不符合“登录框文字都删掉”的要求。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 删除账号/密钥输入框占位文字、保持会话文本、提交按钮文本、错误/成功状态文本以及表单控件上的可读 <code>aria-label</code>;表单视觉只保留图标、输入区域、复选框和箭头按钮。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页合并小人和表单并清空旧文字</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录页不应再出现旧版入口文案、流程状态和指标文字;小人独立玻璃框会扩大遮挡面积,网格背景也不需要。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 将动态角色和登录表单合并进同一个 <code>login-source-auth-panel</code>,删除独立角色框。<code>web/app/globals.css</code> 让浮层容器默认不接收指针事件,只让登录框接收交互;角色区域去掉网格、边框、底部阴影和单独背景。<code>web/components/login/oasis-canvas.tsx</code> 改用 <code>document</code> 捕获阶段监听鼠标移动,并向 Oasis iframe 派发原生 <code>mousemove</code>,让它复用原源码玻璃板覆盖时仍驱动草地的逻辑。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/components/login/oasis-canvas.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页只保留源码背景、登录和动画</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录页仍像内容页,保留了旧版入口营销文案、状态胶囊和底部指标,和“直接把源码背景写过来,上面只放登录和动画”的目标不一致。</p>
|
||
<p><strong>改动:</strong><code>web/app/login/page.tsx</code> 删除左侧营销文案、状态胶囊、标题、说明、Pipeline 和指标栏,只保留 <code>OasisCanvas</code>、动态角色透明框和登录表单。<code>web/app/globals.css</code> 新增 <code>login-page--source</code>、<code>login-source-overlay</code>、<code>login-source-character-panel</code> 等样式,让两个功能浮层直接叠在原版 Digital Oasis 背景上。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页草地鼠标转发、面板压缩和角色放大</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>原版 Digital Oasis 鼠标划过草地会产生响应,但登录页的表单和透明面板盖在 iframe 上方时,iframe 收不到鼠标坐标;同时右侧登录面板过大,左侧动态角色被压成小装饰。</p>
|
||
<p><strong>改动:</strong><code>web/components/login/oasis-canvas.tsx</code> 在捕获阶段监听父页面指针移动,并通过 <code>postMessage</code> 发送到 <code>web/public/oasis-source/index.html</code>,后者复用原 raycaster 逻辑驱动草地。<code>web/app/login/page.tsx</code> 将身份验证面板改成 290-320px 窄列、去掉强制大高度、压缩标题/输入/按钮间距;<code>web/app/globals.css</code> 将动态角色面板放大成左侧透明框架里的主视觉。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/components/login/oasis-canvas.tsx</code>、<code>web/public/oasis-source/index.html</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页两块主面板复刻 Pillars 透明卡片质感</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Login</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录页左右两块面板仍偏旧黑色实体面板,没有用上源码 <code>Pillars</code> 区域的透明玻璃质感。</p>
|
||
<p><strong>改动:</strong><code>web/app/globals.css</code> 将左侧内容面板和右侧登录面板统一改为源码 <code>.pillar-card</code> 的核心效果:<code>rgba(10,18,10,.55)</code> 半透明底、<code>rgba(140,180,120,.12)</code> 细边、<code>16px</code> 圆角、<code>blur(16px)</code>、<code>0 8px 40px rgba(0,0,0,.4)</code> 阴影和 hover 边框/背景变亮;输入框、动态图角色面板、Pipeline 胶囊和底部状态条也同步成同一透明体系。</p>
|
||
<p><strong>影响:</strong><code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页改为 Digital Oasis 动态背景</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Canvas</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>用户希望采用下载的 <code>remix-3d-website-the-digital-o</code> 视觉方向;登录页需要更有沉浸感,但不能回到具体产品展示。</p>
|
||
<p><strong>改动:</strong>新增 <code>web/public/oasis-source/index.html</code>,直接复制下载包原始 WebGPU / Three.js 草场源码;<code>web/components/login/oasis-canvas.tsx</code> 改为 iframe 承载这份源码,登录页只做上层文案和表单覆盖。源码页仅用 CSS 隐藏 demo 站自己的导航、文字和设置面板,保留原草场、景深、风动和鼠标交互。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/components/login/oasis-canvas.tsx</code>、<code>web/public/oasis-source/index.html</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页移除产品元素并保留动态模块</h3>
|
||
<span class="tag rose">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>登录页不应该放具体产品图,入口职责是进入内容生产系统,不是展示某个产品。</p>
|
||
<p><strong>改动:</strong>移除登录页产品图、G7/Neck Massager 等产品文案和产品摄影卡,改为抽象流程视觉与旧版入口文案。四个动态几何角色作为独立小组件保留,继续响应鼠标眼神跟随、输入、显示密码、错误和成功状态。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页吸收 skg.com 官网视觉元素</h3>
|
||
<span class="tag rose">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>改动:</strong>参考 skg.com 官网的浅灰产品橱窗、黑白强对比、胶囊按钮、SKG 标识、米白/香槟金健康产品光感,重构生产登录页左侧展示区;角色舞台从纯暗色网格改为官网感浅灰产品展示台,底部模块文案改为 Shop by Need / Recovery / Self-Care 语义。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页角色视觉样式升级</h3>
|
||
<span class="tag rose">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>改动:</strong>在保留四个几何角色结构的基础上,增加底座阴影、发光边、玻璃高光、内部面板和状态点,让角色更像 SKG 内容工作台里的小模块,而不是纯色几何块。</p>
|
||
<p><strong>影响:</strong><code>web/components/login/animated-login-characters.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页角色取消默认上下浮动</h3>
|
||
<span class="tag rose">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>角色舞台默认挂了 <code>login-stage-breathe</code> 无限循环,导致四个角色在登录页一直上下移动。</p>
|
||
<p><strong>改动:</strong>移除默认呼吸动画,角色平时固定贴底;错误态只保留短暂横向抖动,成功态保留一次性反馈动画。</p>
|
||
<p><strong>影响:</strong><code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页角色组件重构</h3>
|
||
<span class="tag rose">UI</span>
|
||
<span class="tag violet">Refactor</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>改动:</strong>新增 <code>web/components/login/animated-login-characters.tsx</code>,把登录页四个角色从 <code>web/app/login/page.tsx</code> 抽成独立组件;角色用配置数组渲染,眼睛、嘴型和黄色 SVG 嘴不再散落在页面主体。动效状态从全页 <code>data-mood</code> 改为挂在角色舞台 <code>login-character-stage</code> 上,样式作用域更清晰。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/components/login/animated-login-characters.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页角色眼神幅度增强</h3>
|
||
<span class="tag rose">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>改动:</strong>放大登录页动画角色的鼠标跟随瞳孔位移,并加大显示密码时眼睛整体看向目标的偏移;同时略微放大白眼球,避免瞳孔大幅移动时显得被裁切。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 登录页动画角色改回风格库原版几何结构</h3>
|
||
<span class="tag rose">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>首版登录页把风格库的动画角色理解成圆润小球,视觉上偏幼稚,和 <code>14 动画角色登录</code> 的原始气质不一致。</p>
|
||
<p><strong>改动:</strong>对照风格库 <code>AnimatedCharacters.vue</code> 和 demo,把角色重写为紫色高矩形、黑色矩形、橙色半圆、黄色圆角柱的贴底几何组合;保留鼠标视线跟随,并让输入、显示密码、错误、成功状态驱动 skew、眼睛和嘴型变化。</p>
|
||
<p><strong>影响:</strong><code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 生产站点增加应用内登录页</h3>
|
||
<span class="tag gray">Runtime</span>
|
||
<span class="tag blue">Security</span>
|
||
<span class="tag rose">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>公司域名部署后任何人知道地址都能打开工作台并调用生成能力。</p>
|
||
<p><strong>改动:</strong>把浏览器 Basic Auth 改为应用内登录页:前端新增 <code>web/app/login/page.tsx</code>,参考风格库 <code>14 动画角色登录</code> 做四个几何角色、鼠标视线跟随、输入 / 显示密码 / 错误 / 成功状态反馈;后端新增 <code>/auth/login</code>、<code>/auth/check</code>、<code>/auth/logout</code>,使用 HttpOnly Cookie + HMAC 会话签名;生产 Nginx 通过 <code>auth_request</code> 保护工作台和 <code>/api/</code>。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/app/login/page.tsx</code>、<code>web/app/globals.css</code>、<code>web/lib/api.ts</code>、<code>docker-compose.prod.yml</code>、<code>deploy/nginx.conf</code>、<code>deploy/.env.production.example</code>、<code>api/.env.example</code>、<code>.project.json</code>、<code>RULES.md</code>、<code>docs/deploy-vps.md</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 公司域名生产部署配置</h3>
|
||
<span class="tag gray">Runtime</span>
|
||
<span class="tag blue">Deploy</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>改动:</strong>把生产入口确定为 <code>https://marketing.skg.com</code>,DNS 已解析到 VPS <code>76.13.31.179</code>。新增 Docker Compose 生产配置:前端用 Next 静态导出 + Nginx,<code>/api/</code> 反代到唯一容器名 <code>skg-marketing-api:4291</code>,避免与 Coolify 网络里其他项目的泛名 <code>api</code> 冲突;后端任务目录持久化到服务器 <code>./data/jobs</code>;Traefik 通过既有 <code>coolify</code> 外部网络接管 80/443。已完成上线验证:HTTPS 首页 200,<code>/api/health</code> 返回 <code>ok:true</code>。</p>
|
||
<p><strong>影响:</strong><code>Dockerfile.web</code>、<code>Dockerfile.api</code>、<code>docker-compose.prod.yml</code>、<code>deploy/nginx.conf</code>、<code>deploy/.env.production.example</code>、<code>docs/deploy-vps.md</code>、<code>.project.json</code>、<code>RULES.md</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-15 · 本地启动改为后台不弹 Terminal</h3>
|
||
<span class="tag gray">Runtime</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>通过 macOS Terminal 启动后端会每次弹出一个终端窗口,打开页面时干扰使用。</p>
|
||
<p><strong>改动:</strong>新增 <code>scripts/start-dev-background.sh</code> 和 <code>scripts/stop-dev-background.sh</code>。启动脚本自动检查前端 4290 和后端 4291,缺哪个后台启动哪个,日志写入 <code>.logs/</code>,PID 写入 <code>.pids/</code>,以后无需通过 <code>osascript</code> 打开 Terminal。</p>
|
||
<p><strong>影响:</strong><code>scripts/start-dev-background.sh</code>、<code>scripts/stop-dev-background.sh</code>、<code>.gitignore</code>、<code>RULES.md</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合按真实产品外置合成</h3>
|
||
<span class="tag orange">产品融合</span>
|
||
<span class="tag blue">Video Gen</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>Seedance 生成时可能把颈部按摩仪当成可变形装饰物,导致产品样式变化、穿进透明身体或与骨架融合。</p>
|
||
<p><strong>改动:</strong>产品融合 prompt 改为英文硬约束:四张 SKG 产品图是真实产品照片和唯一实物真源,生成时按外置刚性设备做 product placement / visual compositing;产品必须停留在透明皮肤外侧,后颈外侧承托、两端沿左右颈侧向前,保留遮挡、接触阴影、透视和真实比例,禁止 x-ray blending、穿模、融进骨架或重绘成其他颈带。</p>
|
||
<p><strong>界面:</strong>产品融合顶部常驻显示桌面四张真实产品角度图,并支持鼠标停留放大查看。每行视频结果不再只显示最新一个,而是按历史持续追加横向结果条,鼠标停留任一结果会放大预览。</p>
|
||
<p><strong>后端:</strong>生视频参考图顺序调整为主参考图之后优先传四张产品图,再传其余人物角色图,提高真实产品外观权重。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<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>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag orange">产品融合</span>
|
||
<span class="tag blue">角色库</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>当前产品融合不再需要手动首帧/尾帧,用户要的是从内置透明骨架人角色、场景描述、产品使用方式和享受状态直接生成视频。</p>
|
||
<p><strong>改动:</strong>桌面 <code>skg_anatomy_characters_20260514_120852</code> 的 5 个角色、35 张图内置为 <code>api/character_library/skg-characters</code>。产品融合页新增角色下拉和角色预览,每行只保留场景/产品使用/享受描述、秒数、生成按钮和结果视频;选择不同角色时,6 行描述会自动改成对应角色的场景气质、产品使用动作和享受状态,并自主写入“本镜头主要参考哪几张角色图、生成什么场景”。生成前自动复制所选角色 7 张参考图和固定 4 张 SKG 产品图到当前 job。</p>
|
||
<p><strong>后端:</strong>新增 <code>GET /character-library/skg</code>、<code>GET /character-library/skg/images/{filename}</code>、<code>POST /jobs/{job_id}/assets/character-library</code>。视频提交新增 <code>subject_images</code>,无首帧时主人物图以 <code>reference_image</code> role 传入 Ark/Seedance,而不是强制作为 <code>first_frame</code>。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/character_library/skg-characters</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合内置多组镜头语言</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag orange">产品融合</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>产品融合不能只写“人物使用产品”,还要稳定控制出场方式、景别、运镜、产品入画、佩戴贴合、使用感受和收尾;同时 SKG 产品是颈部/肩颈按摩仪,比例和佩戴位置不能跑偏。</p>
|
||
<p><strong>改动:</strong>前端内置 36 条产品融合镜头语言模板,6 条为一组,对应建立出场、产品入画、佩戴贴合、使用感受、生活延展和收尾记忆;产品融合页新增“换一组”按钮,只刷新 6 行描述词,不改变已选角色和视频结果。视频 prompt 额外写入颈部/后颈/颈肩使用部位和真实尺寸比例约束。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/app/page.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 音频提取直接生成英文产品口播</h3>
|
||
<span class="tag gray">Audio</span>
|
||
<span class="tag green">MiniMax</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>“提取音频”不能只做原音频转文字再改写,用户需要点击后直接得到介绍 SKG 产品的英文文案和配音,长度尽量贴近原音频,并且声音不能生硬。</p>
|
||
<p><strong>改动:</strong><code>pipeline_transcribe</code> 提取 <code>audio.wav</code> 后读取原音频时长,用该时长估算英文口播词数;<code>_rewrite_audio_script_sync</code> 改为生成自然、有趣、可直接 TTS 的 SKG 英文产品介绍。ASR/翻译保留为对照和节奏参考,ASR 不可用时仍继续生成产品口播。MiniMax voice_id 改为从 <code>MINIMAX_TTS_VOICE_POOL</code> 随机选择男声、女声或成熟声。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env.example</code>、<code>api/README.md</code>、<code>RULES.md</code>、<code>web/components/nodes/index.tsx</code>、<code>web/components/audio-strip.tsx</code>、<code>web/components/dashboard.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合描述词扩成 20 条精准模板</h3>
|
||
<span class="tag orange">产品融合</span>
|
||
<span class="tag blue">Prompt</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>产品融合视频的动作描述不能泛泛写“人物使用产品”,需要稳定表达透明骨架人在具体场景中佩戴 SKG 产品,并呈现舒适享受状态。</p>
|
||
<p><strong>改动:</strong>前端内置 20 条产品使用描述模板,覆盖卧室、客厅、办公、浴室、阳台、影棚、阅读角等场景;当前产品融合页默认把前 6 条预填到 6 行镜头,用户只在需要时直接改每行描述。</p>
|
||
<p><strong>后端:</strong><code>generateProductFusionDescriptions</code> 的兜底模板同步扩为 20 条,LLM 提示也改为生成 20 条 35-70 字描述,要求包含场景、佩戴/展示动作和舒适表情,同时排除医疗治疗承诺。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合改为首尾帧加四产品角度垫图</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag orange">产品融合</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>原产品融合依赖白底人物、手动画区域、场景图和融合引导图,但当前透明骨架人二创流程更需要文字生成首尾帧,再把产品真源作为垫图传给视频模型。</p>
|
||
<p><strong>改动:</strong>“场景图”页签改名为“首尾帧”,右侧用地点、风格、参考要素和 prompt 生成首帧/尾帧,生成后自动填入当前产品融合镜头。产品融合 6 行工作表改为首帧、尾帧、四张同一产品不同角度图、描述词、秒数和生成按钮,并提供桌面四角度填当前镜头/填满 6 镜头。</p>
|
||
<p><strong>后端:</strong><code>generateSceneAsset</code> 新增 <code>asset_role</code>,<code>first_frame/last_frame</code> 走文字生图并标记资产角色;<code>ProductFusionShot</code> 新增 <code>first_image</code>、<code>last_image</code>、<code>product_images</code>,视频提交直接把首尾帧和四张产品图交给 Seedance;产品库新增桌面 <code>skg产品1-4.jpg</code> 四角度条目。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 本地抽帧改为展示友好算力档</h3>
|
||
<span class="tag orange">抽帧</span>
|
||
<span class="tag gray">Audio</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>透明骨架人目标逐帧调用 Vision 验收会拖慢抽帧;切回本机算力后,如果自动档直接跑最高极准,也可能在展示时占满机器资源。</p>
|
||
<p><strong>改动:</strong><code>transparent_human</code> 目标保留,但抽帧阶段只走本地扫描、评分、去重和时间覆盖,不再逐帧调用 Vision。<code>quality=auto</code> 最高只自动选择精细;极准仍保留为手动选项。抽帧开始拆出 <code>audio.wav</code> 后会启动独立音频线程,视觉抽帧和音频处理并行,互不标失败。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 修复 ReactFlow Hydration 和后端 reload 卡住</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">Dev Server</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>刷新页面时 Next 报 Hydration mismatch,ReactFlow 节点服务端默认宽度和客户端 localStorage 里的用户调整宽度不一致;同时提交抖音链接时若后端正在 <code>--reload</code> 等后台任务结束,会出现 4291 端口占用但请求卡住。</p>
|
||
<p><strong>改动:</strong><code>web/app/page.tsx</code> 增加 <code>clientReady</code>,ReactFlow 和底部音频条只在浏览器挂载后渲染,避免服务端 HTML 和客户端本地布局缓存不一致。后端启动说明改为不带 <code>--reload</code> 的稳定命令,并更新 <code>RULES.md</code>、<code>api/README.md</code> 和本页运行入口。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>RULES.md</code>、<code>api/README.md</code>、<code>docs/source-analysis.html</code>。本地 4291 后端已按无 reload 模式重启。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 音频处理改为音频卡片手动触发</h3>
|
||
<span class="tag gray">Audio</span>
|
||
<span class="tag blue">Workflow</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>等待抽帧完成后自动启动音频,不符合“先把声音文案拿出来审核”的工作流;用户需要在音频卡片上直接触发。</p>
|
||
<p><strong>改动:</strong>移除前端抽帧完成后的自动转写逻辑;<code>AudioNode</code> 保留并固定显示“提取音频 / 重新提取音频”按钮,点击音频卡片也会立即打开底部音频条。后端 <code>/transcribe</code> 不再要求 <code>frames_extracted</code>,视频就绪后可直接从 <code>source.mp4</code> 拆出 <code>audio.wav</code>,并按原音频时长生成 SKG 英文产品介绍和 MiniMax 随机英文配音;抽帧中触发时不抢主状态,而是用 <code>audio_script.status</code> 表示音频处理中。当当前网关的 <code>whisper-1</code> audio endpoint 返回 404 时,会 fallback 到 Gemini 多模态音频识别;ASR 不可用时也会继续按原音频时长生成产品口播,不把可用文案标成前端错误。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 新增底部可伸缩音频条</h3>
|
||
<span class="tag gray">Audio</span>
|
||
<span class="tag violet">Timeline</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>音频和文案只在节点或侧栏里展示,审核时缺少“文字和声音时间轴对应”的空间;英文口播和中文翻译也没有上下对齐。</p>
|
||
<p><strong>改动:</strong>新增 <code>web/components/audio-strip.tsx</code>,在主工作台底部吸附显示,可拖拽调整高度、可收起。每个音频段按时间横向排列,上方显示英文,中间显示中文翻译,下方显示对应波形条;底部原音频播放器驱动时间轴,播放时绿色指针会沿全局波形移动,并在当前字幕节点内同步走过该段。右侧显示按原音频时长生成的 SKG 英文产品口播、MiniMax 随机英文配音和产品依据。后端新增 <code>source_audio_url</code> 和 <code>GET /jobs/{id}/audio.wav</code> 只读接口,前端用 Web Audio API 解码生成波形峰值。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/audio-strip.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 音频结果改为改前/改后对照展示</h3>
|
||
<span class="tag gray">Audio</span>
|
||
<span class="tag violet">UI</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>音频识别成功后只显示改写文案,用户看不到它和原音频之间的变化关系,难以判断“是不是把参考视频转成我们自己的话”。</p>
|
||
<p><strong>改动:</strong><code>AudioNode</code> 增加轻量对照摘要:改前显示原音频识别/翻译预览,改后显示 SKG 英文产品口播;侧栏 <code>Rewrite</code> 面板改为完整审核视图,先列原音频逐段 ASR/翻译,再列英文产品介绍稿、产品卖点依据和 MiniMax 英文配音播放器。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>web/components/dashboard.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 多视频工作流状态按 job 隔离</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">Job State</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>同时上传多个视频后,前端把已选关键帧和关键帧详情面板作为全局状态保存;切换 active 视频会清空选中帧,或者让详情面板指向另一个视频的同序号帧,容易误以为生图/自动化被终止或串任务。</p>
|
||
<p><strong>改动:</strong><code>web/app/page.tsx</code> 将 <code>selectedFrames</code> 和 <code>expandedFrame</code> 改为按 <code>jobId</code> 存储。切换视频只改变当前视图,不清空其他视频的选择;重新抽帧、删帧、手动加帧只清理或更新对应 job。异步生图、生视频、产品融合返回后按返回的 <code>job.id</code> 写回 <code>jobs[]</code>,不会落到切换后的 active job。轮询条件也把 <code>audio_script.status=rewriting</code> 纳入运行态,保证音频改写/配音阶段切换视频后仍继续刷新。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>docs/source-analysis.html</code>。后端轮询本来已经覆盖所有运行中的 job,这轮主要修正前端 UI 工作上下文。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 抽帧后台任务不再卡住 API</h3>
|
||
<span class="tag blue">API</span>
|
||
<span class="tag orange">抽帧</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>点击视频抽帧时,后端 4291 端口能连接但 <code>/health</code> 和后续请求长时间不返回,前端看起来像按钮没有反应。</p>
|
||
<p><strong>原因:</strong><code>pipeline_download</code> 和 <code>pipeline_analyze</code> 声明为 async background task,但内部实际是同步 <code>yt-dlp</code>、<code>ffmpeg</code> 和 Vision 验收;Starlette 会在事件循环里执行 async background task,导致长抽帧把 API 主循环堵住。</p>
|
||
<p><strong>改动:</strong>下载和抽帧 pipeline 改为普通同步函数,让 FastAPI/Starlette 按线程池后台任务执行;<code>analyze_queue_worker</code> 也改为同步 worker。服务启动恢复时,如果磁盘里有重启前遗留的 <code>downloading</code>、<code>splitting</code> 或 <code>transcribing</code> 运行态,会恢复成可重试状态,避免按钮一直 disabled。开发运行时改用不带 <code>--reload</code> 的后端命令,避免重载等待后台任务。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>docs/source-analysis.html</code>。已重启本地 4291 后端并验证 <code>/health</code> 立即返回;遗留的 <code>8b37e65521a6</code> job 已恢复为 <code>downloaded</code>,可重新点击抽帧。</p>
|
||
</div>
|
||
</article>
|
||
<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>用户提供 <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> 轮询;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>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 音频处理接入 SKG 英文产品口播与 MiniMax 配音</h3>
|
||
<span class="tag gray">Audio</span>
|
||
<span class="tag green">MiniMax</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>音频处理节点之前只说明“音轨 → ASR → 翻译 → 改写”,没有按原音频时长生成的产品介绍产物,也没有配音输出;用户无法直接拿到符合 SKG 产品语境的英文口播。</p>
|
||
<p><strong>改动:</strong><code>Job</code> 新增 <code>audio_script</code>,<code>pipeline_transcribe</code> 提取 <code>audio.wav</code> 后按原音频秒数生成 SKG 英文产品介绍文案,并在配置 <code>MINIMAX_API_KEY</code> 时调用 MiniMax T2A 输出 <code>/jobs/{id}/audio-script.mp3</code>。MiniMax voice_id 从英文男声、女声、成熟声池随机选择;前端 <code>AudioNode</code> 和侧栏 Rewrite 区显示模型链路、英文产品文案和配音播放器。</p>
|
||
<p><strong>边界:</strong>MiniMax 官方 Speech API 当前接入的是 TTS 配音,不替代 ASR;原始音频文案提取仍走现有 OpenAI-compatible audio transcription 入口。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env.example</code>、<code>api/README.md</code>、<code>web/lib/api.ts</code>、<code>web/components/nodes/index.tsx</code>、<code>web/components/dashboard.tsx</code>、<code>web/app/page.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 默认抽帧张数改为 12 帧</h3>
|
||
<span class="tag violet">InputNode</span>
|
||
<span class="tag blue">抽帧</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>透明骨架人主题需要更稳定的素材覆盖,默认 5 帧太少,容易缺少可用于主体、场景和产品融合的角度。</p>
|
||
<p><strong>改动:</strong>后端 <code>KEYFRAME_COUNT</code> 默认值、前端抽帧 fallback、API client 默认参数都改为 12;抽帧设置里的张数选项把 12 放到第一位。透明骨架人目标仍会对每个候选做 Vision 验收,不合格候选自动换下一帧。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env.example</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 抽帧新增透明骨架人 AI 验收目标</h3>
|
||
<span class="tag violet">InputNode</span>
|
||
<span class="tag blue">Vision</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>透明人二创不能只靠清晰度抽帧,也不能只要出现“骨头”就算合格;需要确认同一人形角色同时具备透明/半透明外壳、干净白色骨架、足够大且清晰、非恐怖广告感。</p>
|
||
<p><strong>改动:</strong><code>FrameExtractTarget</code> 新增 <code>transparent_human</code> 并设为当前 UI 默认目标。后端抽帧先按本地清晰度、中心主体、对比度和去重扩大候选池,再逐张从原视频抽高清帧交给 Vision 评分;评分维度包括透明身体、可见骨架、人物占比、清晰度、商业风格和产品可用性。不合格帧会被删除并自动换下一候选,直到凑够目标张数或候选耗尽。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>web/lib/workflow-target.ts</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 清洗页增加一键替换待应用清洗版</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">清洗</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>一键清洗后会生成多张待应用清洗版,但用户仍需要逐张点“替换原图”,素材准备阶段操作成本偏高。</p>
|
||
<p><strong>改动:</strong>“原图/清洗”页新增“待替换清洗版”状态和“一键替换待应用 N 张”按钮,并显示批量替换进度和失败数。该按钮只应用已经存在的清洗结果,不重新清洗;不满意的帧仍可先单张重洗或丢弃。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合收敛为首尾帧 + 固定四产品图</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag orange">产品融合</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>产品融合页继续显示产品角度槽、辅助栏和产品图库会把操作变复杂;当前工作流只需要用户手动补人物首尾帧,产品图固定来自桌面 4 张 SKG 图。</p>
|
||
<p><strong>改动:</strong>“产品融合”页每行只保留首帧、尾帧、已预填描述词、秒数、生成按钮和行末视频结果。生成单条或批量视频前,前端自动把内置的 4 张桌面 SKG 产品图复制为当前 job asset 并写入 <code>product_images[4]</code>;视频 prompt 增加 <code>产品融合镜头ID</code> 标记,用来把生成结果显示回对应行。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>web/components/dashboard.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合镜头组改为纵向 6 行工作表</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag orange">产品融合</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>产品融合要生成 6 条视频,但旧排版只在列表里显示摘要,真正编辑区只展开当前镜头,用户无法从上到下同时检查 6 条镜头的产品、人物、场景和描述是否一一对应。</p>
|
||
<p><strong>改动:</strong>“产品融合”页左侧改为纵向 6 行镜头工作表。每行包含产品图槽、白底人物图槽、人物图内产品区域画框、场景图槽、动作描述、秒数选择和单条生成按钮;右侧只保留模型状态、当前镜头状态、AI 草拟 6 条、批量排队和当前镜头产品图库。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合改为 6 行区域约束镜头组</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag orange">Seedance</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>只把产品图作为参考图无法解决尺寸和位置融合,模型不知道产品应该放在人物或场景里的哪个区域。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 的“产品融合”页改为 6 行镜头组。每行绑定产品图、白底人物图、手动画出的产品区域、场景图、描述词和视频秒数;图片槽支持上传和粘贴,产品图也可从内置 SKG 白底图库选用。右侧固定显示图片模型 <code>GPT Image 2</code> 和视频模型 <code>Seedance</code>,支持 AI 草拟 6 条动作描述和批量排队;单条生成入口放在每一行镜头内。</p>
|
||
<p><strong>后端:</strong>新增 <code>POST /jobs/{job_id}/product-fusion/guide</code> 和 <code>POST /jobs/{job_id}/product-fusion/descriptions</code>。前者把产品图按 <code>product_region</code> 合成到白底人物图上,生成普通 <code>asset</code> 引导图;后者用 LLM 或本地模板生成 6 条动作描述草稿。前端再把引导图作为 Seedance 首帧,并把产品图、人物图、场景图作为参考图提交。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>web/components/dashboard.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 产品融合槽位接入应用内剪贴板</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">Clipboard</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>卡片上的“复制”写入的是应用内 <code>ImageRef</code> 剪贴板,而产品融合槽位只监听系统剪贴板文件,导致复制后的素材无法在产品融合里粘贴。</p>
|
||
<p><strong>改动:</strong><code>NodeData</code> 和 <code>FrameLightbox</code> 新增 <code>clipboard</code> 传递链路;产品融合三类槽位的“粘贴”按钮优先使用应用内剪贴板,应用剪贴板为空时再提示可选中槽位后 Cmd+V 粘贴系统图片。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>web/components/dashboard.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 增加产品融合和 SKG 内置白底图库</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag orange">产品融合</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>生成视频需要稳定的 SKG 产品真源,不能每次都依赖临时上传或从参考视频里找产品图;桌面已有整理过的 SKG 产品图,应作为内置数据库使用。</p>
|
||
<p><strong>改动:</strong>从桌面 <code>skg_product_downloads/all_products</code> 的 gallery 中筛出 41 张白底产品图,生成 <code>api/product_library/skg-products/manifest.json</code> 和压缩预览图。<code>FrameLightbox</code> 新增“产品融合”页签,<code>StoryboardWorkbench</code> 的 SKG 产品参考区也接入同一个 <code>ProductLibraryPicker</code>,支持搜索、品类筛选、尺寸预览和一键加入。</p>
|
||
<p><strong>后端:</strong>新增 <code>GET /product-library/skg</code>、<code>GET /product-library/skg/images/{filename}</code> 和 <code>POST /jobs/{job_id}/assets/product-library</code>。选中库内产品图时,后端会复制成当前 job 的 <code>asset</code>,后续仍通过既有 <code>product_images</code> 进入生视频接口。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/product_library/skg-products</code>、<code>web/lib/api.ts</code>、<code>web/components/product-library-picker.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>web/components/storyboard-workbench.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 场景图改为全图参考和关键词 Prompt</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">Prompt</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>场景图页不能只围绕当前单张图;它需要看到全部关键帧,并通过地点、风格、参考要素等关键词组合出可控 prompt,再生成场景。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 的“场景图”页左侧改为全部关键帧网格:点击图片设为生成目标,点击“选”加入场景参考。右侧新增地点、生成方式、风格、额外关键词和参考要素 chips,并自动拼出可编辑场景 prompt。</p>
|
||
<p><strong>后端:</strong><code>generateSceneAsset</code> 请求新增 <code>prompt</code> 和 <code>source_frame_indices</code>;多张参考帧会拼成 contact sheet 给图像模型,同时把用户 prompt 注入场景生成提示词。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 主体资产改为参考重绘六张标准图</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">Assets</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>主体资产不是抠图,也不是只看当前单帧生成多角度;主体页需要看到全部参考帧,并用这些参考重新绘制一个完整主体。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 在“主体资产”页左侧显示参考帧网格,优先纳入所有已清洗帧,额外已选帧也会并入;小图排列,可点击切换当前帧。右侧仍负责统一主体确认和生成。人物/生物默认视图改为六张身份标准图:正面、背面、左侧、右侧、左前 45°、右前 45°;并把表情补充和动作补充折成独立分组,需要时再勾选。</p>
|
||
<p><strong>后端:</strong><code>generateSubjectAssets</code> prompt 改为“参考重绘”,明确禁止裁剪/抠图/粘贴源像素,要求主体完整居中、纯白/黑背景、无其他元素,并占画面约 85-95% 高度;落盘时会裁掉纯背景空白并放大主体。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 主体资产改为统一主体参考帧生成</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">Workflow</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>当前流程里抽多张关键帧的目的不是让每张图各自生成一个主体,也不是从单张图硬造多角度,而是用多张关键帧共同还原同一个主体的多角度、动作和表情。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 的主体页改成“统一主体”逻辑:全局只保留一个主体候选;生成主体资产包时默认传全部关键帧作为 <code>source_frame_indices</code>,用户手动选择关键帧时只传已选帧。场景图仍然按当前关键帧逐张生成,因此是一个主体包 + 多个场景图。</p>
|
||
<p><strong>后端:</strong><code>generateSceneAsset</code> 查找主体名称时改为从整个 job 的已生成主体资产中读取,而不是只看当前帧,确保任意关键帧生成场景图时都能移除统一主体。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 场景图改为主体资产之后生成</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>场景图如果先于主体资产生成,只能做普通背景清理,无法准确知道要移除哪个主体,也不利于后续生成相似但不同或同构换风格的场景。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 页签顺序改为“原图/清洗 → 主体资产 → 场景图 → 审核”;画面工作台缩略图和进度文案也同步为主体资产先于场景图。场景图页新增“去主体原场景 / 相似新场景 / 同构换风格”和风格选择,且在没有主体资产时提示先生成主体资产。</p>
|
||
<p><strong>后端:</strong><code>generateSceneAsset</code> 请求新增 <code>scene_mode</code> 和 <code>scene_style</code>;后端提示词会优先读取已生成主体资产对应的主体名称,生成去主体并补背景的场景图,再按模式决定是否做相似变化或风格变化。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 关键帧素材面板统一右侧操作栏</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">Layout</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>“原图/清洗、主体资产、场景图、审核”都应遵循同一结构:左侧负责看图和框选,右侧负责操作、状态和结果;旧布局把部分操作塞在左侧下方,导致左侧满、右侧空。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 统一为左侧主图、右侧操作栏。清洗按钮、批量清洗、清洗结果预览、场景图生成/复制、主体识别/主体资产包和审核状态都在右侧;切换到非清洗页时会退出框选模式,避免画框状态残留。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 单帧清洗不再全局锁住其他帧</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">Bugfix</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>单独清洗某一张关键帧时,前端使用全局 <code>cleaning</code> 布尔状态,导致切到其他关键帧后清洗按钮仍被禁用。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 改用 <code>cleaningFrameIds</code> 按 <code>frame.index</code> 记录正在清洗的帧,只禁用当前正在清洗的那一张;其他帧可以继续单独清洗。区域清洗完成时也只在用户仍停留于同一帧时清空当前框选,避免异步完成误清别的帧操作状态。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 清洗页支持一键批量清洗</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">UX</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>画面工作台里的关键帧已经在抽帧阶段筛过,逐张点“清洗水印”会拖慢素材准备;但自动清洗又不能直接覆盖原图,否则模型误改时不好回退。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 的“原图/清洗”页新增“批量清洗”卡片,一键顺序清洗所有未处理素材帧,并显示进度和失败数。批量清洗只生成 <code>cleaned</code> 待审核版本,不自动应用;没清干净的帧再用单帧框选区域做手工补洗。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。后端暂未新增 batch API,前端复用 <code>POST /jobs/{id}/frames/{idx}/cleanup</code> 顺序执行。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 关键帧详情改为素材准备面板</h3>
|
||
<span class="tag violet">FrameLightbox</span>
|
||
<span class="tag blue">UX</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>面板标题仍叫“关键帧详情 · 元素提取”,里面还露出普通 cutout 抠图、AI 提取、元素清单等旧流程入口;“选用此帧 / 加入目标帧”也无法说明实际价值,因为抽帧阶段已经筛过图,进入画面工作台的关键帧默认就应该参与素材准备。</p>
|
||
<p><strong>改动:</strong><code>KeyframePanelNode</code> 标题改为“关键帧素材准备”;<code>FrameLightbox</code> 的主体页改成“主体识别 / 主体清单 / 主体资产包”,移除普通抠图列表、AI 提取按钮、详情内的目标帧开关以及手动/框选加主体入口,改为只显示“已在素材准备流程”的状态说明;<code>VisualLabNode</code> 上方缩略图也不再展示普通抠图分组,只展示关键帧、主体包、场景图和视频任务。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。底层旧 cutout 数据和接口暂保留兼容历史任务,但不再作为新素材准备流程的可见入口。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 画面工作台改为素材准备看板</h3>
|
||
<span class="tag violet">Visual Lab</span>
|
||
<span class="tag blue">UX</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>画面工作台从展示缩略图扩展为素材生产中枢后,关键帧、主体资产包、场景图和视频任务继续混在一个列表里会让流程不清晰;关键帧详情面板也把清洗、识别、主体生成和场景生成都堆在一屏。</p>
|
||
<p><strong>改动:</strong><code>VisualLabNode</code> 改成素材准备进度看板,显示关键帧素材、主体资产、场景图和分镜/视频四个入口。<code>FrameLightbox</code> 新增“原图/清洗、主体资产、场景图、审核”四个页签,素材审核信息从普通列表中拆出来。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>web/components/lightbox.tsx</code>、<code>docs/source-analysis.html</code>。这轮只重排工作台信息架构,批量自动准备队列仍留到下一阶段。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 画面工作台增加主体资产包和场景图</h3>
|
||
<span class="tag violet">Visual Lab</span>
|
||
<span class="tag blue">Assets</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>抽帧阶段已经筛过图,画面工作台第一步应把已选关键帧转成可用于生视频的干净素材:同一主体一套多视角/动作/表情图,再基于主体生成每帧去主体场景图,而不是继续手动逐张抠普通 cutout。</p>
|
||
<p><strong>改动:</strong><code>KeyFrame</code> 新增 <code>scene_assets</code> 和 <code>quality_report</code>;<code>KeyElement</code> 新增 <code>subject_kind</code> 与 <code>subject_assets</code>。后端新增 <code>generateSubjectAssets</code> 和 <code>generateSceneAsset</code>,主体资产支持白/黑背景、原尺寸/固定尺寸、物体视角、人物/生物动作与喜怒哀乐等表情;当已选关键帧共同指向一个主体时,前端会把这些帧作为 <code>source_frame_indices</code> 传入,后端拼接参考板。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/components/lightbox.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。生成出的素材保存在 <code>jobs/<jobId>/assets</code>,可作为 <code>asset</code> 类型复制到后续分镜槽位。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 抽帧精度自动选择并支持后端排队</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">Queue</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>抽帧精度不应该每次都让用户判断;点击一个视频抽帧后,其他视频不应被全局禁用,而应该可以先后排队。另外打开视频抽帧侧边面板后,也应能自动抽帧。</p>
|
||
<p><strong>改动:</strong><code>quality</code> 新增 <code>auto</code> 默认值,后端按 CPU 核数、内存和视频时长解析为快速或精细;为了展示稳定,auto 不再自动进入极准,极准仅在用户手动选择时启用。后端新增内存队列 <code>ANALYZE_QUEUE</code>,多个 <code>analyze</code> 请求按顺序执行;前端轮询所有运行中的 job,不只轮询当前 active job。<code>VideoFramePanelNode</code> 内也加入同一套自动抽帧工具条。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。队列目前是进程内队列,重启后不会恢复未执行的排队任务。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 抽帧工具条降噪并修复追加失败</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">Bugfix</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>每个缩略图上方同时放目标、张数、精度和按钮太拥挤;另外追加抽帧时可能没有新增图片。</p>
|
||
<p><strong>根因:</strong>追加模式下 <code>frames</code> 目录已经存在,但后端仍使用非 <code>exist_ok</code> 的 <code>mkdir</code>,触发 <code>File exists</code> 后任务进入解析失败。</p>
|
||
<p><strong>改动:</strong>工具条默认只显示目标、抽帧/追加和设置按钮;张数、精度折叠到设置里。后端改为允许已存在的 <code>frames</code> 目录,追加模式不再因目录存在失败。缩略图高度增大到 192px,横屏/竖屏都按真实比例显示;抽帧评分也按视频原比例缩放,不固定 16:9。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。已用临时 job 验证 append:已有 1 张关键帧时追加 3 张后变为 4 张。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 自动抽帧增加本地精度模式</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">Performance</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>当前抽帧默认偏轻量,用户机器是 Apple M2 Max、12 核 CPU、38 核 GPU、64GB 内存,足以承受更密集的本地候选扫描;但需要在 UI 里提示算力档位,避免长视频误用重模式。</p>
|
||
<p><strong>改动:</strong>后端 <code>/jobs/{id}/analyze</code> 新增 <code>quality</code> 参数:快速为 2fps/360px,精细为 8fps/720px,极准为 12fps/960px;高精度模式还会提高本地评分图分辨率,保留竖屏比例,不再把竖屏压扁到 16:9。每个缩略图工具条新增精度选择。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。实测本机 64.5s、1080×1920、60fps 视频,12fps/960px 扫描 774 张候选约 2.61s;重型 ffmpeg 场景/模糊滤镜约 21.63s,因此继续使用本地 PIL/NumPy 评分更划算。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 每个输入视频缩略图绑定自己的抽帧工具条</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">UX</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>统一放在缩略图浮条上方的抽帧工具条仍然不够明确,用户无法一眼判断当前会抽哪一个视频。</p>
|
||
<p><strong>改动:</strong>抽帧目标、张数、精度和抽帧按钮改为渲染在每个视频缩略图正上方,并且每个 job 独立保存目标、张数和精度设置。点击某个缩略图上方的抽帧按钮时,前端直接把该 <code>jobId</code> 传给 <code>analyzeJob</code>,同时切换 active job 并进入该 job 的进度轮询。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。后续与输入视频相关的快捷操作都应优先贴近对应缩略图,不再依赖全局当前选择的心智。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 自动抽帧快捷工具条移到缩略图上方</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">Frame Target</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>自动抽帧入口放在 Input 卡片正文里,离视频缩略图和预览工作区较远;用户需要在看缩略图时快速切目标、切张数并反复抽取。</p>
|
||
<p><strong>改动:</strong>输入视频缩略图浮条上方新增自动抽帧快捷工具条,包含抽帧目标、张数快捷项和抽帧按钮。前端新增 <code>frameCount</code> 状态并把目标 / 张数传给 <code>analyzeJob</code>;已有关键帧时默认用 <code>mode=append</code> 追加抽取。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。后端追加模式会保留已有关键帧,避开非常接近的时间点,并用新的 frame index 落盘。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 自动抽帧支持目标化扫描</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">Frame Target</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>单一“自动抽帧”无法表达这次要清晰人物、下次要转场变化或表情瞬间的不同目标;但把抽帧做成复杂参数面板会破坏 Input 卡片的轻量工作流。</p>
|
||
<p><strong>改动:</strong>Input 节点新增抽帧目标,默认“综合关键帧”,可切换清晰主体、转场变化、表情瞬间、动作峰值。后端 <code>/jobs/{id}/analyze</code> 新增 <code>target</code> 参数,先低清低帧率扫描候选,再按目标评分、pHash 去重、时序分桶,最后只对选中的时间点从原视频抽高质量关键帧。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。当前“人物/动物表情”是本地近似评分,后续可把候选小图接入视觉模型重排。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 视频抽帧面板默认静音播放</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">Video</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>输入视频缩略图改为单击打开抽帧面板后,面板播放器如果自动播放带声音,会打断工作流。</p>
|
||
<p><strong>改动:</strong><code>VideoFramePanelNode</code> 的主播放器增加 <code>muted</code>,默认静音自动播放;用户仍可通过浏览器视频 controls 自行取消静音。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · Canvas Panel 颜色跟随来源卡片且视频单击打开</h3>
|
||
<span class="tag violet">Canvas Panel</span>
|
||
<span class="tag blue">UX</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>视频抽帧面板和画面工作台详情面板框架一致后,标题栏颜色也需要分别跟各自来源卡片一致;输入视频缩略图仍需要双击才能打开抽帧面板,操作偏重。</p>
|
||
<p><strong>改动:</strong>视频抽帧面板标题栏使用 <code>--grad-input</code>,画面工作台详情面板标题栏使用 <code>--grad-ai</code>;输入视频缩略图改为单击打开抽帧面板,hover 仍负责尺寸预览。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。后续面板颜色应从来源卡片类型继承。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 画面工作台详情面板统一为 Canvas Panel 框架</h3>
|
||
<span class="tag violet">Visual Lab</span>
|
||
<span class="tag blue">Canvas Panel</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>关键帧详情 / 元素提取面板虽然默认左侧吸附,但外层仍是旧橙色“钉住”框架,和视频抽帧面板的紫色标题栏、画布/左/右/底吸附按钮不一致。</p>
|
||
<p><strong>改动:</strong><code>KeyframePanelNode</code> 改为和 <code>VideoFramePanelNode</code> 同一套 Canvas Panel 外壳:紫色标题栏、画布模式、吸附左侧、吸附右侧、吸附底部、缩放、关闭和右下角拖拽缩放。面板定位状态从单一 <code>pinned</code> 语义升级为 <code>framePanelDock</code>。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。后续工作面板应复用这套 Canvas Panel 框架。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 关键帧详情嵌入态去掉双标题栏</h3>
|
||
<span class="tag violet">Visual Lab</span>
|
||
<span class="tag blue">FrameLightbox</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>画面工作台详情面板外层已有“关键帧详情 · 元素提取”工具栏,内层 <code>FrameLightbox</code> 嵌入态又显示一条橙红分镜导航栏,视觉上像两个窗口叠在一起。</p>
|
||
<p><strong>改动:</strong><code>FrameLightbox</code> 在 <code>embedded</code> 模式下不再渲染自己的顶部工具栏和外边框;上一帧 / 下一帧导航移动到 <code>KeyframePanelNode</code> 外层标题栏。</p>
|
||
<p><strong>影响:</strong><code>web/components/lightbox.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。非嵌入式 lightbox 保留原标题栏。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 画面工作台详情面板默认左侧吸附</h3>
|
||
<span class="tag violet">Visual Lab</span>
|
||
<span class="tag blue">Dock</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>画面工作台点击关键帧后,关键帧详情 / 元素提取面板仍默认作为画布节点出现,还会触发 <code>fitView</code> 拉动画布;和视频抽帧面板默认左侧吸附的规则不一致。</p>
|
||
<p><strong>改动:</strong><code>framePanelDock</code> 初始值改为 <code>left</code>;从关闭状态打开关键帧详情时默认吸附左侧。若面板已打开,用户切回画布模式后继续切换关键帧,不会被强制吸回左侧;默认吸附状态下也不再触发画布 <code>fitView</code>。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>docs/source-analysis.html</code>。画面工作台处理面板现在与视频抽帧面板保持同一默认策略:先贴左侧,需要时再切回画布。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 视频抽帧面板默认左侧吸附</h3>
|
||
<span class="tag violet">Canvas Panel</span>
|
||
<span class="tag blue">Dock</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>视频抽帧面板默认以画布节点方式打开时,用户还要再点一次吸附左侧,和“处理面板先贴边、需要时再拖回画布”的工作习惯不一致。</p>
|
||
<p><strong>改动:</strong><code>videoPanelDock</code> 初始值改为 <code>left</code>;从关闭状态双击输入视频缩略图时默认吸附左侧。面板已打开后,用户手动切换到画布 / 右侧 / 底部不会被找回动作覆盖。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>docs/source-analysis.html</code>。后续同类处理面板应优先考虑“默认贴边,必要时切回画布”的交互。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 视频抽帧面板支持删除已抽关键帧</h3>
|
||
<span class="tag violet">Canvas Panel</span>
|
||
<span class="tag blue">Frames</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>视频抽帧面板只能新增关键帧,用户看到“已抽关键帧”后不能在同一工作上下文里清理误抽的帧。</p>
|
||
<p><strong>改动:</strong>已抽关键帧缩略图右上角增加删除按钮,点击后按 <code>jobId + frameIdx</code> 删除对应关键帧;删除期间显示小号 loading。图片类素材仍沿用快速删除策略,不弹确认。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。视频抽帧面板不再依赖当前 active job 来决定删除目标。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 吸附工作面板贴近视口边缘</h3>
|
||
<span class="tag violet">Canvas Panel</span>
|
||
<span class="tag blue">Dock</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>视频抽帧面板吸附左侧 / 右侧时顶部仍留出明显空白;这不是实际板块遮挡,而是面板吸附样式里硬编码了 <code>top: 72</code> 和对应的高度预留。关键帧面板也保留了旧 storyboard 顶栏避让逻辑。</p>
|
||
<p><strong>改动:</strong>新增统一吸附边距常量,视频抽帧面板和关键帧详情面板吸附时都贴近视口边缘,仅保留 8px 安全边距;移除关键帧面板对旧 <code>data-storyboard-dock</code> / <code>data-storyboard-bar</code> 的避让查询。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。后续画布工作面板的吸附语义统一为“贴边”,不是为顶部旧板块预留空间。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 输入视频双击改为画布抽帧面板</h3>
|
||
<span class="tag violet">Canvas Panel</span>
|
||
<span class="tag blue">Input</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>输入视频缩略图双击原来只在 Input 节点上方展开一个临时播放器,不能作为无限画布工作台移动、找回或吸附,后续其他板块也无法复用这种交互。</p>
|
||
<p><strong>改动:</strong>新增 <code>videoFramePanel</code> ReactFlow 节点和 <code>VideoFramePanelNode</code>。双击输入视频缩略图会打开/找回画布内抽帧面板,面板可拖动、右下角缩放,也可一键吸附到左侧、右侧或底部边缘;面板内支持播放、时间轴定位、当前时间抽帧和查看已抽关键帧。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。原固定全屏 <code>VideoLightbox</code> 不再从 Input 双击路径进入;后续处理板块应复用同类画布工作面板语义。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · Hover 大预览尺寸信息增强</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">HoverPreview</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>原始尺寸和 Fit 比例之前是左上角小号单行文字,用户在快速扫缩略图时不够醒目,无法马上感知素材分辨率差异。</p>
|
||
<p><strong>改动:</strong><code>HoverPreview</code> 左上角改为两层信息徽章:标题固定为“原始尺寸”,主数字用大号等宽字体显示 <code>宽 × 高</code>,旁边保留 <code>Fit</code> 百分比或 <code>1:1 原寸</code> 状态。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/hover-preview.tsx</code>、<code>docs/source-analysis.html</code>。定位和 Fit / 1:1 行为不变,只提升尺寸信息可读性。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 删除确认改为页面内分层交互</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">UX</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>浏览器原生删除确认会突然出现在页面顶部,和无限画布的操作上下文割裂;图片类素材如果每次删除都确认,也会拖慢快速整理素材的节奏。</p>
|
||
<p><strong>改动:</strong>输入视频和生成视频任务删除改为画布内确认层,背景轻遮罩并支持点击背景 / Esc 取消;关键帧和元素提取图属于可快速整理的图片素材,点击删除后直接执行。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。视频删除仍走既有删除接口;图片删除仍走原有回调,只调整确认策略。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 输入视频缩略图支持删除整个 job</h3>
|
||
<span class="tag violet">Input</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>画布顶部输入视频缩略图只有切换和预览,没有删除入口;用户清理视频队列时只能删关键帧或生成视频任务,不能删除整个输入视频。</p>
|
||
<p><strong>改动:</strong>新增 <code>DELETE /jobs/{id}</code>,前端新增 <code>deleteJob</code> 和 <code>onDeleteJob</code>;Input 缩略图右上角常驻删除按钮,确认后移除该 job、清理 URL 参数,并删除本地 <code>jobs/<id></code> 目录。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>web/lib/api.ts</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 大图预览改为尺寸感知 Fit / 1:1</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">HoverPreview</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>有些源视频和图片分辨率很大,完全按原尺寸展示会撑爆画布;但统一固定预览大小又会丢失素材真实尺寸感知。</p>
|
||
<p><strong>改动:</strong><code>HoverPreview</code> 默认按原比例适应可视区域,角标显示原始分辨率和当前 Fit 百分比;点击钉住后可切换到 <code>1:1</code>,超大素材在预览框内滚动查看局部。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/hover-preview.tsx</code>。视觉缩略图高度同步放大,图片缩略图的复制 / 删除按钮改为常驻大号 icon。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 缩略图滑动条改为大号可拖轨道</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">Thumbnail</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>节点上方缩略图横排内容多时,原生横向滚动条太细且在画布缩放下不容易点中,用户很难拖动。</p>
|
||
<p><strong>改动:</strong>新增 <code>FloatingThumbnailStrip</code> / <code>ThumbnailScrollRail</code>,在缩略图下方显示明显的大号紫色拖动轨道;轨道支持点击跳转、按住拖动和键盘左右移动,并用 <code>nodrag nopan</code> 避免误触发画布拖拽。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>web/app/globals.css</code>、<code>docs/source-analysis.html</code>。Input、VisualLab 以及保留的旧视觉节点缩略图条共用同一交互。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 三个视觉节点合并为画面工作台</h3>
|
||
<span class="tag violet">VisualLab</span>
|
||
<span class="tag blue">Canvas</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>镜头拆解、元素改造、生成视频三个卡片在主画布上占同等权重,但它们只是视觉素材状态展示和入口;真正处理都在点击后的工作台/面板中完成。</p>
|
||
<p><strong>改动:</strong>新增 <code>VisualLabNode</code>,把关键帧、元素 cutout、视频任务缩略图合并到一个“画面工作台 · Visual Lab”卡片里;DAG 从 <code>Input → Keyframe → Storyboard → VideoGen → Compose</code> 简化为 <code>Input → VisualLab → Compose</code>,音频线仍独立。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。底层数据、接口和旧节点组件暂不删除。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 修复节点右下角缩放点击偏移</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">Resize</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>点击或轻微拖动卡片右下角缩放把手时,节点会突然偏移/跳变,影响在无限画布上精调卡片大小。</p>
|
||
<p><strong>原因:</strong><code>getComputedStyle(nodeEl).width/height</code> 读到的已经是 ReactFlow 节点坐标下的布局尺寸,旧逻辑又除了一次 <code>zoom</code>,导致拖动起始宽高被放大或缩小;点击时 1px 级 pointermove 也会立刻写入错误宽高。</p>
|
||
<p><strong>改动:</strong>起始宽高直接使用 computed style,只有鼠标移动量按 zoom 换算;增加 2px 点击死区,单纯点击缩放角不再改写节点尺寸。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/resize-handle.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-14 · 缩略图 hover 原尺寸预览贴缩略图上边缘</h3>
|
||
<span class="tag violet">Canvas</span>
|
||
<span class="tag blue">HoverPreview</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>用户要的是“鼠标停在卡片缩略图上时,原尺寸图片/视频在该缩略图上方边缘展示,并且仍属于无限画布”;不能贴节点卡片上边缘,也不能放到页面 fixed 层。</p>
|
||
<p><strong>改动:</strong><code>HoverPreview</code> 增加缩略图锚点坐标,预览层仍渲染在 ReactFlow 节点 DOM 内,但用缩略图的中心 x 和 top y 定位,预览底边贴缩略图上边缘;Input 视频、镜头拆解关键帧、元素改造 cutout、生成视频缩略图统一走该逻辑。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/hover-preview.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 打开应用自动恢复历史 job</h3>
|
||
<span class="tag blue">API</span>
|
||
<span class="tag violet">Page</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>前端只从 URL <code>?job=</code> 读 job 列表,没有任何本地或后端列表回填,打开 <code>/</code> 不带参数就是空白,之前跑过的 job 看不见。</p>
|
||
<p><strong>改动:</strong>后端新增 <code>GET /jobs</code> 列表接口(返回 <code>JobSummary</code>:id/url/status/progress/duration/width/height/video_url/frame_count/video_count/thumbnail/error/mtime,按 state.json mtime 倒序,可带 <code>limit</code>)。前端 <code>page.tsx</code> 启动逻辑:URL 有 <code>?job=</code> 时尊重 URL;没有时自动调 <code>listJobs()</code> 拿全部历史,反转后让最新 job 落在末尾(active)。持久化基于 <code>api/jobs/<id>/state.json</code> 磁盘文件,不依赖浏览器存储,换浏览器/清缓存都不会傻。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>(<code>JobSummary</code> 类型 + <code>list_jobs</code> endpoint)、<code>web/lib/api.ts</code>(<code>JobSummary</code> + <code>listJobs</code>)、<code>web/app/page.tsx</code>(启动 useEffect)。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 允许骨骼人使用按摩仪后状态变好</h3>
|
||
<span class="tag blue">Prompt</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>本轮参考素材的主体可能是人形骷髅/透明骨骼人,不应被提示词强行替换成普通真人;核心是“用了 SKG 颈部按摩仪后状态变好”。</p>
|
||
<p><strong>改动:</strong>prompt 允许保留人形骷髅作为视觉隐喻,要求正确佩戴 U 形颈部按摩仪,并通过从僵硬/揉脖子/疲惫到抬头/肩颈舒展/放松来表现状态改善;同时禁止恐怖化、血腥化或夸大医疗治愈。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 生视频提示词改为产品图优先</h3>
|
||
<span class="tag blue">Prompt</span>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>已经有真实 SKG 产品图后,提示词还偏“借鉴原视频”,容易让模型保留竞品或改变产品形态。</p>
|
||
<p><strong>改动:</strong>生成视频 prompt 明确“上传的 SKG 产品图是唯一产品真源”,首尾帧只控制起止构图、场景和动作,原视频链接只参考节奏和镜头调度;增加产品一致性、产品呈现、禁止非 SKG 产品/竞品包装/随机新增结构等约束。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 产品参考支持本地上传和拖拽</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>SKG 产品参考不能只依赖从关键帧/元素里复制,用户需要手动上传同一产品的多角度图。</p>
|
||
<p><strong>改动:</strong><code>SKG 产品参考</code> 区支持点击上传和拖拽上传图片,一次可传多张,最多保留 6 张。后端新增 <code>POST /jobs/{job_id}/assets</code> 保存产品图资产,并返回 <code>kind: "asset"</code> 的 <code>ImageRef</code>;生成视频时这些资产会作为产品参考传入 Ark。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-workbench.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 首尾帧编排增加 SKG 产品槽</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>首尾帧可以控制视频起止,但还需要单独指定 SKG 产品图,避免模型只模仿原视频动作而没有稳定产品外观。</p>
|
||
<p><strong>改动:</strong>分镜编排区新增 <code>SKG 产品</code> 槽,和首帧、尾帧并列;生成视频时把该槽作为 <code>product_image</code> 提交。Ark 请求会附加一张 <code>reference_image</code> 产品参考图;如果接口不接受额外参考图,后端自动回退到首尾帧生成。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-workbench.tsx</code>、<code>web/app/page.tsx</code>、<code>api/main.py</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 分镜编排改为首尾帧生成</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>赶交付时,顶部横向分镜缩略条占空间,4 图槽也不如“首帧到尾帧”直接;用户希望直接做首尾帧视频生成。</p>
|
||
<p><strong>改动:</strong>移除 <code>StoryboardBar</code> 的横向分镜缩略图区域,只保留标题栏和展开按钮;<code>StoryboardWorkbench</code> 改成首帧 / 尾帧两个槽,首帧默认当前分镜,尾帧默认下一张已选分镜,也可从剪贴板粘贴指定结束画面。后端 <code>/storyboard/video</code> 支持 <code>first_image</code>/<code>last_image</code>,Ark 请求同时传 <code>first_frame</code>/<code>last_frame</code>,如果接口不接受尾帧字段则自动回退到单首帧。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-bar.tsx</code>、<code>web/components/storyboard-workbench.tsx</code>、<code>web/app/page.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 生视频携带原视频链接做节奏参考</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>用户赶交付,希望直接把上传的原视频链接给视频模型参考,而不是只靠单张关键帧。</p>
|
||
<p><strong>改动:</strong>前端提交生视频时增加 <code>source_ref: { kind: "source_video", url: job.url }</code>;Ark 请求体在文本 prompt 和首帧之外追加 <code>video_url</code> 参考视频,用于模仿节奏、镜头运动和动作顺序。如果 Ark 返回 400/422 不接受参考视频字段,后端自动回退到“当前关键帧首帧生成”,保证这次不会直接阻断出片。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>、<code>docs/source-analysis.html</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 快速出片改为关键帧直生视频</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag blue">Prompt</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>赶交付时不适合再让 4 图槽决定首帧;如果某个槽里是抠图元素,模型会拿碎元素当第一帧,视频容易不连贯。</p>
|
||
<p><strong>改动:</strong>“生成视频”按钮改成直接用当前分镜关键帧作为首帧提交,4 图槽和改造目标只作为提示词参考;提示词强调一镜到底、首帧稳定、时间线连续、禁止跳切/换场景/主体变形。后端取关键帧时优先使用未应用的清洗版,否则使用当前 frame 文件。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/storyboard-workbench.tsx</code>、<code>api/main.py</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 生视频支持火山方舟 Ark 异步任务</h3>
|
||
<span class="tag rose">VideoGenNode</span>
|
||
<span class="tag blue">API</span>
|
||
</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>,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>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 生视频改接 Poe 视频模型</h3>
|
||
<span class="tag rose">VideoGenNode</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>SKG ezlink 的 OpenAI 兼容 base 可列出部分模型,但常规 <code>/videos</code> 入口返回 404/unsupported;用户确认可用的视频模型在 Poe 通道里。</p>
|
||
<p><strong>改动:</strong>后端新增 <code>POE_API_BASE_URL</code>/<code>POE_API_KEY</code> 配置,未显式配置 <code>VIDEO_API_BASE_URL</code> 时优先走 Poe;Seedance / Kling / Veo/Voe 业务别名默认映射到 Poe 真实模型 <code>seedance-2-fast</code>、<code>kling-omni</code>、<code>veo-3.1-fast</code>。Poe 提交使用 <code>input_image</code> base64,继续轮询 <code>/videos/{id}</code> 并下载 <code>/videos/{id}/content</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>,不进入源码解析页。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 生视频提交不再被前端锁死</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>虽然当前探测到常见视频入口返回 404/unsupported,但模型层确实有视频模型,不能在前端简单判定“未开通”并禁用。</p>
|
||
<p><strong>改动:</strong>撤掉分镜编排里的前置禁用;后端允许提交 seedance / kling / veo / voe,并支持通过 <code>VIDEO_CREATE_PATHS</code> 逗号分隔配置多个候选生成入口,逐个尝试。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env.example</code>、<code>web/app/page.tsx</code>、<code>web/components/storyboard-workbench.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 生视频错误提示改为可读原因</h3>
|
||
<span class="tag rose">VideoGenNode</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>提交生视频失败时,前端把 <code>generateStoryboardVideo 503 {"detail": ...}</code> 原样展示,用户无法快速判断是配置、端点还是 UI 问题。</p>
|
||
<p><strong>改动:</strong><code>generateStoryboardVideo</code> 解析后端 JSON 的 <code>detail</code> 后再抛错;后端错误文案区分“模型存在”和“入口不可用”;Video Gen 失败卡把 <code>/videos 404</code> 长错误压缩成一句可读原因。</p>
|
||
<p><strong>影响:</strong><code>web/lib/api.ts</code>、<code>web/components/nodes/index.tsx</code>、<code>api/main.py</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · Video Gen 卡片增加复制和删除</h3>
|
||
<span class="tag rose">VideoGenNode</span>
|
||
<span class="tag blue">API</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>Video Gen 节点上方失败/完成任务卡只有整卡点击复制,不够明确;失败任务也无法从界面清掉。</p>
|
||
<p><strong>改动:</strong>每张视频任务卡左上角增加复制 prompt 按钮,右上角增加删除任务按钮;后端新增 <code>DELETE /jobs/{job_id}/storyboard-videos/{video_id}</code>,删除 <code>generated_videos</code> 记录并清理本地任务目录。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>web/app/page.tsx</code>、<code>web/lib/api.ts</code>、<code>api/main.py</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 分镜编排接入真实生视频任务</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag rose">VideoGenNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>4 图槽已经粘贴参考图后,用户要直接调用生视频 API,而不是只生成 prompt 或图片任务。</p>
|
||
<p><strong>改动:</strong>分镜编排明细区增加 Seedance / Kling / Veo 3 模型选择和“调用模型生成视频”按钮;后端新增 <code>/jobs/{job_id}/frames/{idx}/storyboard/video</code>。提交后按 <code>VIDEO_CREATE_PATHS</code> 逐个尝试生成入口,成功后轮询并保存 MP4;失败时保留任务卡和具体入口错误,方便继续排查网关实际路径。<code>VideoGenNode</code> 读取 <code>job.generated_videos</code> 展示排队、生成中、失败和完成视频。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>api/.env.example</code>、<code>web/components/storyboard-workbench.tsx</code>、<code>web/components/nodes/index.tsx</code>、<code>web/app/page.tsx</code>、<code>web/lib/api.ts</code>。Sora 不再作为默认模型;真实模型 ID 通过 <code>VIDEO_MODEL_SEEDANCE</code>、<code>VIDEO_MODEL_KLING</code>、<code>VIDEO_MODEL_VEO3</code> 配置,真实视频 API 地址通过 <code>VIDEO_API_BASE_URL</code>/<code>VIDEO_API_KEY</code> 配置。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 分镜编排下拉区支持上推缩小</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>分镜编排明细区默认占用太多顶部面积,展开后下方画布空间不足。</p>
|
||
<p><strong>改动:</strong>明细区默认高度降为 320px,并增加底部拖拽手柄,可上推缩到 180px,也可下拉放大查看完整内容。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-workbench.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 分镜缩略图条与编排明细合并为一个下拉区</h3>
|
||
<span class="tag violet">StoryboardBar</span>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>顶部分镜缩略图条和下方内嵌工作台都带分镜导航,看起来像两个不同板块。</p>
|
||
<p><strong>改动:</strong><code>StoryboardBar</code> 成为唯一分镜导航;<code>StoryboardWorkbench</code> 移除自己的标题栏、左侧分镜列表和底部快捷栏,只保留当前分镜的 4 图槽与改造目标明细。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-bar.tsx</code>、<code>web/components/storyboard-workbench.tsx</code>、<code>web/app/page.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 分镜头编排工作台改为内嵌下拉</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
<span class="tag violet">StoryboardBar</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>元素改造节点等入口仍会打开 <code>fixed inset-0</code> 的全屏 <code>StoryboardWorkbench</code>,用户感觉像跳转页面。</p>
|
||
<p><strong>改动:</strong>移除 <code>StoryboardWorkbench</code> 的 portal 全屏承载方式,改为渲染在顶部分镜栏下方;所有“打开编排”入口只展开这个内嵌区域。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-workbench.tsx</code>、<code>web/components/storyboard-bar.tsx</code>、<code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 钉住面板停靠到分镜头编排边缘</h3>
|
||
<span class="tag orange">KeyframePanelNode</span>
|
||
<span class="tag violet">StoryboardBar</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>关键帧详情钉住在浏览器左侧固定位置时,会遮挡顶部分镜头编排栏展开后的缩略图区域。</p>
|
||
<p><strong>改动:</strong>给 <code>StoryboardBar</code> 增加稳定 DOM 标记;钉住面板实时读取该区域下边缘,并吸附到其下方。展开 / 折叠分镜头编排时,钉住面板自动让位。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-bar.tsx</code>、<code>web/components/nodes/index.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 顶部分镜头编排不再跳转全屏工作台</h3>
|
||
<span class="tag violet">StoryboardBar</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>顶部 <code>StoryboardBar</code> 的“进入编排”和分镜缩略图点击会打开全屏 <code>StoryboardWorkbench</code>,打断当前画布流程。</p>
|
||
<p><strong>改动:</strong>顶部按钮改为“展开编排”,只下拉展示当前分镜列表;缩略图点击只聚焦该分镜,不再触发全屏跳转。后续已把工作台整体改成内嵌下拉,见上方最新记录。</p>
|
||
<p><strong>影响:</strong><code>web/components/storyboard-bar.tsx</code>、<code>web/app/page.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 钉住关键帧详情改为左侧停靠</h3>
|
||
<span class="tag orange">KeyframePanelNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>钉住后仍像自由浮层一样停在画布附近,用户继续缩放画布或调整面板尺寸时容易把它和画布节点混在一起。</p>
|
||
<p><strong>改动:</strong>钉住后统一吸附到浏览器左侧边缘,脱离 ReactFlow 画布缩放;钉住瞬间把当前可见大小转换成面板真实尺寸,之后只由右下角拖拽或标题栏按钮调整。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>;钉住语义从“原地浮在上层”改为“左侧停靠工作面板”。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 关键帧详情支持右下角拖拽缩放和上层钉住</h3>
|
||
<span class="tag orange">KeyframePanelNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>只有按钮缩放不够直观;钉住后仍作为画布节点,会继续随 ReactFlow 画布缩放。</p>
|
||
<p><strong>改动:</strong>增加右下角拖拽缩放手柄;钉住时通过 portal 固定到浏览器上层,脱离 ReactFlow 画布缩放和平移。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>、<code>web/app/page.tsx</code>;未钉住时仍是画布节点,钉住后保持屏幕固定位置。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 关键帧详情面板增加钉住按钮</h3>
|
||
<span class="tag orange">KeyframePanelNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>面板可以拖动后,用户仍可能误拖;切换图片时希望保持固定工作位置。</p>
|
||
<p><strong>改动:</strong>在标题栏增加钉子按钮。钉住后面板节点禁止拖动,切换关键帧只切换内容不移动位置;取消钉住后可继续拖动。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 切换关键帧不再重置详情面板位置</h3>
|
||
<span class="tag orange">KeyframePanelNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>用户把关键帧详情面板拖到合适位置后,再点击下一张关键帧会把面板拉回默认位置,造成视觉疲劳。</p>
|
||
<p><strong>改动:</strong>已打开的面板只切换内容,不移动位置;只有面板不存在、首次打开时才放到默认位置并自动聚焦。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>;关闭后重新打开仍会出现在默认位置。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 关键帧详情面板增加缩放控制</h3>
|
||
<span class="tag orange">KeyframePanelNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>关键帧详情面板作为画布节点后可以随画布缩放,但面板自身没有尺寸控制,用户无法单独放大或缩小它。</p>
|
||
<p><strong>改动:</strong>在面板标题栏增加 <code>-</code>、百分比重置、<code>+</code> 控制,支持 75% 到 135% 的面板级缩放。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>;点击新关键帧仍会找回到默认位置,缩放比例保留。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 关键帧详情从固定左侧抽屉迁到无限画布</h3>
|
||
<span class="tag orange">KeyframeNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>关键帧详情 / 元素提取面板固定在左侧 drawer,和 ReactFlow 无限画布割裂,也不会跟随画布缩放。</p>
|
||
<p><strong>改动:</strong>移除主页面隐藏渲染的 <code>Dashboard</code> drawer 承载方式,新增独立 <code>keyframePanel</code> ReactFlow 节点来挂载 <code>FrameLightbox</code>。</p>
|
||
<p><strong>影响:</strong><code>web/app/page.tsx</code>、<code>web/components/nodes/index.tsx</code>;点关键帧后面板默认出现在流程左侧空白画布里,不遮挡 Input / Keyframe 主节点;标题栏可拖动,跟随 ReactFlow 平移和缩放。再次点击关键帧缩略图会把面板找回到默认位置,并自动把视野拉到“关键帧 + 面板”。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 元素改造 hover 预览简化为原帧预览</h3>
|
||
<span class="tag violet">StoryboardNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>元素改造节点的 hover 预览虽然已改为节点内显示,但仍比关键帧节点复杂,多了“来源原帧 / 提取元素”两栏和元素名称,信息过载。</p>
|
||
<p><strong>改动:</strong>改成和镜头拆解关键帧一致的简单预览:只显示来源原帧,底部显示分镜编号和时间。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>;元素改造板块 hover 现在更轻,不干扰当前判断。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 元素改造 hover 预览改为节点内效果</h3>
|
||
<span class="tag violet">StoryboardNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>上一版把元素预览用 <code>createPortal</code> 挂到 <code>body</code>,DevTools 里会出现额外 fixed 层,交互形态和关键帧节点不一致。</p>
|
||
<p><strong>改动:</strong>改成节点内 <code>group-hover</code> 预览,不再向 <code>body</code> 插入预览层。后续又简化为只展示来源原帧,见上方最新记录。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>;元素改造板块的 DOM 和交互效果更接近关键帧缩略图。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 新增独立源码解析与协作地图</h3>
|
||
<span class="tag blue">docs</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>目的:</strong>把产品功能区、源码位置、接口、数据模型、需求描述方式固定下来,减少“描述不准导致改偏”。</p>
|
||
<p><strong>影响:</strong>新增 <code>docs/source-analysis.html</code>,不接入 Next 应用,不影响工作台运行。</p>
|
||
<p><strong>以后描述:</strong>可以直接引用本页的功能区名称、节点职责和源码文件名。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · Storyboard 元素缩略图 hover 预览修复</h3>
|
||
<span class="tag violet">StoryboardNode</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>元素改造节点上方小图 hover 没有像镜头拆解节点一样显示原图预览,并且首次修复时出现运行时错误。</p>
|
||
<p><strong>原因:</strong>节点内部 overflow 裁剪了预览;随后 portal 预览里把变量写成了不存在的 <code>aspectRatio</code>。</p>
|
||
<p><strong>影响:</strong><code>web/components/nodes/index.tsx</code>。该记录之后又改为节点内预览,见上方最新记录。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 元素识别结果不再锁死</h3>
|
||
<span class="tag orange">元素提取</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>Vision 识别可能错,但元素列表像最终结果;点击提取图会跳页面,打断用户思路。</p>
|
||
<p><strong>改动:</strong>支持元素改名、改英文提示、改位置、删除元素、重复提取、删除单张提取图;提取图不再用链接跳新页。</p>
|
||
<p><strong>影响:</strong><code>FrameLightbox</code>、<code>web/lib/api.ts</code>、<code>PATCH /jobs/{job_id}/frames/{idx}/elements/{element_id}</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 分镜编排入口聚焦到具体分镜</h3>
|
||
<span class="tag violet">StoryboardWorkbench</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>从 Storyboard 或顶部分镜条进入编排时,没有明确定位到用户正在看的那一帧。</p>
|
||
<p><strong>改动:</strong>工作台接受 <code>focusedFrame</code>,点击缩略图会打开工作台并聚焦对应分镜。</p>
|
||
<p><strong>影响:</strong><code>page.tsx</code>、<code>StoryboardBar</code>、<code>StoryboardWorkbench</code>、<code>StoryboardNode</code>。</p>
|
||
</div>
|
||
</article>
|
||
<article class="change">
|
||
<header>
|
||
<h3>2026-05-13 · 视觉管线不再被 ASR 阻断</h3>
|
||
<span class="tag green">Pipeline</span>
|
||
</header>
|
||
<div class="body">
|
||
<p><strong>问题:</strong>SKG 网关 audio 不通时,视觉解析也容易被标记失败。</p>
|
||
<p><strong>改动:</strong><code>analyze</code> 主流程强调拆轨和关键帧,声音文案轨独立处理。</p>
|
||
<p><strong>影响:</strong><code>api/main.py</code>、<code>page.tsx</code>、节点语义说明。</p>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="update-rule" data-search>
|
||
<h2>更新规则</h2>
|
||
<div class="callout">
|
||
<p>以后任何改动只要影响产品理解、节点职责、界面行为、数据模型、API、运行方式或用户操作路径,都要同步更新本页的对应章节和“变更记录”。</p>
|
||
</div>
|
||
<table style="margin-top:14px">
|
||
<thead>
|
||
<tr><th>改动类型</th><th>必须更新本页哪里</th><th>原因</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>看板文案 / 工作区功能</td><td>业务管线、节点职责边界、界面区域到源码、变更记录</td><td>避免用户按旧节点理解描述需求。</td></tr>
|
||
<tr><td>新增 / 修改接口</td><td>接口地图、数据模型、变更记录</td><td>避免前后端契约不清。</td></tr>
|
||
<tr><td>新增数据字段</td><td>数据模型、源码结构地图、变更记录</td><td>刷新恢复和 state.json 依赖字段一致。</td></tr>
|
||
<tr><td>改交互路径</td><td>界面区域到源码、需求描述模板、变更记录</td><td>用户描述“点击哪里”时必须和真实路径一致。</td></tr>
|
||
<tr><td>修 bug</td><td>变更记录;如果暴露新坑,也更新当前已通与阻塞</td><td>让后续同类问题能快速定位。</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
|
||
<script>
|
||
const input = document.getElementById("search");
|
||
const searchable = Array.from(document.querySelectorAll("[data-search]"));
|
||
input.addEventListener("input", () => {
|
||
const q = input.value.trim().toLowerCase();
|
||
searchable.forEach((el) => {
|
||
const text = el.innerText.toLowerCase();
|
||
el.classList.toggle("hidden-by-search", q && !text.includes(q));
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|