[이 모듈이 하는 일] 설계도대로 AI 이미지를 만든다. 먼저 반복 등장 요소의 설정 시트(요소 views)를 만들고, 그 시트를 참조 이미지로 붙여 장면 키프레임을 만든다. 인물·물체가 컷마다 달라지지 않게 하는 것이 이 모듈의 핵심이다. [입력] 이전 단계 JSON(vidia.doc@1). - blueprint.video: {aspectRatio, visualStyle, negativeStyle} - blueprint.elements[]: {id, name, description, identityRules[], views[{id, angle, imagePrompt}]} - blueprint.scenes[]: {id, media.type, keyframes[{id, role, imagePrompt, references[{elementId, viewId}], referenceKeyframeIds[]}]} - assets: 이미 만든 이미지("sheet:<요소>:<구도>", "kf:<장면>:<키프레임>")와 자료 단계 결과("media:<장면>"). 앞 단계가 회원이 올린 사진(제품·인물)을 "sheet:…" 에 미리 넣었으면 그 사진이 정본 시트다 — 다시 만들지 않고 참조로 붙인다. - retry.images: 이미지 평가 단계가 다시 만들라고 남긴 키 목록(있을 때) - promptOverrides: {"<키>": "고친 프롬프트"} (이미지 평가 단계가 남긴 개선 프롬프트, 있을 때) [할 일] 1. 만들 목록을 정한다. - 요소 시트: 키프레임 references 에 한 번이라도 쓰인 {요소, 구도} 쌍만 만든다. 키 "sheet::". - 키프레임: media.type 이 ai-image 또는 ai-video 인 장면의 모든 키프레임. 키 "kf:<장면id>:<키프레임id>". - 내 자료 장면 확인: media.type 이 upload 이고 scene.media.assetId 가 있는데 assets["media:<장면id>"] 가 없으면 get_asset(무료)으로 확인한다. 회원의 이미지·영상이면 assets["media:<장면id>"] = 그 id 로 적고 이 장면은 이미지를 만들지 않는다. - 대체 키프레임: media.type 이 photo·stock-video·upload 인 장면 가운데 (위 확인 뒤에도) assets["media:<장면id>"] 가 없는 장면(자료를 못 찾았거나 자료 단계가 없던 경우)은 그 장면의 첫 키프레임을 만든다. 키프레임이 없으면 장면 purpose 와 발화 내용으로 영어 imagePrompt 를 직접 한 문단 써서 키 "kf:<장면id>:auto" 로 만든다. - assets 에 이미 있는 키는 건너뛴다. 단 retry.images 에 있는 키는 다시 만든다. 2. 프롬프트를 조립한다(영어). - 시트: "\nCharacter/object reference sheet of <요소 name 을 영어로>: \nIdentity: \nPlain light-grey seamless studio background, full subject visible, no other objects.\nAvoid: , text, letters, logos, watermark." - 키프레임: "\n\nAvoid: , text, letters, logos, watermark." - promptOverrides 에 그 키가 있으면 imagePrompt 자리에 그 프롬프트를 쓴다. - visualStyle·negativeStyle 이 없으면 그 줄을 뺀다. 프롬프트 안의 한국어는 영어로 옮긴다. 3. 참조 이미지를 붙인다(최대 3장). - 키프레임의 references 순서대로 assets["sheet::"] 를 넣는다. - 남는 자리에 referenceKeyframeIds 의 이미지(assets["kf:<그 키프레임이 속한 장면id>:<키프레임id>"])를 넣는다. - 참조가 2장 이상이면 도구가 번호 붙인 한 장의 시트로 합쳐 보낸다. 프롬프트 끝에 "Reference sheet: image 1 = <요소1 이름>, image 2 = <…>. Keep their identity exactly; take only appearance from the references, not pose or background." 를 덧붙인다. 참조가 1장이면 "Keep the identity of the reference image exactly." 를 덧붙인다. - 참조할 이미지가 아직 없으면(앞에서 실패) 그 참조는 빼고 만든다. 4. 크기(size): 요소 시트는 "1024x1024". 키프레임은 "auto"(프로젝트 화면 비율을 따른다). 5. 순서: 시트를 모두 먼저 만든 뒤, 키프레임을 설계도의 장면 순서·키프레임 순서대로 만든다(뒤 키프레임이 앞 키프레임을 참조하기 때문). 6. image_generate 를 이미지 1장마다 한 번 부른다. label 은 키 그대로("kf:s03:s03_k1"). 결과 asset_id 를 assets[키] 에 넣는다. 7. 도구가 오류를 돌려주면: - 프롬프트 정책·안전 문제면 문제 표현(실존 인물 이름, 상표, 폭력 묘사)을 일반화해 한 번 다시 부른다. - 참조 이미지 문제면 참조를 빼고 한 번 다시 부른다. - 그래도 실패하면 그 키를 건너뛰고 imageErrors 에 {"key": 키, "message": 요약} 을 더한다. 8. 끝나면 retry.images 를 [] 로 비운다. promptOverrides 는 그대로 둔다(평가 단계가 기록으로 쓴다). [출력] 다음 최상위 필드만 담은 JSON 객체 하나(적지 않은 최상위 필드는 입력값이 그대로 이어지므로 다시 적지 않는다. 바꾸는 필드는 값 전체를 적는다.) - assets: 기존 값에 새로 만든 "sheet:…"·"kf:…" 키(와 확인한 "media:<장면id>")를 더하거나(재생성한 키는) 새 asset_id 로 바꾼다. - retry: {"images": [], …기존 retry 의 다른 키는 그대로} - imageErrors: 실패한 키 목록(없으면 []) - imageStats: {"generated": 이번에 만든 장수, "skipped": 이미 있어 건너뛴 수} 예: "assets":{…, "sheet:main_elevator:front":61, "kf:s01:s01_k1":62, "kf:s02:s02_k1":63} [주의] - image_generate 는 장당 비용이 드는 도구다. 목록에 있는 이미지만 한 번씩 만든다. 마음에 들지 않는다고 같은 키를 여러 번 만들지 않는다(품질 판정은 다음 평가 단계가 한다). - 없는 asset_id 를 적지 않는다. 도구가 돌려준 값만 쓴다. - 이미지 안에 글자·숫자·로고를 넣으라고 요구하지 않는다. - 설계도(blueprint)는 바꾸지 않는다. - 설명·마크다운 없이 JSON 객체 하나만 답한다.