auto-save 2026-05-18 00:12 (~3)

This commit is contained in:
2026-05-18 00:12:58 +08:00
parent 745f72ded4
commit ba202e43b7
3 changed files with 73 additions and 31 deletions

View File

@@ -260,8 +260,42 @@ function closestFrameForTime(frames: KeyFrame[], time: number) {
}
function isSimilarActorElement(element: KeyElement) {
const name = `${element.name_zh || ""} ${element.name_en || ""}`.toLowerCase()
return name.includes("相似主角") || name.includes("相似主体") || name.includes("similar ad actor") || name.includes("similar actor") || name.includes("similar subject")
const zh = element.name_zh || ""
const en = (element.name_en || "").toLowerCase()
const combined = `${zh} ${en}`.toLowerCase()
const zhSimilarSubject = zh.includes("相似") && (zh.includes("主体") || zh.includes("主角") || zh.includes("人物"))
const enSimilarSubject = en.includes("similar") && (en.includes("subject") || en.includes("actor") || en.includes("humanoid") || en.includes("character"))
return (
zhSimilarSubject
|| enSimilarSubject
|| combined.includes("相似主角")
|| combined.includes("相似主体")
|| combined.includes("similar ad actor")
|| combined.includes("similar actor")
|| combined.includes("similar subject")
|| combined.includes("transparent skeleton humanoid subject")
)
}
function findSimilarActorSource(preferredFrames: KeyFrame[], allFrames: KeyFrame[]) {
const pools = [preferredFrames, allFrames]
const seen = new Set<number>()
for (const needsAssets of [true, false]) {
for (const pool of pools) {
const frames = [...pool].filter((frame) => {
if (seen.has(frame.index)) return false
seen.add(frame.index)
return true
}).reverse()
for (const frame of frames) {
const elements = [...(frame.elements || [])].reverse()
const element = elements.find((item) => isSimilarActorElement(item) && (!needsAssets || !!item.subject_assets?.length))
if (element) return { frame, element }
}
}
seen.clear()
}
return null
}
function buildSimilarSubjectPrompt(subjectStyle: SubjectStyleMode, direction: string) {
@@ -306,6 +340,10 @@ function imageModelChain(models?: RuntimeModels) {
return modelList(models?.image_fallbacks?.length ? models.image_fallbacks : [models?.image, "gemini-3.1-flash-image-preview", "gemini-2.5-flash-image"])
}
function subjectImageModelChain(models?: RuntimeModels) {
return modelList(models?.subject_image_fallbacks?.length ? models.subject_image_fallbacks : [models?.subject_image, "gpt-image-2", "gpt-image-1.5"])
}
function resolveVideoModelLabel(models: RuntimeModels | undefined, model: string) {
const concrete = models?.video_aliases?.[model] || (model === models?.video ? models.video : "")
return concrete && concrete !== model ? `${model} -> ${concrete}` : modelValue(concrete || model)
@@ -340,11 +378,11 @@ function productModelTrace(models?: RuntimeModels): ModelTraceSpec {
function similarSubjectModelTrace(models: RuntimeModels | undefined, subjectStyle: SubjectStyleMode): ModelTraceSpec {
return {
title: subjectStyle === "transparent_human" ? "相似透明骨架主体" : "相似普通真人主体",
model: imageModelChain(models),
model: subjectImageModelChain(models),
chain: [
"参考帧策略:未勾选时使用全部关键帧,勾选后只使用已选关键帧",
`主体类型:${subjectStyle === "transparent_human" ? "透明/半透明皮肤包裹可见白色骨架" : "普通商业广告真人"}`,
`图像生成:${imageModelChain(models)} 逐张生成正、背、左、右、左前 45、右前 45`,
`图像生成:${subjectImageModelChain(models)} 逐张生成正、背、左、右、左前 45、右前 45`,
"身份锁定:六张必须是同一个主体,性别表现、年龄段、体型、材质和风格保持一致",
],
note: "这是生成类似主体,不是复制、抠出或复刻源视频人物身份。",
@@ -1411,17 +1449,8 @@ function SourceReferenceBuildPanel({
[frames, selectedReferenceFrames],
)
const actorSource = useMemo(() => {
const pool = subjectReferenceFrames
for (const frame of pool) {
const element = frame.elements?.find(isSimilarActorElement)
if (element?.subject_assets?.length) return { frame, element }
}
for (const frame of pool) {
const element = frame.elements?.find(isSimilarActorElement)
if (element) return { frame, element }
}
return null
}, [subjectReferenceFrames])
return findSimilarActorSource(subjectReferenceFrames, frames)
}, [frames, subjectReferenceFrames])
const actorAssets = actorSource?.element.subject_assets ?? []
const previewFrame = framePreview ? frames.find((frame) => frame.index === framePreview.index) ?? null : null
const referenceCountLabel = selectedReferenceFrames.length