feat: standardize product asset inputs
This commit is contained in:
@@ -4277,13 +4277,14 @@ def normalize_product_asset_image(src: Path, out: Path) -> dict:
|
|||||||
|
|
||||||
out.parent.mkdir(parents=True, exist_ok=True)
|
out.parent.mkdir(parents=True, exist_ok=True)
|
||||||
img.save(out, "JPEG", quality=PRODUCT_ASSET_JPEG_QUALITY, optimize=True, progressive=True, subsampling=0)
|
img.save(out, "JPEG", quality=PRODUCT_ASSET_JPEG_QUALITY, optimize=True, progressive=True, subsampling=0)
|
||||||
|
work_width, work_height = img.size
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"standard": f"AI工作副本:最长边≤{PRODUCT_ASSET_MAX_SIDE}px,建议长边≥{PRODUCT_ASSET_MIN_LONG_SIDE}px,短边≥{PRODUCT_ASSET_MIN_SHORT_SIDE}px,JPEG q{PRODUCT_ASSET_JPEG_QUALITY}",
|
"standard": f"AI工作副本:最长边≤{PRODUCT_ASSET_MAX_SIDE}px,建议长边≥{PRODUCT_ASSET_MIN_LONG_SIDE}px,短边≥{PRODUCT_ASSET_MIN_SHORT_SIDE}px,JPEG q{PRODUCT_ASSET_JPEG_QUALITY}",
|
||||||
"original_width": original_width,
|
"original_width": original_width,
|
||||||
"original_height": original_height,
|
"original_height": original_height,
|
||||||
"width": img.width,
|
"width": work_width,
|
||||||
"height": img.height,
|
"height": work_height,
|
||||||
"original_bytes": original_bytes,
|
"original_bytes": original_bytes,
|
||||||
"work_bytes": out.stat().st_size if out.exists() else 0,
|
"work_bytes": out.stat().st_size if out.exists() else 0,
|
||||||
"max_side": PRODUCT_ASSET_MAX_SIDE,
|
"max_side": PRODUCT_ASSET_MAX_SIDE,
|
||||||
|
|||||||
@@ -589,7 +589,7 @@
|
|||||||
<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/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/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/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>信息流广告复刻工作表:左侧素材输入;右侧展示视频下载状态、默认折叠的音频文案依据,以及统一的音频解析结果面板;面板顶部是一行讲话人/节奏/背景音摘要,下方左侧为原视频播放器、右侧为逐句时间轴,底部横向音频波形用参考图式的连续灰色包络显示响度、停顿和密集爆点。视频播放时通过 <code>requestAnimationFrame</code> 平滑驱动波形播放线,同时同步高亮并滚动当前句;点击音频波形或字幕行会跳转原视频时间。音频结果下方是信息流复刻分镜工作台:顶部产品参考区是“同一产品素材池”,不限量上传产品图,不做不同产品身份判断;上传后自动识别正面/左右 45 度/厚度/内侧触点/背底等视角,并标注背景类型、用途标签、生成风险和备注,用户只检查备注,鼠标悬停可放大预览;缺视角补图失败时保留重试入口。每条音频分镜纵向排列,行内从左到右串起原内容、新口播文案、画面规划/产品融入、参考帧/关键元素和 6 个候选视频槽。单条生成会从产品素材池按分镜角色、视角优先级、用途标签、置信度和风险自动挑选最多 6 张相关产品图,不会把全部产品图提交给生视频模型,然后复用现有生视频接口提交 Seedance 候选。旧分镜卡、抽帧控制和视频生成组件仍保留在文件里,但当前主路径不渲染。</td></tr>
|
<tr><td><code>web/components/ad-recreation-board.tsx</code></td><td>信息流广告复刻工作表:左侧素材输入;右侧展示视频下载状态、默认折叠的音频文案依据,以及统一的音频解析结果面板;面板顶部是一行讲话人/节奏/背景音摘要,下方左侧为原视频播放器、右侧为逐句时间轴,底部横向音频波形用参考图式的连续灰色包络显示响度、停顿和密集爆点。视频播放时通过 <code>requestAnimationFrame</code> 平滑驱动波形播放线,同时同步高亮并滚动当前句;点击音频波形或字幕行会跳转原视频时间。音频结果下方是信息流复刻分镜工作台:顶部产品参考区是“同一产品素材池”,不限量上传产品图,不做不同产品身份判断;上传原图推荐长边 1200-2000px、短边至少 600px,但后端会统一生成最长边 1600px、JPEG 92 的 AI 工作副本,并回显尺寸、自动转换和风险标注;上传后自动识别正面/左右 45 度/厚度/内侧触点/背底等视角,并标注背景类型、用途标签、生成风险和备注,用户只检查备注,鼠标悬停可放大预览;缺视角补图失败时保留重试入口。每条音频分镜纵向排列,行内从左到右串起原内容、新口播文案、画面规划/产品融入、参考帧/关键元素和 6 个候选视频槽。单条生成会从产品素材池按分镜角色、视角优先级、用途标签、置信度和风险自动挑选最多 6 张相关产品图,不会把全部产品图提交给生视频模型,然后复用现有生视频接口提交 Seedance 候选。旧分镜卡、抽帧控制和视频生成组件仍保留在文件里,但当前主路径不渲染。</td></tr>
|
||||||
<tr><td><code>web/app/login/page.tsx</code></td><td>生产登录页:访问账号/访问密钥表单、保持登录、错误/成功状态;当前只在原版 Digital Oasis 动态背景上叠加一个组合登录框,桌面端左侧是动态角色,右侧是图标化登录表单;面板左上角展示官网 SKG 字标和中文“营销内容工作台”系统标识。</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/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/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>
|
||||||
@@ -777,6 +777,20 @@ SubjectAsset {
|
|||||||
white_score,
|
white_score,
|
||||||
source_path,
|
source_path,
|
||||||
tags[]
|
tags[]
|
||||||
|
}</pre>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h3>ImageRef.asset_meta</h3>
|
||||||
|
<p>产品图上传或从产品图库复制到 job 时,后端会把原图转为统一 AI 工作副本,避免超高清原图拖慢识别、生图和生视频链路。黑底/白底不强行改色;只有透明底会铺白。前端用该字段展示工作图尺寸、自动转换动作和分辨率风险。</p>
|
||||||
|
<pre>asset_meta {
|
||||||
|
standard: "AI工作副本:最长边≤1600px,建议长边≥900px,短边≥600px,JPEG q92",
|
||||||
|
original_width, original_height,
|
||||||
|
width, height,
|
||||||
|
original_bytes, work_bytes,
|
||||||
|
max_side, min_long_side, min_short_side, quality,
|
||||||
|
actions[],
|
||||||
|
warnings[],
|
||||||
|
normalized
|
||||||
}</pre>
|
}</pre>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@@ -838,7 +852,7 @@ SubjectAsset {
|
|||||||
<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 /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>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>产品图库</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>产品图入库到 job</td><td><code>POST /jobs/{id}/assets</code>、<code>POST /jobs/{id}/assets/product-library</code></td><td><code>uploadStoryboardAsset</code>、<code>copyProductLibraryAsset</code></td><td>上传产品图或把内置产品图库条目复制为当前 job 的普通 asset。后端统一生成最长边 1600px、JPEG 92 的 AI 工作副本,透明底铺白,过大/过小图片会在 <code>ImageRef.asset_meta</code> 里返回转换动作和风险;黑底/白底背景本身不强行转换。</td></tr>
|
||||||
<tr><td>产品视角识别</td><td><code>POST /jobs/{id}/assets/product-views/analyze</code></td><td><code>analyzeProductViews</code></td><td>读取同一产品素材池,不限制只看前 6 张;自动分类为正面、左右 45 度、侧面厚度、内侧触点或背面/底部,并返回背景类型、用途标签、中文视角备注、生成风险和置信度;前端不再要求用户手动选择视角,也不做不同产品身份判断。</td></tr>
|
<tr><td>产品视角识别</td><td><code>POST /jobs/{id}/assets/product-views/analyze</code></td><td><code>analyzeProductViews</code></td><td>读取同一产品素材池,不限制只看前 6 张;自动分类为正面、左右 45 度、侧面厚度、内侧触点或背面/底部,并返回背景类型、用途标签、中文视角备注、生成风险和置信度;前端不再要求用户手动选择视角,也不做不同产品身份判断。</td></tr>
|
||||||
<tr><td>产品缺角度补图</td><td><code>POST /jobs/{id}/assets/product-angle</code></td><td><code>generateProductAngleAsset</code></td><td>用当前产品白底图作为参考,通过图像模型自动补全缺失视角,输出新的 <code>ImageRef(kind="asset")</code>。Prompt 会约束白底产品图、左右非对称、厚度、内侧触点和肩颈真实佩戴比例;前端只在自动补图失败时暴露重试入口。</td></tr>
|
<tr><td>产品缺角度补图</td><td><code>POST /jobs/{id}/assets/product-angle</code></td><td><code>generateProductAngleAsset</code></td><td>用当前产品白底图作为参考,通过图像模型自动补全缺失视角,输出新的 <code>ImageRef(kind="asset")</code>。Prompt 会约束白底产品图、左右非对称、厚度、内侧触点和肩颈真实佩戴比例;前端只在自动补图失败时暴露重试入口。</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>角色库</td><td><code>GET /character-library/skg</code></td><td><code>listCharacterLibrary</code></td><td>读取内置 5 个透明骨架人角色 manifest,每个角色含正面、左右 45 度、侧面、背面、半身近景和背部特写 7 张参考图。</td></tr>
|
||||||
@@ -950,6 +964,19 @@ SubjectAsset {
|
|||||||
<h2>变更记录</h2>
|
<h2>变更记录</h2>
|
||||||
<p>这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。</p>
|
<p>这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。</p>
|
||||||
<div class="changelog">
|
<div class="changelog">
|
||||||
|
<article class="change">
|
||||||
|
<header>
|
||||||
|
<h3>2026-05-17 · 产品图上传统一生成 AI 工作副本</h3>
|
||||||
|
<span class="tag blue">API</span>
|
||||||
|
<span class="tag rose">UI</span>
|
||||||
|
<span class="tag cyan">Workflow</span>
|
||||||
|
</header>
|
||||||
|
<div class="body">
|
||||||
|
<p><strong>问题:</strong>同事容易把“上传最高清”理解为最好,但超大原图会拖慢上传、识别和后续生图/生视频,而且并不会让模型更稳定;低分辨率图也需要被标出来,避免后面误以为细节可靠。</p>
|
||||||
|
<p><strong>改动:</strong><code>api/main.py</code> 新增 <code>normalize_product_asset_image</code>,产品图上传和产品图库复制都会生成统一 AI 工作副本:最长边 1600px、JPEG 92,推荐原图长边 1200-2000px、短边至少 600px。超大图自动压缩,低分辨率图自动放大并标风险,透明底铺白;黑底/白底背景本身不强行转换。接口返回 <code>ImageRef.asset_meta</code> 记录原尺寸、工作图尺寸、自动动作和警告。</p>
|
||||||
|
<p><strong>影响:</strong><code>web/lib/api.ts</code> 增加 <code>asset_meta</code> 类型;<code>ProductReferenceCard</code> 展示工作图尺寸、“已标准化”和“需留意”标签,悬停预览里显示规格风险。后续视频/图片生成应优先使用该工作副本,不把超高清原图直接交给模型。</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
<article class="change">
|
<article class="change">
|
||||||
<header>
|
<header>
|
||||||
<h3>2026-05-17 · 同一产品素材池增加生视频选图标注</h3>
|
<h3>2026-05-17 · 同一产品素材池增加生视频选图标注</h3>
|
||||||
|
|||||||
@@ -1350,7 +1350,7 @@ function AudioStoryboardPlanPanel({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-1 max-w-[760px] text-[11px] leading-snug text-white/42">
|
<p className="mt-1 max-w-[760px] text-[11px] leading-snug text-white/42">
|
||||||
上传原图不限尺寸,但系统会自动生成轻量 AI 工作副本:最长边 1600px、JPEG 92。超高清原图不会更稳;低分辨率会自动放大并标注风险。每条视频只挑最多 {MAX_PRODUCT_REFS_PER_VIDEO} 张相关产品图。
|
推荐原图长边 1200-2000px、短边至少 600px;超出也能上传,系统会自动生成最长边 1600px、JPEG 92 的轻量 AI 工作副本。黑底/白底保留,透明底铺白;超高清不会更稳,低分辨率会放大并标注风险。每条视频只挑最多 {MAX_PRODUCT_REFS_PER_VIDEO} 张相关产品图。
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex shrink-0 items-center gap-2">
|
<div className="flex shrink-0 items-center gap-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user