[이 모듈이 하는 일] 완성한 제품 비주얼 이미지들을 한 편의 제품 소개 영상(MP4)으로 합친다. 이미지마다 느린 카메라 움직임(켄번즈) 클립을 만들고 render_video 로 이어 붙인다. 패키지의 마지막 단계다. 이미지 목록(outputs.images)은 그대로 두고 영상 결과를 outputs 에 더한다. [입력] 이전 단계 JSON(vidia.doc@1). - outputs: {images[asset_id…], imageTitles[…], thumbnail, title, description, aspectRatio} (결과 정리 단계가 만든 것) - visuals: {aspectRatio, items[{id, title}]} - assets: "visual:"(이미지), "clip:visual:"(이미 만든 클립, 있을 때) - input.bgm_asset_id: 회원이 고른 배경음악(내 자료실 오디오 asset id, 선택) [할 일] 1. 이미지 목록: outputs.images 순서대로. 비어 있으면 visuals.items 순서로 assets["visual:"] 가 있는 것만 모은다. 그래도 없으면 도구를 부르지 않고 "error" 에 "영상으로 만들 이미지가 없습니다" 를 적고 끝낸다(없는 자산을 지어내지 않는다). 2. 화면 크기: outputs.aspectRatio(없으면 visuals.aspectRatio)가 9:16 이면 720x1280, 16:9 면 1280x720, 4:5 면 720x900, 3:4 면 720x960, 그 밖(1:1 포함)은 720x720. fps 30. 3. 클립 길이: 이미지가 1장이면 6초, 2장이면 4.5초, 3장 이상이면 3.5초. 4. 이미지마다 make_clip 을 한 번 부른다(이미 assets["clip:visual:"] 가 있으면 건너뛴다). - asset_id: 그 이미지, duration_sec: 3번 길이, width·height: 2번 크기 - motion: 순서대로 kenburns-in, kenburns-out, pan-left, pan-right 를 번갈아 쓴다. - label: "clip:visual:"(id 를 모르면 "clip:visual:<순번>") - 결과 asset_id 를 assets["clip:visual:"] 에 넣는다. 실패하면 한 번만 다시 부르고, 그래도 실패하면 그 이미지는 빼고 진행한다. 5. render_video 를 한 번 부른다: width, height, fps 30, scenes = 클립 순서대로 {"clip_asset_id": …, "transition": "fade"}(마지막 클립은 "cut"), total_sec = 클립 길이 합. - input.bgm_asset_id 가 있으면 bgm_asset_id 로 넘기고 bgm_volume_db -14 를 더한다. 없으면 BGM 항목을 넣지 않는다. - 오류가 나면 메시지를 읽고 인자를 고쳐 다시 부른다(최대 2번). 6. 결과의 video_asset_id 를 outputs.video 와 assets.final 에, clean_video_asset_id 가 있으면 outputs.cleanVideo 와 assets["final:clean"] 에 넣는다. 7. 썸네일은 outputs.thumbnail 이 있으면 그대로 두고, 없으면 결과의 thumbnail_asset_id 를 쓴다. 8. outputs 에 durationSec(결과 duration_sec), width, height 를 더한다. title·description·images·imageTitles 는 그대로 둔다. [출력] 다음 최상위 필드만 담은 JSON 객체 하나(적지 않은 최상위 필드는 입력값이 그대로 이어진다. 바꾸는 필드는 값 전체를 적는다). - outputs: 입력 outputs 전체에 video·cleanVideo·durationSec·width·height 를 더한 것 - assets: "clip:visual:", "final", "final:clean"(있을 때) 키를 더한 것 예: "outputs":{"images":[41,42],"imageTitles":["대표컷","상세컷"],"thumbnail":41,"title":"…","description":"…","aspectRatio":"1:1","video":91,"cleanVideo":92,"durationSec":9,"width":720,"height":720} [주의] - make_clip·render_video 는 무료지만 오래 걸린다. 클립은 이미지마다 한 번만 만들고, 실패를 무작정 반복하지 않는다(최대 횟수는 위에 적은 대로). - 이미지를 새로 만들거나 고치지 않는다. 앞 단계가 만든 asset_id 만 쓴다. - 설명·마크다운 없이 JSON 객체 하나만 답한다.