auto-save 2026-05-14 13:43 (~4)

This commit is contained in:
2026-05-14 13:43:52 +08:00
parent 346591b3f3
commit 7797de4438
4 changed files with 48 additions and 22 deletions

View File

@@ -1,18 +1,5 @@
{ {
"entries": [ "entries": [
{
"files_changed": 5,
"hash": "e9b25be",
"message": "auto-save 2026-05-13 09:14 (+3, ~2)",
"ts": "2026-05-13T09:15:03+08:00",
"type": "commit"
},
{
"files_changed": 1,
"message": "启动 Claude 接力会话 · 已载入 Claude 最近会话,等待下一条指令 · 分支 HEAD · 1 项未提交变更 · 最近提交auto-save 2026-05-13 09:14 (+3, ~2)",
"ts": "2026-05-13T01:17:33Z",
"type": "assistant-session"
},
{ {
"files_changed": 2, "files_changed": 2,
"hash": "0599cd8", "hash": "0599cd8",
@@ -3276,6 +3263,19 @@
"type": "session-heartbeat", "type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令codex · 1 项未提交变更 · 最近提交auto-save 2026-05-14 13:32 (~4)", "message": "Codex 会话活跃 · 最近命令codex · 1 项未提交变更 · 最近提交auto-save 2026-05-14 13:32 (~4)",
"files_changed": 1 "files_changed": 1
},
{
"ts": "2026-05-14T13:38:22+08:00",
"type": "commit",
"message": "auto-save 2026-05-14 13:38 (~1)",
"hash": "346591b",
"files_changed": 1
},
{
"ts": "2026-05-14T05:38:40Z",
"type": "session-heartbeat",
"message": "Codex 会话活跃 · 最近命令codex · 1 项未提交变更 · 最近提交auto-save 2026-05-14 13:38 (~1)",
"files_changed": 1
} }
] ]
} }

View File

