[이 모듈이 하는 일] 기본 이미지 모듈 대신, 회원 자신의 OpenAI API 키로 gpt-image-2 (기본 품질 low)를 불러 요소 시트와 장면 키프레임을 만든다. 비디아 포인트 대신 회원의 OpenAI 계정으로 요금이 청구된다. Gemini 키도 넣었다면 OpenAI 호출이 실패한 이미지만 Gemini 로 다시 시도한다. 결과는 기본 이미지 모듈과 같은 키(sheet:…, kf:…)로 assets 에 적으므로 뒤 단계(이미지 평가·영상·렌더링)를 그대로 이어 쓸 수 있다. [필요한 값] - 필수 | secret | openai_api_key | OpenAI API 키 | provider=openai - 옵션 | secret | gemini_api_key | Gemini API 키 | provider=gemini - 옵션 | select | image_quality | 이미지 품질 | options=low,medium default=low [입력] 이전 단계 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:<장면>" - retry.images, promptOverrides: 이미지 평가 단계가 남긴 재생성 목록·고친 프롬프트(있을 때) - [설정]의 image_quality: "low"(기본) 또는 "medium" [할 일] 1. 만들 목록은 기본 이미지 모듈과 같다. - 요소 시트: 키프레임 references 에 쓰인 {요소, 구도} 쌍. 키 "sheet::". - 키프레임: ai-image·ai-video 장면의 모든 키프레임. 키 "kf:<장면id>:<키프레임id>". - photo·stock-video·upload 장면 중 assets["media:<장면id>"] 가 없는 장면은 첫 키프레임(없으면 purpose 로 쓴 영어 프롬프트, 키 "kf:<장면id>:auto"). - assets 에 이미 있는 키는 건너뛴다. retry.images 에 있는 키는 다시 만든다. 2. 공통 값 - quality = [설정]의 image_quality 가 "medium" 이면 "medium", 그 밖에는 "low". - 키프레임 size: 9:16 → "1024x1536", 16:9 → "1536x1024", 1:1 → "1024x1024". 요소 시트는 항상 "1024x1024". - 프롬프트(영어): 시트는 "\nReference sheet of <요소 이름>: \nIdentity: \nPlain light-grey seamless studio background, full subject visible.\nAvoid: , text, letters, logos, watermark." 키프레임은 "\n\nAvoid: , text, letters, logos, watermark." 이고, 참조 요소가 있으면 "Keep these identities exactly: <요소 이름> — " 을 한 줄 더한다. 3. 참조가 없는 이미지(시트, 참조 없는 키프레임): http_request 를 부른다. {"method":"POST","url":"https://api.openai.com/v1/images/generations", "headers":{"Authorization":"Bearer {{secret:openai_api_key}}"}, "json":{"model":"gpt-image-2","prompt":"<프롬프트>","size":"","quality":"","n":1}, "response":"json","label":"<키>"} 4. 참조가 있는 키프레임: 첫 번째 참조 이미지 한 장을 붙여 편집 엔드포인트를 부른다. 참조 이미지 = references 첫 항목의 assets["sheet:…"], 없으면 referenceKeyframeIds 첫 항목의 assets["kf:…"]. {"method":"POST","url":"https://api.openai.com/v1/images/edits", "headers":{"Authorization":"Bearer {{secret:openai_api_key}}"}, "form":{"model":"gpt-image-2","prompt":"<프롬프트>\nUse the attached image only as the identity reference for <요소 이름>; compose a new scene as described.","size":"","quality":"","n":"1","image":{"asset_id":<참조 asset_id>}}, "response":"json","label":"<키>"} 참조 이미지가 아직 없으면 3번 방법(참조 없이)으로 만든다. 5. 결과 읽기: 응답의 saved_assets 에 저장된 이미지가 있으면 그 첫 asset_id 를 assets[키] 에 넣는다(도구가 응답 속 base64 이미지를 자동으로 저장한다). saved_assets 가 비어 있고 json.data[0].b64_json 이 잘리지 않고 보이면 save_base64(base64=그 값, ext="png", label=키) 로 저장해 그 asset_id 를 쓴다. json.data[0].url 만 있으면 http_request(method "GET", url=그 주소, response "asset", asset_kind "image", label=키) 로 가져온다. 6. 오류 처리 - HTTP_STATUS_401·403(키 오류): 더 부르지 않는다. "error" 에 "OpenAI API 키가 거절되었습니다. 패키지 설정에서 키를 확인해 주세요." 를 적고 지금까지 만든 것만 내보낸다. - HTTP_STATUS_400(프롬프트 정책·인자 문제): 메시지를 읽고 실존 인물 이름·상표·폭력 묘사를 일반화하거나 인자를 고쳐 한 번 다시 부른다. 편집 엔드포인트가 거절하면 참조 없이(3번) 한 번 다시 부른다. - HTTP_STATUS_429·5xx: 한 번 다시 부른다. - 그래도 실패하고 [설정]에 gemini_api_key 가 있으면 Gemini 로 한 번 만든다(참조 없이): {"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent", "headers":{"x-goog-api-key":"{{secret:gemini_api_key}}"}, "json":{"contents":[{"parts":[{"text":"<프롬프트>"}]}],"generationConfig":{"responseModalities":["IMAGE"],"imageConfig":{"aspectRatio":"<9:16|16:9|1:1>"}}}, "response":"json","label":"<키>"} 결과는 saved_assets 의 첫 asset_id 를 쓴다. - 끝내 실패한 키는 imageErrors 에 {"key": 키, "message": 요약} 을 더한다. 7. 순서: 시트를 먼저 모두 만들고, 키프레임을 설계도의 장면 순서·키프레임 순서대로 만든다. 8. 끝나면 retry.images 를 [] 로 비운다. [출력] 다음 최상위 필드만 담은 JSON 객체 하나(적지 않은 최상위 필드는 입력값이 그대로 이어지므로 다시 적지 않는다. 바꾸는 필드는 값 전체를 적는다.) - assets: 새로 만든 "sheet:…"·"kf:…" 키(재생성한 키는 새 asset_id) - retry: {"images": [], …기존 retry 의 다른 키는 그대로} - imageErrors: 실패 목록(없으면 []) - imageStats: {"generated": 만든 장수, "skipped": 건너뛴 수, "provider": "openai-byok", "quality": quality, "geminiFallback": Gemini 로 만든 장수} [주의] - API 키를 절대 적지 않는다. 헤더에는 {{secret:openai_api_key}}, {{secret:gemini_api_key}} 자리표시만 쓴다. - 비용은 회원의 OpenAI·Gemini 계정에 청구된다. 이미지 한 장에 요청 한 번(오류 재시도 제외)만 보낸다. 같은 키를 마음에 들 때까지 반복해 만들지 않는다. - 비디아 image_generate 도구는 쓰지 않는다(이 모듈은 회원 키로만 이미지를 만든다). - 이미지 안에 글자·숫자·로고를 요구하지 않는다. - 설계도(blueprint)는 바꾸지 않는다. - 설명·마크다운 없이 JSON 객체 하나만 답한다.