diff --git a/.memory/worklog.json b/.memory/worklog.json index f5f714f..890ad54 100644 --- a/.memory/worklog.json +++ b/.memory/worklog.json @@ -1,19 +1,5 @@ { "entries": [ - { - "files_changed": 1, - "hash": "92794f6", - "message": "auto-save 2026-05-13 07:27 (~1)", - "ts": "2026-05-13T07:27:19+08:00", - "type": "commit" - }, - { - "files_changed": 1, - "hash": "ced696f", - "message": "auto-save 2026-05-13 07:33 (~1)", - "ts": "2026-05-13T07:33:13+08:00", - "type": "commit" - }, { "files_changed": 1, "hash": "af608ef", @@ -3280,6 +3266,19 @@ "type": "session-heartbeat", "message": "Codex 会话活跃 · 最近命令:codex · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 13:10 (~5)", "files_changed": 3 + }, + { + "ts": "2026-05-14T13:16:15+08:00", + "type": "commit", + "message": "auto-save 2026-05-14 13:16 (~3)", + "hash": "22f8885", + "files_changed": 3 + }, + { + "ts": "2026-05-14T05:18:40Z", + "type": "session-heartbeat", + "message": "Codex 会话活跃 · 最近命令:codex · 3 项未提交变更 · 最近提交:auto-save 2026-05-14 13:16 (~3)", + "files_changed": 3 } ] } diff --git a/docs/source-analysis.html b/docs/source-analysis.html index 5390203..109eec0 100644 --- a/docs/source-analysis.html +++ b/docs/source-analysis.html @@ -629,7 +629,7 @@ api/main.py
你看到的区域关键帧素材审核面板
-
主要源码FrameLightbox;按“原图/清洗、主体资产、首尾帧、产品融合、审核”五个页签组织;左侧只放主图/框选画布,但主体资产页左侧改为全部已清洗/已选参考帧网格,首尾帧页左侧显示全部关键帧并可勾选人物/机位参考。主体识别页会显示透明骨架人目标和 Vision 验收分数。清洗页右侧支持一键清洗未处理帧、单张替换清洗版和一键替换全部待应用清洗版;批量替换顺序调用 applyCleanedFrame,不新增后端接口。产品融合页左侧是纵向 6 行镜头工作表:顶部选择 5 个内置透明骨架人角色之一,每行只显示已预填场景/产品使用/享受描述、秒数、生成按钮和对应视频结果;描述词内置 36 条镜头语言模板,按“建立出场、产品入画、佩戴贴合、使用感受、生活延展、收尾记忆”排列,点击“换一组”只刷新 6 行描述词。四张桌面 SKG 产品图和所选角色 7 张参考图作为固定参考,生成时分别通过 copyProductLibraryAssetcopyCharacterLibraryAssets 自动写入当前 job,不再暴露产品角度槽、产品融合辅助栏、产品图库选择器或首尾帧槽。主体资产页只确认一个统一主体,后端按参考重绘六张纯背景、占满画面的标准站立透明骨架人资产图;首尾帧页保留给旧流程/单独生图,不再是产品融合必填步骤。相关接口包括 cleanupFrameapplyCleanedFrameaddElementgenerateSubjectAssetsgenerateSceneAssetcopyProductLibraryAssetcopyCharacterLibraryAssets
+
主要源码FrameLightbox;按“原图/清洗、主体资产、首尾帧、产品融合、审核”五个页签组织;左侧只放主图/框选画布,但主体资产页左侧改为全部已清洗/已选参考帧网格,首尾帧页左侧显示全部关键帧并可勾选人物/机位参考。主体识别页会显示透明骨架人目标和 Vision 验收分数。清洗页右侧支持一键清洗未处理帧、单张替换清洗版和一键替换全部待应用清洗版;批量替换顺序调用 applyCleanedFrame,不新增后端接口。产品融合页左侧是纵向 6 行镜头工作表:顶部选择 5 个内置透明骨架人角色之一,每行只显示已预填场景/产品使用/享受描述、秒数、生成按钮和对应视频结果;描述词内置 36 条镜头语言模板,按“建立出场、产品入画、佩戴贴合、使用感受、生活延展、收尾记忆”排列,并且会按角色自动改写场景气质、使用动作和享受状态。每行还内置角色参考图调度:例如正面/半身用于出场,侧面/背部特写用于佩戴贴合,半身/背部特写用于收尾产品记忆点。点击“换一组”只刷新 6 行描述词。四张桌面 SKG 产品图和所选角色 7 张参考图作为固定参考,生成时分别通过 copyProductLibraryAssetcopyCharacterLibraryAssets 自动写入当前 job,不再暴露产品角度槽、产品融合辅助栏、产品图库选择器或首尾帧槽。主体资产页只确认一个统一主体,后端按参考重绘六张纯背景、占满画面的标准站立透明骨架人资产图;首尾帧页保留给旧流程/单独生图,不再是产品融合必填步骤。相关接口包括 cleanupFrameapplyCleanedFrameaddElementgenerateSubjectAssetsgenerateSceneAssetcopyProductLibraryAssetcopyCharacterLibraryAssets
适合怎么描述“这一组关键帧如何共同生成一个统一主体包;某张关键帧的水印、去主体场景图、产品融合镜头组和质量风险应该如何审核”。
@@ -928,7 +928,7 @@ SubjectAsset {

问题:当前产品融合不再需要手动首帧/尾帧,用户要的是从内置透明骨架人角色、场景描述、产品使用方式和享受状态直接生成视频。

-

改动:桌面 skg_anatomy_characters_20260514_120852 的 5 个角色、35 张图内置为 api/character_library/skg-characters。产品融合页新增角色下拉和角色预览,每行只保留场景/产品使用/享受描述、秒数、生成按钮和结果视频;生成前自动复制所选角色 7 张参考图和固定 4 张 SKG 产品图到当前 job。

+

改动:桌面 skg_anatomy_characters_20260514_120852 的 5 个角色、35 张图内置为 api/character_library/skg-characters。产品融合页新增角色下拉和角色预览,每行只保留场景/产品使用/享受描述、秒数、生成按钮和结果视频;选择不同角色时,6 行描述会自动改成对应角色的场景气质、产品使用动作和享受状态,并自主写入“本镜头主要参考哪几张角色图、生成什么场景”。生成前自动复制所选角色 7 张参考图和固定 4 张 SKG 产品图到当前 job。

后端:新增 GET /character-library/skgGET /character-library/skg/images/{filename}POST /jobs/{job_id}/assets/character-library。视频提交新增 subject_images,无首帧时主人物图以 reference_image role 传入 Ark/Seedance,而不是强制作为 first_frame

影响:api/main.pyapi/character_library/skg-charactersweb/lib/api.tsweb/app/page.tsxweb/components/lightbox.tsxdocs/source-analysis.html

diff --git a/web/components/lightbox.tsx b/web/components/lightbox.tsx index 194018e..1375781 100644 --- a/web/components/lightbox.tsx +++ b/web/components/lightbox.tsx @@ -194,39 +194,107 @@ const PRODUCT_FUSION_DESCRIPTION_PRESETS = [ "备用30|舒适微表情|佩戴稳定后,透明骨架人眼神变柔和、嘴角轻扬,肩颈线条放松;镜头从产品细节回到脸部,保持广告级质感。", ] -const CHARACTER_PROMPT_PROFILES: Record = { +const FUSION_STAGE_PLANS = [ + { + refs: "正面 + 半身近景", + product: "产品先在桌面、床头或手边出现,人物尚未佩戴,负责建立角色和场景", + result: "角色成立、场景成立、观众看到 SKG 产品即将被使用", + }, + { + refs: "正面 + 左45度 + 产品正面/侧面", + product: "手把 SKG 从桌面或包中拿起带入画面,产品沿手部运动靠近后颈", + result: "产品进入画面自然,不悬浮,尺寸开始和人物肩颈建立关系", + }, + { + refs: "侧面 + 背部特写 + 产品侧面/背面", + product: "SKG 准确落到脖子、后颈、颈肩交界处,双手扶两端微调贴合", + result: "重点解决佩戴位置、产品尺寸、透视和后颈贴合真实性", + }, + { + refs: "半身近景 + 侧面", + product: "产品已经稳定佩戴,人物轻按控制区或保持佩戴状态", + result: "表现闭眼、肩部下沉、呼吸放慢、舒适享受,但不做医疗疗效承诺", + }, + { + refs: "正面 + 左45度/右45度", + product: "人物在生活场景中继续佩戴 SKG,产品位置稳定,不漂移不变形", + result: "展示真实使用中的生活方式,人物、场景和产品统一", + }, + { + refs: "半身近景 + 背部特写 + 产品主视角", + product: "收尾停在肩颈和产品清楚可辨的位置,手不遮挡产品关键轮廓", + result: "形成广告记忆点:角色舒适、产品清楚、画面干净高级", + }, +] + +const CHARACTER_PROMPT_PROFILES: Record = { "character-01": { name: "运动阳光男", subject: "清爽运动阳光男透明骨架人,身形挺拔、年轻有活力,整体气质健康明亮", - scenes: "晨练后卧室、阳台休息区、明亮健身房休息长椅或运动后居家放松场景", + stageScenes: [ + "晨练后的明亮卧室,阳光从窗边进入,SKG 放在床头或运动包旁", + "健身房休息长椅旁,人物从运动包中拿起 SKG", + "阳台休息区侧面近景,阳光照到后颈和白色骨架", + "运动后客厅或卧室半身近景,背景清爽明亮", + "窗边拉伸区或瑜伽垫旁,人物轻松活动肩颈", + "干净白色广告背景或明亮卧室收尾特写", + ], usage: "运动后双手拿起 SKG,准确戴到后颈和颈肩交界处,轻按侧边控制区并微调贴合", enjoyment: "从运动后的颈肩紧绷变成轻松舒展,闭眼深呼吸、肩部下沉、露出阳光放松微笑", }, "character-02": { name: "都市型男", subject: "都市通勤型男透明骨架人,穿搭利落,高层公寓和商务感更强", - scenes: "高层公寓客厅、办公桌、商务休息区、夜晚城市窗边或会议间隙", + stageScenes: [ + "高层公寓客厅或落地窗前,桌面上摆着 SKG", + "办公桌前或商务休息区,人物从桌面拿起 SKG", + "办公椅侧面近景,后颈和颈肩区域清楚可见", + "夜晚城市窗边半身近景,灯光克制高级", + "会议间隙的安静休息区,人物靠回椅背继续佩戴", + "高层公寓半身收尾,产品在后颈位置清楚可辨", + ], usage: "久坐办公后从桌面拿起 SKG,戴到后颈,手指轻按按键,让产品稳定贴合颈肩", enjoyment: "从低头疲惫、揉脖子变为靠回椅背放松,眼神平静、嘴角微扬,呈现高效恢复感", }, "character-03": { name: "优雅白领女", subject: "优雅白领女透明骨架人,姿态端正、干净精致,商业广告感更高级", - scenes: "办公室午休区、极简卧室、化妆镜前、柔和落地窗旁或精致公寓客厅", + stageScenes: [ + "精致公寓客厅或柔和落地窗旁,SKG 放在小桌上", + "办公室午休区或化妆镜前,人物优雅拿起 SKG", + "镜前或窗边侧面近景,后颈线条和白色骨架清楚", + "极简卧室半身近景,柔和光线突出放松表情", + "办公室休息区继续佩戴,动作克制自然", + "高级广告式半身收尾,产品轮廓和人物微笑都清楚", + ], usage: "工作间隙优雅拿起 SKG,轻放到后颈,双手细致调整两端贴合,动作慢而自然", enjoyment: "从肩颈紧绷转为安静舒缓,闭眼微笑、呼吸放慢,呈现精致、自洽、舒服的状态", }, "character-04": { name: "运动辣妹", subject: "运动辣妹透明骨架人,线条利落、活力强,适合健身后和生活方式广告", - scenes: "健身房更衣区、瑜伽垫旁、阳光客厅、运动后休息区或浴室镜前", + stageScenes: [ + "健身房更衣区或瑜伽垫旁,SKG 放在水杯和毛巾旁", + "运动后休息区,人物从健身包或桌面拿起 SKG", + "浴室镜前或瑜伽垫旁侧面近景,后颈和肩线清楚", + "阳光客厅半身近景,人物闭眼放松", + "运动后休息区继续佩戴,轻轻侧头伸展", + "健身生活方式广告收尾,产品贴合后颈且轮廓清晰", + ], usage: "训练后拿起 SKG 戴到后颈,侧头伸展时保持产品稳定贴合,手部不遮挡产品轮廓", enjoyment: "从训练后的酸胀紧绷变为轻松舒展,闭眼享受、肩颈打开,表情自信舒服", }, "character-05": { name: "绅士大叔", subject: "成熟绅士大叔透明骨架人,气质稳重高级,适合书房、客厅和商务休息场景", - scenes: "木质书房、皮质休闲椅、安静客厅、窗边阅读角或商务酒店房间", + stageScenes: [ + "木质书房或皮质休闲椅旁,SKG 放在书桌边", + "窗边阅读角,人物从桌边稳稳拿起 SKG", + "书房侧后方近景,后颈、颈椎和背部特写参考清楚", + "安静客厅半身近景,灯光温暖克制", + "商务酒店房间或书房里继续佩戴阅读休息", + "成熟高级的半身收尾,产品清楚、人物从容微笑", + ], usage: "阅读或工作后从桌边拿起 SKG,稳稳戴到后颈,轻扶两端调整到颈肩正确位置", enjoyment: "从沉稳疲惫变为从容舒适,缓慢闭眼、肩部放松、轻轻微笑,表达成熟克制的享受", }, @@ -235,10 +303,15 @@ const CHARACTER_PROMPT_PROFILES: Record { const base = PRODUCT_FUSION_DESCRIPTION_PRESETS[presetIndex % PRODUCT_FUSION_DESCRIPTION_PRESETS.length] const profile = CHARACTER_PROMPT_PROFILES[characterId] ?? CHARACTER_PROMPT_PROFILES[DEFAULT_CHARACTER_ID] + const stage = presetIndex % FUSION_SHOT_COUNT + const stagePlan = FUSION_STAGE_PLANS[stage] + const scene = profile.stageScenes[stage] || profile.stageScenes[0] return [ base, `角色设定:${profile.subject}。`, - `场景倾向:${profile.scenes}。`, + `自主图像编排:本镜头主要参考角色图【${stagePlan.refs}】,场景生成【${scene}】。`, + `产品调度:${stagePlan.product}。`, + `镜头目标:${stagePlan.result}。`, `产品使用:${profile.usage};产品只能在脖子、后颈、颈肩交界处使用,尺寸必须符合真实颈部按摩仪比例。`, `享受状态:${profile.enjoyment};不要医疗治疗承诺,不要恐怖解剖感。`, ].join("\n") @@ -264,7 +337,7 @@ const createFusionShots = (): ProductFusionShot[] => person_image: null, product_region: null, scene_image: null, - action_text: PRODUCT_FUSION_DESCRIPTION_PRESETS[i % PRODUCT_FUSION_DESCRIPTION_PRESETS.length], + action_text: fusionDescriptionForCharacter(DEFAULT_CHARACTER_ID, i), duration: 5, image_model: "gpt-image-2", video_model: "seedance", @@ -544,7 +617,7 @@ export function FrameLightbox({ jobId, frames, generatedVideos = [], activeIndex const start = (page * FUSION_SHOT_COUNT) % PRODUCT_FUSION_DESCRIPTION_PRESETS.length const next = fusionShots.map((shot, i) => ({ ...shot, - action_text: PRODUCT_FUSION_DESCRIPTION_PRESETS[(start + i) % PRODUCT_FUSION_DESCRIPTION_PRESETS.length] || shot.action_text, + action_text: fusionDescriptionForCharacter(selectedCharacterId, start + i), })) setFusionPresetPage(page) setFusionShots(next) @@ -554,10 +627,12 @@ export function FrameLightbox({ jobId, frames, generatedVideos = [], activeIndex const selectFusionCharacter = (characterId: string) => { const character = characterLibrary.find((item) => item.id === characterId) - const next = fusionShots.map((shot) => ({ + const start = (fusionPresetPage * FUSION_SHOT_COUNT) % PRODUCT_FUSION_DESCRIPTION_PRESETS.length + const next = fusionShots.map((shot, i) => ({ ...shot, character_id: characterId, character_name: character?.name || shot.character_name || DEFAULT_CHARACTER_NAME, + action_text: fusionDescriptionForCharacter(characterId, start + i), subject_image: null, subject_images: [], })) @@ -1274,7 +1349,7 @@ export function FrameLightbox({ jobId, frames, generatedVideos = [], activeIndex void persistFusionShots(next) }} placeholder="写清场景、产品如何佩戴到脖子/后颈,以及人物舒适享受状态。" - className="h-[92px] w-full resize-none rounded-md border border-white/10 bg-black/35 px-2 py-1.5 text-[10px] leading-relaxed text-white/75 outline-none placeholder:text-white/25 focus:border-amber-300/45" + className="h-[148px] w-full resize-none rounded-md border border-white/10 bg-black/35 px-2 py-1.5 text-[10px] leading-relaxed text-white/75 outline-none placeholder:text-white/25 focus:border-amber-300/45" />