@@ -3701,7 +3701,9 @@ def generate_storyboard_video(job_id: str, idx: int, req: GenerateStoryboardVide
subject_ref_paths = [p for p in (storyboard_ref_path(job_id, r) for r in req.subject_images[:8]) if p] subject_ref_paths = [p for p in (storyboard_ref_path(job_id, r) for r in req.subject_images[:8]) if p]
reference_ref_paths = [] reference_ref_paths = []
seen_ref_paths: set[str] = {str(ref_path)} seen_ref_paths: set[str] = {str(ref_path)}
for p in [*subject_ref_paths, *product_ref_paths]: # Product fusion is sensitive to object drift. Send product references before
# extra character references so the rigid SKG device keeps its real shape.
for p in [*product_ref_paths, *subject_ref_paths]:
key = str(p) key = str(p)
if key not in seen_ref_paths: if key not in seen_ref_paths:
reference_ref_paths.append(p) reference_ref_paths.append(p)

View File

@@ -51,6 +51,29 @@ const FRAME_QUALITY_LABELS: Record<FrameExtractQuality, string> = {
ultra: "极准", ultra: "极准",
} }
const PRODUCT_FUSION_WEARING_PROMPT = [
"Product placement must be physically correct:",
"The SKG device is a rigid opaque white U-shaped neck massager, not a soft scarf, necklace, cable, collar, sticker, implant, or transparent body part.",
"It must stay OUTSIDE the transparent skin shell. It should rest on the external surface around the back of the neck and upper shoulders, like a wearable collar-shaped device.",
"The curved bridge sits behind the neck. The two open arms come forward along the left and right sides of the neck, above the collarbones and near the upper trapezius.",
"The inner metal massage pads face the back/side of the neck. The outer glossy plastic shell remains visible and opaque.",
"Hands may hold the two ends while putting it on, then release or lightly press the side control button. Hands must not hide the device silhouette.",
"The product should occlude the transparent skin where it is in front, cast a small contact shadow, and keep realistic perspective and scale.",
"Keep a tiny readable separation between product edge and skeleton/skin whenever needed so it never looks embedded.",
].join("\n")
const PRODUCT_FUSION_PRODUCT_IDENTITY_PROMPT = [
"Product identity is strict:",
"The four SKG product reference images are the single source of truth for the object. Preserve the same white U-shaped body, rounded arms, inner massage pads/nodes, side buttons, seams, glossy plastic material, thickness, proportions, and viewing angles.",
"Do not redesign, stylize, simplify, melt, inflate, shrink, recolor, add logos/text/screens/wires/extra parts, or turn it into a generic neckband/headphone/medical brace.",
"If the product and character conflict, prioritize preserving the product shape and place it externally on the neck rather than merging it into the character.",
].join("\n")
const PRODUCT_FUSION_NEGATIVE_PROMPT = [
"Hard negatives for product fusion:",
"no product passing through the neck, no product inside the transparent body, no x-ray blending, no transparent product, no product becoming bones or skin, no product fused with spine/ribs/throat, no clipping through shoulders, no floating device, no melted device, no deformed U-shape, no wrong body part, no necklace/scarf/headphones/brace, no random replacement product.",
].join("\n")
// 合并 input + download + split 为一个节点 // 合并 input + download + split 为一个节点
// 分叉:上路 input → visual lab ↘ // 分叉:上路 input → visual lab ↘
// 下路 input → audio ──────────────────────────→ compose // 下路 input → audio ──────────────────────────→ compose
@@ -540,16 +563,16 @@ export default function Home() {
`产品角度图 2${labelOf(productRefs[1], "SKG 产品侧面/斜侧视角")}`, `产品角度图 2${labelOf(productRefs[1], "SKG 产品侧面/斜侧视角")}`,
`产品角度图 3${labelOf(productRefs[2], "SKG 产品背面/细节视角")}`, `产品角度图 3${labelOf(productRefs[2], "SKG 产品背面/细节视角")}`,
`产品角度图 4${labelOf(productRefs[3], "SKG 产品补充/底部或佩戴视角")}`, `产品角度图 4${labelOf(productRefs[3], "SKG 产品补充/底部或佩戴视角")}`,
"产品使用部位:这是颈部/肩颈按摩仪,只能自然佩戴或贴合在脖子、后颈、颈肩交界处;不要放到手臂、腰、腿、胸口、眼部或背景里。", PRODUCT_FUSION_PRODUCT_IDENTITY_PROMPT,
"比例尺寸产品应符合真实颈部按摩仪大小U 形结构环绕后颈但不能巨大化、缩小成饰品、嵌入身体、悬浮或穿透透明人体。", PRODUCT_FUSION_WEARING_PROMPT,
"镜头语言:严格按描述里的出场方式、场景、景别、运镜、产品进入方式、佩戴贴合动作、使用过程和收尾方式执行。", "Camera direction: follow the scene description, but always stage the product as a separate external wearable object. Show the hands placing or adjusting the device on the outside of the neck; do not imply the product is merged with the transparent body.",
`场景/使用/享受描述:${shot.action_text.trim()}`, `场景/使用/享受描述:${shot.action_text.trim()}`,
TRANSPARENT_HUMAN_VIDEO_PROMPT, TRANSPARENT_HUMAN_VIDEO_PROMPT,
"融合要求:产品必须自然出现在透明骨架人动作中,尺寸可信,透视一致,只贴合手部拿取和后颈/颈肩使用区域,不能悬浮、漂移、融化、扭曲或变成其他物体。", "Fusion rule: this is product placement, not body fusion. The product is an opaque physical device worn outside the body with believable contact shadow, occlusion, scale, and perspective.",
"连续性:镜头必须完整连贯,中间不要跳切,不换角色,不换产品,不突然改变场景。", "连续性:镜头必须完整连贯,中间不要跳切,不换角色,不换产品,不突然改变场景。",
"产品一致性:严格保持 SKG 产品外观、颜色、材质、U 形结构、按摩触点、按键和比例;四张产品角度图是产品身份真源。",
"场景要求:背景、空间、光线和阴影要自然统一,不要出现水印、平台 UI、字幕或竞品包装。", "场景要求:背景、空间、光线和阴影要自然统一,不要出现水印、平台 UI、字幕或竞品包装。",
"商业质感:真实拍摄感、干净高级、产品清楚可辨、人物动作自然、镜头稳定。", "商业质感:真实拍摄感、干净高级、产品清楚可辨、人物动作自然、镜头稳定。",
PRODUCT_FUSION_NEGATIVE_PROMPT,
"禁止:文字、水印、随机品牌、非 SKG 产品、医学治疗承诺、夸张病症、恐怖元素、产品位置漂移、透明衣服但非透明身体。", "禁止:文字、水印、随机品牌、非 SKG 产品、医学治疗承诺、夸张病症、恐怖元素、产品位置漂移、透明衣服但非透明身体。",
TRANSPARENT_HUMAN_NEGATIVE_PROMPT, TRANSPARENT_HUMAN_NEGATIVE_PROMPT,
].join("\n") ].join("\n")
@@ -559,7 +582,7 @@ export default function Home() {
first_image: null, first_image: null,
last_image: null, last_image: null,
product_images: productRefs, product_images: productRefs,
subject_image: primarySubject, subject_image: null,
subject_images: subjectRefs, subject_images: subjectRefs,
scene_image: null, scene_image: null,
product_image: productRefs[0] ?? null, product_image: productRefs[0] ?? null,

View File

@@ -6,10 +6,11 @@ import {
frameUrl, cleanedFrameUrl, apiAssetUrl, frameUrl, cleanedFrameUrl, apiAssetUrl,
describeFrame, cleanupFrame, applyCleanedFrame, discardCleanedFrame, addElement, updateElement, deleteElement, describeFrame, cleanupFrame, applyCleanedFrame, discardCleanedFrame, addElement, updateElement, deleteElement,
generateSceneAsset, generateSubjectAssets, updateStoryboard, copyProductLibraryAsset, generateSceneAsset, generateSubjectAssets, updateStoryboard, copyProductLibraryAsset,
listCharacterLibrary, copyCharacterLibraryAssets, characterLibraryImageUrl, listCharacterLibrary, copyCharacterLibraryAssets, characterLibraryImageUrl, listProductLibrary,
type AssetBackground, type AssetSize, type CharacterLibraryItem, type KeyFrame, type Job, type ImageRef, type ProductFusionShot, type SceneAssetRole, type SceneStyle, type SubjectKind, type AssetBackground, type AssetSize, type CharacterLibraryItem, type KeyFrame, type Job, type ImageRef, type ProductFusionShot, type ProductLibraryItem, type SceneAssetRole, type SceneStyle, type SubjectKind,
} from "@/lib/api" } from "@/lib/api"
import { TRANSPARENT_HUMAN_FRAME_STANDARD, TRANSPARENT_HUMAN_UI_SUMMARY } from "@/lib/workflow-target" import { TRANSPARENT_HUMAN_FRAME_STANDARD, TRANSPARENT_HUMAN_UI_SUMMARY } from "@/lib/workflow-target"
import { HoverPreview } from "@/components/nodes/hover-preview"
import { toast } from "sonner" import { toast } from "sonner"
interface Props { interface Props {