feat: add versioned Blender production contracts
This commit is contained in:
@@ -6,6 +6,6 @@
|
|||||||
|
|
||||||
개별 호출도 topic/story/scenes/final의 사용자 검토를 우회하지 않는다. 담당은 자기 새 버전과 검토를 제출하고 공유 진행·승인은 총괄만 바꾼다. 실제 파일이 없는 외부 결과를 완료로 처리하지 않는다.
|
개별 호출도 topic/story/scenes/final의 사용자 검토를 우회하지 않는다. 담당은 자기 새 버전과 검토를 제출하고 공유 진행·승인은 총괄만 바꾼다. 실제 파일이 없는 외부 결과를 완료로 처리하지 않는다.
|
||||||
|
|
||||||
필드·입력·승인 지점을 추가하지 않는다. 사례의 반전·위기·시간 배분은 모든 소재의 의무가 아니다. 실제 사용한 구성과 비적용 이유는 기존 review.md에 남긴다.
|
계약에 없는 필드·입력·승인 지점을 추가하지 않는다. 새 제작은 1.1 Blender 계약, 기존 1.0은 보존·참조한다. scenes 승인 전 제한된 08 대표 샘플만 허용하고 정식 10–12는 승인 후 진행한다. 사례의 반전·위기·시간 배분은 모든 소재의 의무가 아니다. 실제 사용한 구성과 비적용 이유는 기존 review.md에 남긴다.
|
||||||
|
|
||||||
변경한 스킬의 머리말·이름·미완성 내용과 실제 상대 링크를 확인하고, 선행 결과·승인 부재·외부 파일 부재가 올바르게 보고되는지 검토한다. 불필요한 지원 파일·실행 프로그램·검증 프레임워크를 추가하지 않는다.
|
변경한 스킬의 머리말·이름·미완성 내용과 실제 상대 링크를 확인하고, 선행 결과·승인 부재·외부 파일 부재가 올바르게 보고되는지 검토한다. 불필요한 지원 파일·실행 프로그램·검증 프레임워크를 추가하지 않는다.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ description: 승인된 대본·제목과 실제 컷 영상·통합 음성·자
|
|||||||
|
|
||||||
개별 호출에서도 같은 제작물의 유효한 `03-script`, `04-title`, `06-tts`, `07-cuts`, `12-motion`과 그 선행 관계를 확인한다. 실제 사용한 다섯 결과의 `{stage_id, revision}`을 `inputs`에 기록한다. project.json의 story·scenes가 실제 사용자 승인이며 사용 버전과 연결되는지 확인한다. pending·changes_requested·stale 승인을 우회하지 않고 같은 승인 버전은 다시 묻지 않는다. 누락·미확인 파일·길이 불일치가 있으면 문제 단계·컷을 총괄에 보고하고 요청 준비 완료로 처리하지 않는다.
|
개별 호출에서도 같은 제작물의 유효한 `03-script`, `04-title`, `06-tts`, `07-cuts`, `12-motion`과 그 선행 관계를 확인한다. 실제 사용한 다섯 결과의 `{stage_id, revision}`을 `inputs`에 기록한다. project.json의 story·scenes가 실제 사용자 승인이며 사용 버전과 연결되는지 확인한다. pending·changes_requested·stale 승인을 우회하지 않고 같은 승인 버전은 다시 묻지 않는다. 누락·미확인 파일·길이 불일치가 있으면 문제 단계·컷을 총괄에 보고하고 요청 준비 완료로 처리하지 않는다.
|
||||||
|
|
||||||
Qwen3-TTS 통합 WAV와 실측 구간, `gpt-image-2.5-sunburst` 이미지에서 이어진 실제 컷 영상, `references/1.png` 그림체를 유지한다. 이 스킬은 합성 엔진을 선택·구현하거나 실제 모델 API·합성을 실행하지 않고 도구에 중립적인 요청과 받은 결과 확인을 담당한다.
|
Qwen3-TTS 통합 WAV와 실측 구간, 승인된 Blender Scene에서 렌더링한 실제 컷 영상·교육용 3D 기준을 유지한다. 기존 1.0 결과도 유효한 입력이면 보존·참조한다. 승인된 기존 Remotion + FFmpeg 경로로 합성하고 1.1의 기존 13 구조와 실제 결과를 확인한다. 실행 프로그램 준비·파일 존재와 실제 재생·청취 성공을 구분한다. 원본 references/1.png를 보존하며 도구를 임의로 바꾸지 않는다.
|
||||||
|
|
||||||
## 요청 연결
|
## 요청 연결
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,32 @@
|
|||||||
---
|
---
|
||||||
name: short-video-images
|
name: short-video-images
|
||||||
description: 승인된 짧은 영상의 컷별 시작·끝 이미지 요청서를 작성하고 11 이미지의 실제 PNG와 장면 연속성을 검증할 때 사용한다.
|
description: 승인된 컷의 Blender Scene·시작/끝 상태와 논리 프레임을 작성하고 11의 실제 .blend·PNG·연속성을 검증한다.
|
||||||
---
|
---
|
||||||
|
|
||||||
# 컷 이미지 요청과 결과 확인
|
# Blender 컷 끝점 렌더
|
||||||
|
|
||||||
11-images만 담당한다. 각 컷에 시작과 끝 프레임이 필요하며 요청서만으로 생성 완료를 보고하지 않는다.
|
## 입력과 경계
|
||||||
|
|
||||||
## 읽을 자료와 시작 조건
|
[공통 계약](../../../docs/workflow-contracts.md), [전달 형식](../../../docs/contracts.md), [제작 지침](../../../docs/short-video-guide.md), [결과 스키마](../../../contracts/artifact.schema.json), [검토 양식](../../../templates/review.md)을 읽는다. 새 결과는 1.1이고 기존 1.0 결과를 보존·참조한다. 필수 입력 topic/language, Qwen3-TTS 기존 qwen3-tts 환경, 세로 9:16·최종 180000ms 이하·실측 컷 5000ms 이하를 유지한다.
|
||||||
|
|
||||||
- [공통 계약](../../../docs/workflow-contracts.md): 입력·선행 버전·경로·승인·실제 미디어 완료 기준.
|
같은 제작물의 유효한 선행 버전·실제 파일과 topic/story/scenes 승인을 확인하고 사용 버전을 inputs에 기록한다. 필요한 결과·승인이 없거나 stale이면 누락과 돌아갈 단계를 총괄에 보고한다. 같은 유효 승인 버전은 다시 묻지 않는다. 08의 제한된 대표 화면·짧은 움직임만 scenes 승인 전 검토용으로 허용하며 정식 10–12 전체 제작·완료와 구분한다. 새 08·09 승인 후 정식 제작한다.
|
||||||
- [제작 지침](../../../docs/short-video-guide.md): 근거와 숫자, 화면의 역할, 연속 연결, 그림체와 주석.
|
|
||||||
- [11 양식](../../../templates/stages/11-images.json), [결과 스키마](../../../contracts/artifact.schema.json), [검토 양식](../../../templates/review.md).
|
|
||||||
- [그림체 기준](../../../references/1.png): 실제 이미지를 열어 가는 윤곽선·단순 형태·정돈된 색면·제한적인 음영을 확인한다.
|
|
||||||
|
|
||||||
1. 제작물의 `topic`, `language`를 보존하고 세로 9:16, 전체 180000ms 이내, 각 컷 0ms 초과 5000ms 이하 조건을 확인한다.
|
원본 references/1.png를 보존하고 단순 형태·정돈된 색을 교육용 3D로 해석한다. 단순 배경·부드러운 조명·선명한 형태를 사용하며 평면 복제·캠핑 소재·상표를 강제하지 않는다. 02의 조사와 대본 근거로 모델·재질·방향·상태·수치를 확인하고 사실에 없는 구조를 만들지 않는다. 설명 텍스트는 검증한 합성 텍스트로 배치한다.
|
||||||
2. 같은 제작물의 유효한 02-research, 03-script, 07-cuts, 08-scenes, 09-entities, 10-references를 읽고 실제 사용 버전을 `inputs`에 기록한다. 10의 모든 필요한 기준 PNG와 참조가 검증되어야 한다. 자료가 없거나 stale·부분 결과이면 먼저 해결할 단계와 이유를 총괄에 보고한다.
|
|
||||||
3. scenes 검토의 실제 사용자 응답과 `artifact_refs`가 사용하는 07·08·09 버전을 승인했는지 확인한다. 10이 이 승인 전에 진행되었다면 유효한 선행 완료로 취급하지 않는다. topic·story 등 앞선 승인도 유효해야 한다. 개별 호출로 선행 결과·승인을 우회하지 않으며 같은 승인 버전에 재승인을 요구하지 않는다.
|
|
||||||
|
|
||||||
## 컷별 요청서 작성
|
## 컷별 Scene·끝점 요청
|
||||||
|
|
||||||
`payload.request`의 기존 `model`, `frames`만 사용하며 모델은 `gpt-image-2.5-sunburst`다. 스타일은 10의 기준 결과와 원본 `references/1.png`에 연결한다.
|
[11 양식](../../../templates/stages/11-images.json)을 사용한다. 유효한 02/03/07/08/09/10과 10의 실제 기준 .blend·PNG를 확인한다. request={engine:"Blender",scene_path,render_profile,frames}. scene_path는 만들 원본의 루트 상대 경로다.
|
||||||
|
|
||||||
- 각 frame은 유일한 `id`, `cut_id`, `position`, `prompt`, `reference_ids`를 가진다. 07의 모든 컷마다 `position=start`와 `position=end`가 정확히 하나씩 있어야 한다. 추가 컷·중복 위치·누락은 허용하지 않는다.
|
frame={id,cut_id,position,prompt,reference_ids,scene_name,frame_index}. 모든 실제 07 컷마다 start/end가 정확히 하나씩 있고 ID가 유일해야 한다. reference_ids는 10의 검증된 요청/결과 ID, scene_name은 비어 있지 않은 실제 Scene 이름, frame_index는 0 이상 논리 프레임이다. 같은 컷 start/end는 같은 Scene을 사용한다. 조사·대본·08 상태와 카메라·09 고정 특징을 prompt에 연결한다.
|
||||||
- `cut_id`는 07·08의 같은 컷을 가리키고, `reference_ids`는 10의 요청 `id`와 결과 `reference_id`가 일치하는 검증된 기준 이미지를 참조한다. 스타일 및 해당 컷의 인물·배경 기준을 포함하고 09의 등장 인물·배경 ID를 프롬프트에 연결한다.
|
|
||||||
- `prompt`는 03의 관련 블록·주장, 02의 확인한 근거, 08의 해당 start_state/end_state와 camera를 따른다. 인물·배경의 고정 특징을 유지하고 의상·표정·시간 변화는 장면에 근거해 명시한다. 원본 스타일 이미지의 등장인물을 모든 영상의 고정 인물로 삼지 않는다.
|
|
||||||
- 작동 원리와 단면·지도·주석의 구조·재료·방향·수치를 조사·대본과 대조한다. 근거가 없거나 선행 설계와 충돌하면 임의로 도해하지 말고 수정할 단계·컷을 보고한다. 단순화해도 사실에 중요한 차이를 남긴다.
|
|
||||||
- 그림체는 첨부의 가는 윤곽선·단순 형태·색면·제한적 음영을 따른다. 참고 Shorts의 입체 렌더링이나 캠핑 소재·상표 복제를 강제하지 않는다. 부정확한 생성 글자·숫자는 검증한 텍스트로 합성하도록 메모한다.
|
|
||||||
|
|
||||||
## 인접 프레임 연결
|
continuous는 같은 Scene의 앞 end와 뒤 start 상태를 맞추고 실제 PNG를 공유해도 위치별 별도 ID를 유지한다. cut은 서로 다른 Scene의 같은 프레임 번호를 구별하며 캐시 식별에 Scene 이름을 포함한다. 연결을 임의로 바꾸지 않는다. Blender 실제 번호=논리 프레임+1로 평가한다. 영상은 [start,end) 구간이고 끝점 PNG는 end 자체를 평가한다.
|
||||||
|
|
||||||
08의 `connections.mode`와 `reason`을 따른다. continuous는 앞 컷 end와 다음 컷 start의 같은 인물·배경·물체 위치·행동 진행·흐름 방향·카메라 상태를 맞춘다. 동일한 이미지를 공유할 수 있으나 각 컷·위치에는 별도 frame ID를 유지하고, 두 결과의 실제 `media.path` 및 공유하는 end/start frame ID 관계를 `review.md`에 명시한다. cut은 위치·시간·시점이 어떻게 바뀌는지 프롬프트와 검토 메모에서 설명한다. 장면 연결을 이미지 단계에서 임의로 변경하지 않는다.
|
result는 null 또는 {scene_file,frames:[{frame_id,media:image}]}다. 요청마다 실제 PNG가 누락·중복·추가 없이 대응하며 실제 .blend의 Scene·프레임·상태·재질·연결을 확인한다. 원본과 RenderProfile은 후속 12의 기준이다.
|
||||||
|
|
||||||
## 실제 결과 확인과 전달
|
## 실제 결과와 전달
|
||||||
|
|
||||||
실제 제작 시 해당 모델과 세로 출력 지원을 확인한다. 확인하지 않은 API 파라미터를 고정하거나 다른 모델로 무단 대체하지 않는다. 지원이 확인되지 않거나 실제 결과가 없으면 요청서를 보존하고 `result=null`, `awaiting_input`을 총괄에 보고한다.
|
승인된 저장소 내 Blender 실행 경로를 사용한다. 기존 설치를 무단 변경하거나 다른 도구로 바꾸지 않는다. 설치·요청 준비와 실제 렌더링 성공을 구분한다. .blend는 BlendFile={path,verified,sha256,blender_version}로 기록하고 실제 파일·해시·버전·재열기·Scene/자산을 검증한다. PNG/MP4 media로 위장하지 않는다. RenderProfile의 실제 지원을 확인하며 요청값을 실측 결과로 복사하지 않는다.
|
||||||
|
|
||||||
- 실제 부분 결과는 `payload.result.frames`에 보존한다. 각 결과는 `frame_id`, `media`이며 frame_id는 요청 frame의 `id`와 일치해야 한다. 모든 요청의 start/end 결과가 누락·중복 없이 검증되기 전 전체 complete로 보고하지 않는다.
|
media는 기존 여섯 키 {path,kind,verified,duration_ms,width,height}다. PNG는 image·duration_ms=null, MP4는 video·실측 양수 길이이며 실제 형식·해상도·9:16·내용을 확인한다. 확인한 파일만 verified=true이고 미확인 크기·시간은 null이다. 데이터 경로는 루트 상대 경로다. 실제 파일이 없으면 result=null·awaiting_input, 실행/검증 실패는 failed로 보고한다. 부분 결과와 실패 시도를 보존하며 전체 요청 결과가 검증되기 전 complete로 보고하지 않는다.
|
||||||
- `media`는 기존 `{path, kind, verified, duration_ms, width, height}`를 사용한다. 경로는 저장소 루트 기준이다. 실제 파일 존재·PNG 내용 형식·해상도와 화면을 확인한 경우만 `verified=true`다. `kind=image`, `duration_ms=null`, 크기는 실제 측정값이며 미확인 값은 null이다. 확장자·요청 크기·예제 경로만으로 검증하지 않는다. 실제 세로 9:16, 컷 상태·고정 특징·근거·연속성도 확인한다.
|
|
||||||
- 자기 단계의 새 `stages/11-images/r<revision>/artifact.json`과 `review.md`만 작성하고 이전 버전을 덮어쓰지 않는다. 메모에 적용 원칙과 결과, 비적용 이유, 실제 모델·지원 확인, 컷·프레임·파일별 검증과 미확인 사항을 적는다. 새 JSON 필드·필수 입력·승인 지점은 만들지 않는다.
|
자기 단계의 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 버전 review.md만 작성하고 이전 결과를 덮어쓰지 않는다. 실제 사용 버전·파일별 검사·명령·종료코드·미확인 영역·적용 원칙과 비적용 이유를 적는다. project.json·상태·현재 포인터·사용자 승인은 총괄만 갱신한다. 필드·열거값은 계약을 따르고 새 필수 입력·승인 지점을 만들지 않는다.
|
||||||
- 모든 컷의 두 위치와 결과 검증을 대조해 준비 여부·남은 문제·후속 영향과 수정할 단계를 총괄에 보고한다. `project.json`, 상태·현재 포인터·사용자 승인은 총괄만 변경한다.
|
|
||||||
|
|||||||
@@ -1,39 +1,32 @@
|
|||||||
---
|
---
|
||||||
name: short-video-motion
|
name: short-video-motion
|
||||||
description: 승인된 컷·장면과 실제 시작/끝 이미지로 12-motion 영상 요청을 작성하고 받은 MP4의 길이·상태·연결을 확인한다.
|
description: 승인된 실제 Blender 원본·Scene·끝점·실측 컷으로 12 렌더 요청을 작성하고 실제 MP4의 길이·상태·연결을 확인한다.
|
||||||
---
|
---
|
||||||
|
|
||||||
# 컷 영상 요청과 결과 확인
|
# Blender 컷 영상 렌더
|
||||||
|
|
||||||
## 시작 조건
|
## 입력과 경계
|
||||||
|
|
||||||
[공통 계약](../../../docs/workflow-contracts.md)의 저장·전달, 실제 파일과 시간, 승인·수정 규칙과 [제작 지침](../../../docs/short-video-guide.md)의 설명에 필요한 움직임·장면 연결 절을 읽는다. [12 양식](../../../templates/stages/12-motion.json)과 [결과 스키마](../../../contracts/artifact.schema.json)의 `12-motion` 정의를 사용하며 새 필드를 추가하지 않는다.
|
[공통 계약](../../../docs/workflow-contracts.md), [전달 형식](../../../docs/contracts.md), [제작 지침](../../../docs/short-video-guide.md), [결과 스키마](../../../contracts/artifact.schema.json), [검토 양식](../../../templates/review.md)을 읽는다. 새 결과는 1.1이고 기존 1.0 결과를 보존·참조한다. 필수 입력 topic/language, Qwen3-TTS 기존 qwen3-tts 환경, 세로 9:16·최종 180000ms 이하·실측 컷 5000ms 이하를 유지한다.
|
||||||
|
|
||||||
개별 호출에서도 같은 제작물의 유효한 `07-cuts`, `08-scenes`, `11-images`와 그 선행 관계를 확인한다. 실제 사용한 세 결과의 `{stage_id, revision}`을 `inputs`에 기록한다. `project.json`에서 story·scenes가 사용 버전과 연결된 실제 사용자 승인인지 확인하며 pending·changes_requested·stale 승인을 우회하지 않는다. 이미 승인된 같은 버전은 재승인을 요구하지 않는다. 자료·승인이 없으면 빠진 항목과 돌아갈 단계를 총괄에 보고한다.
|
같은 제작물의 유효한 선행 버전·실제 파일과 topic/story/scenes 승인을 확인하고 사용 버전을 inputs에 기록한다. 필요한 결과·승인이 없거나 stale이면 누락과 돌아갈 단계를 총괄에 보고한다. 같은 유효 승인 버전은 다시 묻지 않는다. 08의 제한된 대표 화면·짧은 움직임만 scenes 승인 전 검토용으로 허용하며 정식 10–12 전체 제작·완료와 구분한다. 새 08·09 승인 후 정식 제작한다.
|
||||||
|
|
||||||
선행 조건인 Qwen3-TTS 통합 WAV의 실측 컷, `gpt-image-2.5-sunburst`의 실제 PNG, `references/1.png` 그림체를 유지한다. 그림체 참고에 캠핑 소재를 강제하지 않는다. 이 스킬은 영상 엔진을 선택·구현하거나 실제 모델 API·영상 생성을 실행하지 않고 도구에 중립적인 요청과 받은 결과 확인을 담당한다.
|
원본 references/1.png를 보존하고 단순 형태·정돈된 색을 교육용 3D로 해석한다. 단순 배경·부드러운 조명·선명한 형태를 사용하며 평면 복제·캠핑 소재·상표를 강제하지 않는다. 02의 조사와 대본 근거로 모델·재질·방향·상태·수치를 확인하고 사실에 없는 구조를 만들지 않는다. 설명 텍스트는 검증한 합성 텍스트로 배치한다.
|
||||||
|
|
||||||
## 요청 작성
|
## 원본과 프레임 범위
|
||||||
|
|
||||||
`payload.request.clips`는 07의 컷 순서대로 모든 컷을 정확히 한 번 포함한다. 각 항목은 다음 기존 필드만 사용한다.
|
[12 양식](../../../templates/stages/12-motion.json)을 사용한다. 유효한 07/08/11, 실제 Qwen 통합 WAV의 실측 컷, 11의 검증된 .blend·시작/끝 PNG를 확인한다. request={engine:"Blender",scene_path,render_profile,clips}. scene_path는 11의 실제 원본 경로, render_profile은 11과 동일하다.
|
||||||
|
|
||||||
- `cut_id`: 07의 컷 ID. 08 장면과 11 프레임의 컷 참조가 같은지 확인한다.
|
clip={cut_id,start_frame_id,end_frame_id,duration_ms,motion_prompt,scene_name,start_frame,end_frame}. 07 순서의 모든 컷을 정확히 한 번 포함한다. 끝점 ID는 11의 같은 컷·위치이며 Scene 이름·논리 프레임도 일치해야 한다. start_frame/end_frame은 0 이상이며 end_frame>start_frame이다. duration_ms는 실측 end_ms-start_ms이고 0 초과 5000 이하이며 프레임 수×1000/fps와 정확히 같아야 한다. 미작성 null은 실행 준비가 아니다.
|
||||||
- `start_frame_id`, `end_frame_id`: 11 요청에서 해당 컷의 start/end인 ID. 11 결과의 `frame_id`로 실제 PNG를 찾고 `media.verified=true`와 이미지 내용을 확인한다.
|
|
||||||
- `duration_ms`: 07의 실측 `end_ms-start_ms`. 양수이고 5000ms 이하이며 글자 수 추정으로 대체하지 않는다.
|
|
||||||
- `motion_prompt`: 08의 시작→끝 상태, 설명에 필요한 물체·인물 동작, 흐름 방향과 카메라 동작을 전달한다. 별도 camera 필드를 만들지 않는다.
|
|
||||||
|
|
||||||
물높이 변화·부품 조작 등 원인과 결과를 보여주는 움직임을 우선한다. 줌·흔들림으로 설명을 대신하거나 근거 없는 구조·수치를 더하지 않는다. 시작/끝 이미지와 요청이 같은 변화를 설명해야 한다. continuous 연결은 이전 끝과 다음 시작의 위치·방향·카메라·인물·배경을 맞추고 cut 전환은 승인된 이유를 보존한다.
|
원인과 결과를 보여주는 실제 물체·상태 변화와 카메라 동작을 motion_prompt에 적고 줌·흔들림으로 설명을 대신하지 않는다. [start_frame,end_frame) 프레임을 렌더링하고 논리 번호+1을 Blender에 전달한다. continuous 경계의 실제 상태를 맞추고 cut의 서로 다른 Scene·캐시를 구별한다. PNG end 자체와 MP4의 마지막 프레임(end-1) 검사를 구분한다.
|
||||||
|
|
||||||
## 받은 결과 확인
|
result는 기존 null 또는 {clips:[{cut_id,media:video}]}다. 모든 요청 컷의 실제 MP4·길이·화면·동작·연속성을 검증한다. 요청과 실측이 다르면 12/11/08/07 중 문제 단계와 컷을 보고하고 음성·시간·속도를 임의 변경하지 않는다. 모든 파일이 확인되어야 13 합성에 전달한다.
|
||||||
|
|
||||||
요청만 준비되면 `payload.result=null`을 유지하고 awaiting_input으로 보고한다. 실제 결과는 `payload.result.clips`의 `{cut_id, media}`로 기록한다. 각 요청 cut_id에 MP4 한 개씩 대응해야 하며 누락·중복·요청 외 ID를 허용하지 않는다. 부분 결과는 보존하되 전체 요청을 받기 전 complete로 보고하지 않는다.
|
## 실제 결과와 전달
|
||||||
|
|
||||||
media는 기존 `{path, kind, verified, duration_ms, width, height}`다. path는 저장소 루트 기준 상대 경로, kind는 video다. 실제 파일 존재·MP4 형식·재생 내용·길이·화면 크기를 확인한 뒤에만 verified=true와 실측 메타데이터를 기록한다. 파일 미확인은 verified=false, 확인하지 못한 메타데이터는 null이다. 요청값이나 확장자만으로 실측했다고 쓰지 않는다.
|
승인된 저장소 내 Blender 실행 경로를 사용한다. 기존 설치를 무단 변경하거나 다른 도구로 바꾸지 않는다. 설치·요청 준비와 실제 렌더링 성공을 구분한다. .blend는 BlendFile={path,verified,sha256,blender_version}로 기록하고 실제 파일·해시·버전·재열기·Scene/자산을 검증한다. PNG/MP4 media로 위장하지 않는다. RenderProfile의 실제 지원을 확인하며 요청값을 실측 결과로 복사하지 않는다.
|
||||||
|
|
||||||
각 실제 클립 길이를 요청 duration_ms와 비교한다. 다르면 cut_id·요청/실측 길이·수정할 `12-motion`을 보고하며 임의로 컷·음성을 늘리거나 속도를 바꿔 통과시키지 않는다. 실제 시작/끝 상태와 동작·카메라·인접 연결도 확인한다. 프레임 문제는 `11-images`, 장면 설계 문제는 `08-scenes`, 시간 기준 문제는 `07-cuts`로 돌린다. 모든 컷의 실제 파일·길이·상태가 맞아야 합성 전달 준비로 보고한다.
|
media는 기존 여섯 키 {path,kind,verified,duration_ms,width,height}다. PNG는 image·duration_ms=null, MP4는 video·실측 양수 길이이며 실제 형식·해상도·9:16·내용을 확인한다. 확인한 파일만 verified=true이고 미확인 크기·시간은 null이다. 데이터 경로는 루트 상대 경로다. 실제 파일이 없으면 result=null·awaiting_input, 실행/검증 실패는 failed로 보고한다. 부분 결과와 실패 시도를 보존하며 전체 요청 결과가 검증되기 전 complete로 보고하지 않는다.
|
||||||
|
|
||||||
## 저장과 보고
|
자기 단계의 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 버전 review.md만 작성하고 이전 결과를 덮어쓰지 않는다. 실제 사용 버전·파일별 검사·명령·종료코드·미확인 영역·적용 원칙과 비적용 이유를 적는다. project.json·상태·현재 포인터·사용자 승인은 총괄만 갱신한다. 필드·열거값은 계약을 따르고 새 필수 입력·승인 지점을 만들지 않는다.
|
||||||
|
|
||||||
담당은 `projects/<project_id>/stages/12-motion/r<revision>/artifact.json`과 같은 버전 `review.md`만 작성한다. 이전 버전을 덮어쓰지 않고 [검토 양식](../../../templates/review.md)에 선행 버전, 요청 대비 실측 결과, 적용한 움직임 원칙·적용하지 않은 구성과 이유, 문제 단계·컷을 적는다.
|
|
||||||
|
|
||||||
총괄만 project.json의 상태·포인터·승인을 작성한다. 담당은 준비 여부·미확인 내용·후속 13/14 및 final 검토에 미치는 수정 영향을 보고한다. 사용자 final 승인 전 제작 완료를 선언하지 않는다.
|
|
||||||
|
|||||||
@@ -1,38 +1,30 @@
|
|||||||
---
|
---
|
||||||
name: short-video-references
|
name: short-video-references
|
||||||
description: 승인된 짧은 영상 장면과 반복 요소를 바탕으로 10 기준 이미지 요청서를 작성하고 실제 PNG 결과를 검증할 때 사용한다.
|
description: 승인된 장면과 반복 요소로 Blender 기준 모델·렌더 요청을 작성하고 10의 실제 .blend·PNG 자산과 고정 특징을 확인한다.
|
||||||
---
|
---
|
||||||
|
|
||||||
# 기준 이미지 요청과 결과 확인
|
# Blender 기준 모델과 이미지
|
||||||
|
|
||||||
10-references만 담당한다. 요청서 작성은 이미지 생성 성공이나 단계 완료가 아니다.
|
## 입력과 경계
|
||||||
|
|
||||||
## 읽을 자료와 시작 조건
|
[공통 계약](../../../docs/workflow-contracts.md), [전달 형식](../../../docs/contracts.md), [제작 지침](../../../docs/short-video-guide.md), [결과 스키마](../../../contracts/artifact.schema.json), [검토 양식](../../../templates/review.md)을 읽는다. 새 결과는 1.1이고 기존 1.0 결과를 보존·참조한다. 필수 입력 topic/language, Qwen3-TTS 기존 qwen3-tts 환경, 세로 9:16·최종 180000ms 이하·실측 컷 5000ms 이하를 유지한다.
|
||||||
|
|
||||||
- [공통 계약](../../../docs/workflow-contracts.md): 입력·버전·경로·선행 결과·승인·미디어 완료 기준.
|
같은 제작물의 유효한 선행 버전·실제 파일과 topic/story/scenes 승인을 확인하고 사용 버전을 inputs에 기록한다. 필요한 결과·승인이 없거나 stale이면 누락과 돌아갈 단계를 총괄에 보고한다. 같은 유효 승인 버전은 다시 묻지 않는다. 08의 제한된 대표 화면·짧은 움직임만 scenes 승인 전 검토용으로 허용하며 정식 10–12 전체 제작·완료와 구분한다. 새 08·09 승인 후 정식 제작한다.
|
||||||
- [제작 지침](../../../docs/short-video-guide.md): 근거와 숫자, 화면의 역할, 깔끔한 그림체와 작동 방식.
|
|
||||||
- [10 양식](../../../templates/stages/10-references.json), [결과 스키마](../../../contracts/artifact.schema.json), [검토 양식](../../../templates/review.md).
|
|
||||||
- [그림체 기준](../../../references/1.png): 실제 이미지를 열어 가는 윤곽선·단순 형태·정돈된 색면·제한적인 음영을 확인한다.
|
|
||||||
|
|
||||||
1. 제작물의 `topic`, `language`, 현재 결과와 검토 기록을 확인한다. 세로 9:16, 전체 180000ms 이내, 각 컷 0ms 초과 5000ms 이하 조건을 보존한다.
|
원본 references/1.png를 보존하고 단순 형태·정돈된 색을 교육용 3D로 해석한다. 단순 배경·부드러운 조명·선명한 형태를 사용하며 평면 복제·캠핑 소재·상표를 강제하지 않는다. 02의 조사와 대본 근거로 모델·재질·방향·상태·수치를 확인하고 사실에 없는 구조를 만들지 않는다. 설명 텍스트는 검증한 합성 텍스트로 배치한다.
|
||||||
2. 같은 제작물의 유효한 02-research, 08-scenes, 09-entities 결과를 읽고 실제 사용 버전을 `inputs`에 기록한다. 필요한 선행 자료가 없거나 stale이면 총괄에 보완할 단계와 이유를 보고한다.
|
|
||||||
3. 사용자가 07-cuts·08-scenes·09-entities의 현재 사용 버전을 scenes 검토에서 승인했는지 실제 응답과 `artifact_refs`로 확인한다. 그 전에 10 요청을 작성하거나 생성으로 넘어가지 않는다. topic·story 등 앞선 승인 경계도 유효해야 하며, 개별 호출은 선행 결과나 승인을 우회하지 않는다. 같은 승인 버전은 재승인을 요구하지 않는다.
|
|
||||||
|
|
||||||
## 요청서 작성
|
## 요청과 자산 확인
|
||||||
|
|
||||||
`payload.request`의 기존 `model`, `style_reference`, `items`만 사용한다. 모델은 `gpt-image-2.5-sunburst`, 그림체 경로는 `references/1.png`다. 이 경로와 모든 JSON 미디어 경로는 저장소 루트 기준이다.
|
[10 양식](../../../templates/stages/10-references.json)을 사용한다. 선행 결과는 유효한 02/08/09다. request={engine:"Blender",style_reference:"references/1.png",render_profile,items}이며 RenderProfile은 공통 계약을 따른다.
|
||||||
|
|
||||||
- 각 item은 유일한 `id`, `kind`, `entity_id`, `prompt`를 가진다. `kind=style`만 `entity_id=null`이며, character/background는 09의 해당 인물/배경 ID를 참조한다. 스타일과 09에서 필요한 모든 인물·배경을 빠짐없이 다룬다.
|
item={id,kind,entity_id,prompt}. ID는 유일하고 kind는 style/character/background/object다. style/object의 entity_id는 null, character/background는 실제 09의 해당 ID다. 스타일과 필요한 인물·배경·물체를 빠짐없이 요청하고 고정 특징·근거·08 상태를 prompt에 연결한다. 예제의 fps·samples·seed를 모든 제작의 고정값으로 취급하지 않는다.
|
||||||
- 프롬프트에 08의 장면·컷 ID, 09의 인물·배경 ID와 고정 특징을 연결한다. 고정 특징을 유지하고 의상·표정·시간에 따른 변화는 해당 장면에서 허용된 변화로 명시한다. 기준 이미지에 등장한 인물을 모든 영상의 고정 인물로 지정하지 않는다.
|
|
||||||
- 02의 확인한 주장·출처를 근거로 작동 원리와 단면·지도·주석의 구조·재료·방향·수치를 점검한다. 선행 장면이 근거와 충돌하면 임의로 바꾸지 말고 수정할 단계와 문제를 보고한다.
|
|
||||||
- 첨부 그림체를 적용하며 참고 Shorts의 입체 렌더링을 강제하지 않는다. 캠핑 소재·인물·상표를 복제하지 않는다. 표현을 단순화해도 사실에 중요한 재료·구조의 차이는 남긴다. 부정확한 생성 글자·숫자는 검증한 텍스트를 합성 단계에 배치하도록 보고한다.
|
|
||||||
|
|
||||||
실제 제작 시 해당 모델과 세로 출력 지원을 확인한다. 확인하지 않은 API 파라미터를 고정하거나 다른 모델로 무단 대체하지 않는다. 지원·결과가 확인되지 않으면 요청서와 미확인 내용을 남긴다.
|
result는 null 또는 {scene_file,items}이며 결과 item={reference_id,object_name,media:image}다. 모든 요청 ID가 누락·중복·추가 없이 대응해야 한다. object_name은 실제 .blend의 오브젝트/컬렉션 이름이다. 모델·재질·고정 특징과 PNG를 함께 확인하고 불일치는 장면/요소/조사 단계로 보고한다.
|
||||||
|
|
||||||
## 결과 검증과 전달
|
## 실제 결과와 전달
|
||||||
|
|
||||||
- 결과가 없으면 `payload.result=null`로 두고 총괄에 `awaiting_input`을 보고한다. 실제 받은 부분 결과는 `result.items`에 보존하되 전체 완료로 보고하지 않는다.
|
승인된 저장소 내 Blender 실행 경로를 사용한다. 기존 설치를 무단 변경하거나 다른 도구로 바꾸지 않는다. 설치·요청 준비와 실제 렌더링 성공을 구분한다. .blend는 BlendFile={path,verified,sha256,blender_version}로 기록하고 실제 파일·해시·버전·재열기·Scene/자산을 검증한다. PNG/MP4 media로 위장하지 않는다. RenderProfile의 실제 지원을 확인하며 요청값을 실측 결과로 복사하지 않는다.
|
||||||
- 각 결과는 `reference_id`, `media`를 사용한다. `reference_id`는 요청 item의 `id`와 일치해야 하며, 중복·누락·알 수 없는 ID가 없어야 한다. 모든 스타일·인물·배경 요청의 실제 결과와 고정 특징을 대조한다.
|
|
||||||
- `media`는 기존 `{path, kind, verified, duration_ms, width, height}`만 사용한다. 실제 파일 존재·PNG 내용 형식·해상도를 확인하고 화면을 열어 확인한 경우만 `verified=true`로 기록한다. `kind=image`, `duration_ms=null`, width/height는 실제 측정값이다. 미확인 파일은 false, 미확인 크기는 null이며 예제 경로를 실제 결과로 기록하지 않는다. 세로 출력 조건도 실제 해상도로 확인한다.
|
media는 기존 여섯 키 {path,kind,verified,duration_ms,width,height}다. PNG는 image·duration_ms=null, MP4는 video·실측 양수 길이이며 실제 형식·해상도·9:16·내용을 확인한다. 확인한 파일만 verified=true이고 미확인 크기·시간은 null이다. 데이터 경로는 루트 상대 경로다. 실제 파일이 없으면 result=null·awaiting_input, 실행/검증 실패는 failed로 보고한다. 부분 결과와 실패 시도를 보존하며 전체 요청 결과가 검증되기 전 complete로 보고하지 않는다.
|
||||||
- 자기 단계의 새 `stages/10-references/r<revision>/artifact.json`과 `review.md`만 작성하고 이전 버전을 덮어쓰지 않는다. 검토 메모에 사용한 원칙·적용 결과·소재에 맞지 않아 적용하지 않은 원칙의 이유, 실제 모델·지원 확인 근거, 파일별 검증 결과와 남은 문제를 적는다. 새로운 JSON 필드·필수 입력·승인 지점은 만들지 않는다.
|
|
||||||
- 요청 전체와 실제 결과 검증이 충족되면 준비 여부를 총괄에 보고한다. `project.json`, 단계 상태·현재 포인터·사용자 승인은 총괄만 변경한다. 변경이 후속 이미지에 미치는 영향도 함께 보고한다.
|
자기 단계의 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 버전 review.md만 작성하고 이전 결과를 덮어쓰지 않는다. 실제 사용 버전·파일별 검사·명령·종료코드·미확인 영역·적용 원칙과 비적용 이유를 적는다. project.json·상태·현재 포인터·사용자 승인은 총괄만 갱신한다. 필드·열거값은 계약을 따르고 새 필수 입력·승인 지점을 만들지 않는다.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ description: 13-compose의 실제 완성본을 여섯 영역에서 검수해 14-
|
|||||||
|
|
||||||
개별 호출에서도 같은 제작물의 유효한 `13-compose`와 검수에 직접 사용한 선행 결과를 확인하고 실제 사용한 `{stage_id, revision}`을 `inputs`에 기록한다. 대본·제목·근거, 실측 음성·컷, 장면·인물·배경·이미지·영상은 검수에 필요한 해당 결과와 그 선행 관계를 읽는다. 다른 제작물·오래된 버전·stale 결과를 섞지 않는다.
|
개별 호출에서도 같은 제작물의 유효한 `13-compose`와 검수에 직접 사용한 선행 결과를 확인하고 실제 사용한 `{stage_id, revision}`을 `inputs`에 기록한다. 대본·제목·근거, 실측 음성·컷, 장면·인물·배경·이미지·영상은 검수에 필요한 해당 결과와 그 선행 관계를 읽는다. 다른 제작물·오래된 버전·stale 결과를 섞지 않는다.
|
||||||
|
|
||||||
project.json에서 story·scenes가 사용 버전과 연결된 실제 사용자 승인인지 확인한다. pending·changes_requested·stale 승인을 우회하지 않으며 같은 승인 버전은 재승인을 요구하지 않는다. 선행 조건인 Qwen3-TTS 음성, `gpt-image-2.5-sunburst` 이미지, `references/1.png` 그림체를 유지한다. 이 스킬은 실제 모델 API·영상 생성·합성 실행이나 엔진 선택을 담당하지 않는다.
|
project.json에서 story·scenes가 사용 버전과 연결된 실제 사용자 승인인지 확인한다. pending·changes_requested·stale 승인을 우회하지 않으며 같은 승인 버전은 재승인을 요구하지 않는다. 선행 조건인 Qwen3-TTS 음성, 승인된 Blender 교육용 3D·실제 컷 영상과 Remotion + FFmpeg 합성 결과를 확인한다. references/1.png 원본은 보존하고 기존 1.0 결과도 유효한 선행 자료로 참조한다. 이 스킬은 실제 최종 영상 검수만 담당하며 도구를 임의로 바꾸지 않는다. 1.1의 14 구조와 여섯 검수 영역을 유지한다.
|
||||||
|
|
||||||
13의 실제 MP4·SRT를 열고 영상을 끝까지 시청·청취한다. `media.verified=true`만으로 검수자의 관찰을 대신하지 않는다. 실제 최종 영상이 없거나 재생해 볼 수 없으면 recommendation=incomplete이며 확인하지 못한 영역은 not_checked로 남긴다. 빠진 결과·파일·승인과 돌아갈 단계를 총괄에 보고한다. 선행 파일 미확인은 verified=false, 미확인 메타데이터는 null로 취급하며 부분 결과의 완료를 인정하지 않는다.
|
13의 실제 MP4·SRT를 열고 영상을 끝까지 시청·청취한다. `media.verified=true`만으로 검수자의 관찰을 대신하지 않는다. 실제 최종 영상이 없거나 재생해 볼 수 없으면 recommendation=incomplete이며 확인하지 못한 영역은 not_checked로 남긴다. 빠진 결과·파일·승인과 돌아갈 단계를 총괄에 보고한다. 선행 파일 미확인은 verified=false, 미확인 메타데이터는 null로 취급하며 부분 결과의 완료를 인정하지 않는다.
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ description: 짧은 영상의 실제 컷마다 설명할 화면과 시작·끝
|
|||||||
4. 07 순서의 각 인접 컷 쌍에 connections를 정확히 하나 작성한다. from_cut_id·to_cut_id는 해당 인접 쌍을 참조하고 mode는 continuous 또는 cut이다. reason에 설명이 이어지거나 위치·시간·시점이 바뀌어야 하는 이유를 적는다.
|
4. 07 순서의 각 인접 컷 쌍에 connections를 정확히 하나 작성한다. from_cut_id·to_cut_id는 해당 인접 쌍을 참조하고 mode는 continuous 또는 cut이다. reason에 설명이 이어지거나 위치·시간·시점이 바뀌어야 하는 이유를 적는다.
|
||||||
5. continuous는 앞 컷 end_state와 다음 start_state의 인물·물체 위치, 흐름 방향, 카메라 상태를 맞춘다. cut은 새로운 시점·상태를 이해할 수 있게 제시한다. 일정한 간격만을 이유로 전환하지 않는다.
|
5. continuous는 앞 컷 end_state와 다음 start_state의 인물·물체 위치, 흐름 방향, 카메라 상태를 맞춘다. cut은 새로운 시점·상태를 이해할 수 있게 제시한다. 일정한 간격만을 이유로 전환하지 않는다.
|
||||||
|
|
||||||
정확한 필드·타입은 양식·스키마를 따른다. 기존 description·상태·camera·연결 필드에 담고 새 필드를 추가하지 않는다. 고정 그림체는 `references/1.png`를 따르되 이미지의 캠핑 소재를 새 배경으로 강제하지 않는다.
|
정확한 필드·타입은 양식·스키마를 따른다. 1.1의 description·상태·camera·연결과 preview 필드를 사용한다. 기존 1.0 입력은 보존·참조한다. 원본 `references/1.png`의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 평면 복제·캠핑 소재를 강제하지 않는다.
|
||||||
|
|
||||||
|
scenes 승인 전에 제한된 대표 Scene의 실제 .blend·PNG·짧은 MP4를 visual-designer/video-editor의 해당 책임으로 준비해 `payload.preview`에 기록할 수 있다. BlendFile·RenderProfile·sample의 정확한 구조는 공통 계약과 스키마를 따른다. sample ID·실제 컷 ID·파일·해시·버전·실제 렌더 프로필·판독성을 확인한다. 자료가 없으면 preview=null이며 준비 완료로 제시하지 않는다. 이 샘플은 기존 scenes 검토에 포함하는 품질 근거이고 정식 10–12 완료나 추가 승인 지점이 아니다. 새 08·09 승인 전 전체 제작을 하지 않는다.
|
||||||
|
|
||||||
## 제출과 검토 경계
|
## 제출과 검토 경계
|
||||||
|
|
||||||
|
|||||||
@@ -35,18 +35,18 @@ description: 주제와 언어로 14단계 짧은 영상 제작을 시작하거
|
|||||||
|
|
||||||
1. 01 후보·선택·범위의 topic 검토를 요청한다. 실제 사용자 승인 전 02를 시작하지 않는다.
|
1. 01 후보·선택·범위의 topic 검토를 요청한다. 실제 사용자 승인 전 02를 시작하지 않는다.
|
||||||
2. 02 근거와 03 대본·04 제목의 story 검토를 요청한다. 제목·첫 문장의 약속과 결말, 블록 연결·주장·비유의 한계를 제시한다. 승인 전 05를 시작하지 않는다.
|
2. 02 근거와 03 대본·04 제목의 story 검토를 요청한다. 제목·첫 문장의 약속과 결말, 블록 연결·주장·비유의 한계를 제시한다. 승인 전 05를 시작하지 않는다.
|
||||||
3. 검증된 실제 음성으로 07을 준비하고 08·09를 같은 묶음으로 완성해 scenes 검토를 요청한다. 실측 구간·상태 변화·연결·고정 특징과 주석 근거를 제시한다. 승인 전 10을 시작하지 않는다.
|
3. 검증된 실제 음성으로 07을 준비하고 08·09를 같은 묶음으로 완성해 scenes 검토를 요청한다. 실측 구간·상태 변화·연결·고정 특징과 주석 근거, 08 preview의 실제 대표 화면·짧은 움직임을 제시한다. 대표 샘플의 교육용 3D 품질을 같은 scenes 검토에서 확인한다. 승인 전에는 이 제한된 샘플만 허용하며 정식 10–12 전체 제작을 시작하지 않는다.
|
||||||
4. 실제 13 완성본과 14 검수 보고의 final 검토를 요청한다. 승인 전 제작 완료를 선언하지 않는다.
|
4. 실제 13 완성본과 14 검수 보고의 final 검토를 요청한다. 승인 전 제작 완료를 선언하지 않는다.
|
||||||
|
|
||||||
검토한 stage_id·revision은 artifact_refs에 고정하고 실제 사용자 응답을 feedback에 기록한다. 응답이 없으면 pending 결정과 awaiting_review 상태로 기다린다. 담당의 선택 제안·검수자의 pass를 사용자 승인으로 만들지 않는다. 변경 요청은 수정할 단계와 새 버전을 배정한다.
|
검토한 stage_id·revision은 artifact_refs에 고정하고 실제 사용자 응답을 feedback에 기록한다. 응답이 없으면 pending 결정과 awaiting_review 상태로 기다린다. 담당의 선택 제안·검수자의 pass를 사용자 승인으로 만들지 않는다. 변경 요청은 수정할 단계와 새 버전을 배정한다.
|
||||||
|
|
||||||
## 실제 미디어가 없는 경우
|
## 실제 미디어가 없는 경우
|
||||||
|
|
||||||
현재 구성은 요청·결과 확인 지침과 양식이며 생성·합성을 실행하는 프로그램은 제공하지 않는다. 06은 기존 qwen3-tts 환경의 Qwen3-TTS, 10–11은 gpt-image-2.5-sunburst로 요청한다. 실제 제작 도구의 모델·화자·언어·출력 지원은 그때 확인하며 전역 환경 재설치·무단 대체를 하지 않는다. 12·13은 특정 영상·합성 엔진을 선택하지 않은 전달 계약이다.
|
새 양식·결과는 계약 1.1이며 새 프로젝트 settings.visual_engine은 Blender다. 06은 기존 qwen3-tts 환경의 Qwen3-TTS, 10–12는 승인된 저장소 내 Blender 실행 경로, 13은 기존 Remotion + FFmpeg 합성 경로를 사용한다. 기존 1.0 결과·승인·WAV를 보존하고 유효한 선행 버전으로 참조한다. 전역 환경 재설치·무단 도구 대체를 하지 않고 설치 확인과 실제 실행 성공을 구분한다.
|
||||||
|
|
||||||
result=null 또는 필수 실제 자료 부재는 awaiting_input이다. 다음 담당에게 필수 파일이 준비됐다고 보고하지 않는다. 결과 제출 시 요청 ID·선행 버전·모든 항목·파일 존재·형식·실측 메타데이터를 확인한다. 부분 제출은 보존하지만 전 단계 완료가 아니다. 실패는 원인과 blocking 여부를 issues에 기록하고 failed로 보고한다.
|
result=null 또는 필수 실제 자료 부재는 awaiting_input이다. 다음 담당에게 필수 파일이 준비됐다고 보고하지 않는다. 결과 제출 시 요청 ID·선행 버전·모든 항목·파일 존재·형식·실측 메타데이터를 확인한다. 부분 제출은 보존하지만 전 단계 완료가 아니다. 실패는 원인과 blocking 여부를 issues에 기록하고 failed로 보고한다.
|
||||||
|
|
||||||
세로 9:16, 최종 180000ms 이내, 각 컷 0ms 초과 5000ms 이하를 확인한다. 그림체는 references/1.png의 윤곽선·단순 형태·색면 기준이며 캠핑 소재·인물·상표를 강제하지 않는다. 07은 실제 통합 음성을 0부터 끝까지 덮고 자막은 별도로 정렬한다. 예상 시간·가상 경로는 실제 확인 근거가 아니다. 음성 길이 초과는 대본 수정과 story 재승인으로 돌린다.
|
세로 9:16, 최종 180000ms 이내, 각 컷 0ms 초과 5000ms 이하를 확인한다. 원본 references/1.png를 보존하고 단순 형태·정돈된 색을 교육용 3D로 해석한다. 단순 배경·부드러운 조명·선명한 형태를 사용하며 평면 복제와 캠핑 소재·인물·상표를 강제하지 않는다. 07은 실제 통합 음성을 0부터 끝까지 덮고 자막은 별도로 정렬한다. 예상 시간·가상 경로는 실제 확인 근거가 아니다. 음성 길이 초과는 대본 수정과 story 재승인으로 돌린다.
|
||||||
|
|
||||||
## 변경과 완료
|
## 변경과 완료
|
||||||
|
|
||||||
|
|||||||
@@ -6,4 +6,4 @@
|
|||||||
|
|
||||||
공유 진행·현재 포인터·승인은 총괄만 작성한다. 다른 담당은 자기 배정 결과·검토를 제출한다. 완료는 실제 파일·실측·필요한 사용자 승인을 확인한 상태이고 요청서·예상·검수자 추천으로 대신하지 않는다.
|
공유 진행·현재 포인터·승인은 총괄만 작성한다. 다른 담당은 자기 배정 결과·검토를 제출한다. 완료는 실제 파일·실측·필요한 사용자 승인을 확인한 상태이고 요청서·예상·검수자 추천으로 대신하지 않는다.
|
||||||
|
|
||||||
역할을 바꾸면 TOML 파싱·필수 키·이름·담당 단계와 스킬 참조의 존재를 확인한다. 새 필드·추가 승인·도구 대체를 역할 지침에만 도입하지 않는다. 참조 경로는 형식 확인과 실제 파일 탐색을 구분해 검증한다.
|
역할을 바꾸면 TOML 파싱·필수 키·이름·담당 단계와 스킬 참조의 존재를 확인한다. 1.1 Blender 계약·08 대표 샘플의 scenes 검토·승인된 실행 경로를 공통 문서와 일치시킨다. 새 필드·추가 승인·도구 대체를 역할 지침에만 도입하지 않는다. 참조 경로는 형식 확인과 실제 파일 탐색을 구분해 검증한다.
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 경계와 보고
|
담당 경계와 보고
|
||||||
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 경계와 보고
|
담당 경계와 보고
|
||||||
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
||||||
@@ -30,5 +30,5 @@ developer_instructions = '''
|
|||||||
완료 조건
|
완료 조건
|
||||||
- 전체 음성을 덮는 컷·자막 시간, 언어·내용·순서·식별자 참조, 모든 컷의 장면·등장 요소·인접 연결을 확인한다. 07·08·09의 scenes 실제 승인이 있어야 완료다.
|
- 전체 음성을 덮는 컷·자막 시간, 언어·내용·순서·식별자 참조, 모든 컷의 장면·등장 요소·인접 연결을 확인한다. 07·08·09의 scenes 실제 승인이 있어야 완료다.
|
||||||
보류 기준
|
보류 기준
|
||||||
- 통합 WAV·실측·정렬 확인이 없으면 예상 시간을 확정하지 않고 총괄에게 보고한다. 승인 전에 유효한 07로 08·09를 준비할 수 있으나 10으로 넘어가지 않는다. 180000ms 초과는 대본 수정과 story 재승인으로 보고한다.
|
- 통합 WAV·실측·정렬 확인이 없으면 예상 시간을 확정하지 않고 총괄에게 보고한다. 승인 전에 유효한 07로 08·09와 제한된 08 대표 .blend·PNG·짧은 MP4를 준비해 같은 scenes 검토에 제시할 수 있다. 교육용 3D 품질·상태 변화·카메라·실제 원본 근거를 확인하고 정식 10–12는 새 08·09 승인 후 시작한다. 180000ms 초과는 대본 수정과 story 재승인으로 보고한다.
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 경계와 보고
|
담당 경계와 보고
|
||||||
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 경계와 보고
|
담당 경계와 보고
|
||||||
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 범위와 읽을 지침
|
담당 범위와 읽을 지침
|
||||||
- 전체 01-topic, 02-research, 03-script, 04-title, 05-tts-split, 06-tts, 07-cuts, 08-scenes, 09-entities, 10-references, 11-images, 12-motion, 13-compose, 14-review를 총괄한다.
|
- 전체 01-topic, 02-research, 03-script, 04-title, 05-tts-split, 06-tts, 07-cuts, 08-scenes, 09-entities, 10-references, 11-images, 12-motion, 13-compose, 14-review를 총괄한다.
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 경계와 보고
|
담당 경계와 보고
|
||||||
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
||||||
@@ -18,12 +18,12 @@ developer_instructions = '''
|
|||||||
- 진행 불가 시 부분 결과를 보존하고 이유, 누락 자료·실제 파일·승인, 재개에 필요한 조건, 돌아갈 단계와 권장 상태(awaiting_input/awaiting_review/failed)를 총괄에게 보고한다. 실행·검증 실패는 failed, 변경된 선행 결과는 stale 대상과 영향 범위를 제안한다. 없는 근거·파일·승인을 만들어 진행하지 않는다.
|
- 진행 불가 시 부분 결과를 보존하고 이유, 누락 자료·실제 파일·승인, 재개에 필요한 조건, 돌아갈 단계와 권장 상태(awaiting_input/awaiting_review/failed)를 총괄에게 보고한다. 실행·검증 실패는 failed, 변경된 선행 결과는 stale 대상과 영향 범위를 제안한다. 없는 근거·파일·승인을 만들어 진행하지 않는다.
|
||||||
|
|
||||||
담당 범위와 읽을 지침
|
담당 범위와 읽을 지침
|
||||||
- 담당 단계는 12-motion, 13-compose다. 단계 스킬 .agents/skills/short-video-motion/SKILL.md와 .agents/skills/short-video-compose/SKILL.md를 읽는다.
|
- 담당 단계는 12-motion, 13-compose다. scenes 검토용 제한된 08 짧은 대표 영상은 장면 담당의 배정과 08 preview 계약 안에서 지원하며 전체 컷 제작과 구분한다. 단계 스킬 .agents/skills/short-video-motion/SKILL.md와 .agents/skills/short-video-compose/SKILL.md를 읽는다.
|
||||||
- docs/short-video-guide.md의 음성을 기준으로 컷과 연결을 확정한다, 깔끔한 그림체로 작동 방식을 보여준다 중 움직임 부분, 자막과 주석을 읽을 수 있게 배치한다, 최종 영상 검토를 읽는다.
|
- docs/short-video-guide.md의 음성을 기준으로 컷과 연결을 확정한다, 깔끔한 그림체로 작동 방식을 보여준다 중 움직임 부분, 자막과 주석을 읽을 수 있게 배치한다, 최종 영상 검토를 읽는다.
|
||||||
입력
|
입력
|
||||||
- 12는 유효한 07-cuts·08-scenes·11-images와 실제 시작/끝 PNG, 13은 03-script·04-title·06-tts·07-cuts·12-motion의 지정 버전과 실제 WAV·컷 MP4다.
|
- 12는 유효한 07-cuts·08-scenes·11-images와 실제 시작/끝 PNG, 13은 03-script·04-title·06-tts·07-cuts·12-motion의 지정 버전과 실제 WAV·컷 MP4다.
|
||||||
출력
|
출력
|
||||||
- templates/stages/12-motion.json에 각 컷의 start_frame_id·end_frame_id·실측 컷 duration_ms·motion_prompt 요청을 작성한다. 설명에 필요한 상태 변화와 연속 기준을 보존한다. 받은 MP4 결과를 cut_id에 연결한다.
|
- templates/stages/12-motion.json에 각 컷의 start_frame_id·end_frame_id·실측 컷 duration_ms·motion_prompt·실제 scene_name·[start_frame,end_frame) 요청을 작성한다. 11 실제 .blend와 같은 RenderProfile을 사용하며 논리 프레임을 Blender 번호(+1)로 평가한다. 설명에 필요한 상태 변화와 연속 기준을 보존한다. cut의 Scene을 구별하고 캐시 키에 Scene 이름을 포함한다. 받은 MP4 결과를 cut_id에 연결한다.
|
||||||
- templates/stages/13-compose.json에 timeline·통합 narration_path·captions·title 요청을 작성한다. 실제 받은 최종 MP4와 SRT를 result에 연결한다. 데이터 경로는 루트 기준이며 가상 파일을 실제 결과로 쓰지 않는다.
|
- templates/stages/13-compose.json에 timeline·통합 narration_path·captions·title 요청을 작성한다. 실제 받은 최종 MP4와 SRT를 result에 연결한다. 데이터 경로는 루트 기준이며 가상 파일을 실제 결과로 쓰지 않는다.
|
||||||
완료 조건
|
완료 조건
|
||||||
- 12의 모든 컷·프레임 참조·실제 길이·시작/끝 상태가 07·08·11과 맞는다. 13의 컷 순서·타임라인·통합 음성·제목·입력 언어 자막이 일치하며 실제 MP4의 너비·높이·9:16·양수 길이·180000ms 이하와 SRT 존재·내용·정렬을 확인한다.
|
- 12의 모든 컷·프레임 참조·실제 길이·시작/끝 상태가 07·08·11과 맞는다. 13의 컷 순서·타임라인·통합 음성·제목·입력 언어 자막이 일치하며 실제 MP4의 너비·높이·9:16·양수 길이·180000ms 이하와 SRT 존재·내용·정렬을 확인한다.
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 경계와 보고
|
담당 경계와 보고
|
||||||
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ developer_instructions = '''
|
|||||||
공통 계약
|
공통 계약
|
||||||
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
- 아래 모든 읽을 경로와 결과의 데이터 경로는 저장소 루트 기준이다. 실행 위치나 이 TOML의 위치를 기준으로 해석하지 않는다.
|
||||||
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
- 먼저 docs/workflow-contracts.md, contracts/project.schema.json, contracts/artifact.schema.json, templates/project.json, templates/review.md를 읽는다. 담당 단계의 templates/stages/<stage_id>.json 구조와 docs/short-video-guide.md의 지정 절을 따른다.
|
||||||
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 이미지 모델 gpt-image-2.5-sunburst를 유지한다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다.
|
- 필수 제작 입력은 topic, language다. 입력 언어로 대본·제목·내레이션·자막을 작성한다. 세로 9:16, 최종 180000ms 이하, 각 컷 0ms 초과 5000ms 이하, 그림체 references/1.png, Qwen3-TTS와 conda 환경 qwen3-tts, 새 제작의 시각 엔진 Blender를 유지한다. references/1.png의 단순 형태·정돈된 색을 교육용 3D로 해석하고 단순 배경·부드러운 조명·선명한 형태를 사용한다. 원본을 보존하며 평면 복제·캠핑 소재·인물·상표를 강제하지 않는다.
|
||||||
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. schema_version=1.0과 기존 필드만 사용한다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
- 프로젝트의 현재 포인터·선행 버전·실제 파일·승인을 읽어 유효성을 확인한다. 결과는 projects/<project_id>/stages/<stage_id>/r<revision>/artifact.json과 같은 위치의 review.md에 작성한다. 새 결과는 schema_version=1.1과 해당 계약 필드만 사용한다. 기존 1.0 결과는 그대로 읽고 유효한 선행 결과로 참조할 수 있다. inputs에는 실제 사용한 같은 제작물의 유효한 {stage_id, revision}을 기록한다. 중복·자기 참조를 금지한다.
|
||||||
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
- 버전은 1부터 시작한다. 총괄이 배정한 단계·새 버전만 작성하고 이전 버전을 덮어쓰지 않는다. 같은 단계의 같은 버전을 동시에 작성하지 않는다. 수정 영향은 실제 inputs 관계를 따라 판단하고 관계없는 결과는 보존한다.
|
||||||
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
- 기존 review.md에 적용한 제작 원칙·결과와 소재상 적용하지 않은 구성의 이유를 요약한다. 사실에 없는 위기·반전·대안 실패를 만들지 않는다. 새 필수 JSON 필드·제작 입력·승인 지점을 추가하지 않는다.
|
||||||
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
- 요청과 실제 결과를 구분한다. result=null 또는 필수 파일·자료 부재는 awaiting_input으로 보고한다. 부분 결과는 보존하고 모두 받기 전에 완료로 보고하지 않는다. 실제 존재·형식·메타데이터를 확인한 media만 verified=true로 기록한다. 예상 시간·예제 경로·확장자를 실측·검증 근거로 쓰지 않는다.
|
||||||
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
- 네 사용자 검토는 topic(01→02), story(02 근거·03/04→05), scenes(07/08/09와 08 대표 샘플→10), final(13/14→제작 완료)이다. 실제 사용자 응답만 승인이다. 담당의 추천이나 응답 없음은 승인이 아니다. 동일한 유효 승인 버전으로 재개하면 재승인을 요구하지 않는다.
|
||||||
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 실제 API·미디어 실행 프로그램을 새로 구현하거나 영상 생성·합성 엔진을 임의로 선택하지 않는다.
|
- 모델·추론 노력·도구·권한 등 세션 설정은 부모의 설정을 상속한다. 사용자 전체 설정·전역 설정·등록 파일을 변경하지 않는다. 승인된 저장소 내 Blender 실행 경로와 기존 Remotion + FFmpeg 합성 경로를 사용한다. 설치 확인과 실제 렌더링 성공을 구분하고 실행 경로·도구를 임의로 대체하지 않는다.
|
||||||
|
|
||||||
담당 경계와 보고
|
담당 경계와 보고
|
||||||
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
- 자신의 담당 단계 결과와 review.md만 작성한다. projects/<project_id>/project.json의 현재 결과 포인터·단계 상태·승인 기록은 총괄만 갱신한다. 담당 밖의 결과·승인·공유 상태를 변경하지 않는다.
|
||||||
@@ -18,15 +18,15 @@ developer_instructions = '''
|
|||||||
- 진행 불가 시 부분 결과를 보존하고 이유, 누락 자료·실제 파일·승인, 재개에 필요한 조건, 돌아갈 단계와 권장 상태(awaiting_input/awaiting_review/failed)를 총괄에게 보고한다. 실행·검증 실패는 failed, 변경된 선행 결과는 stale 대상과 영향 범위를 제안한다. 없는 근거·파일·승인을 만들어 진행하지 않는다.
|
- 진행 불가 시 부분 결과를 보존하고 이유, 누락 자료·실제 파일·승인, 재개에 필요한 조건, 돌아갈 단계와 권장 상태(awaiting_input/awaiting_review/failed)를 총괄에게 보고한다. 실행·검증 실패는 failed, 변경된 선행 결과는 stale 대상과 영향 범위를 제안한다. 없는 근거·파일·승인을 만들어 진행하지 않는다.
|
||||||
|
|
||||||
담당 범위와 읽을 지침
|
담당 범위와 읽을 지침
|
||||||
- 담당 단계는 10-references, 11-images다. 단계 스킬 .agents/skills/short-video-references/SKILL.md와 .agents/skills/short-video-images/SKILL.md를 읽는다.
|
- 담당 단계는 10-references, 11-images다. scenes 검토를 위한 제한된 08 대표 모델·PNG도 장면 담당의 배정과 08 preview 계약 안에서 지원하며 정식 10–12 완료로 취급하지 않는다. 단계 스킬 .agents/skills/short-video-references/SKILL.md와 .agents/skills/short-video-images/SKILL.md를 읽는다.
|
||||||
- docs/short-video-guide.md의 근거와 숫자는 작성 전에 정리한다, 설명의 단위를 화면으로 바꾼다, 깔끔한 그림체로 작동 방식을 보여준다, 자막과 주석을 읽을 수 있게 배치한다를 읽는다.
|
- docs/short-video-guide.md의 근거와 숫자는 작성 전에 정리한다, 설명의 단위를 화면으로 바꾼다, 깔끔한 그림체로 작동 방식을 보여준다, 자막과 주석을 읽을 수 있게 배치한다를 읽는다.
|
||||||
입력
|
입력
|
||||||
- 10은 유효한 02-research·08-scenes·09-entities와 scenes 승인, 11은 02-research·03-script·07-cuts·08-scenes·09-entities·10-references의 지정 버전과 실제 기준 PNG다. references/1.png를 보고 그림체를 확인한다.
|
- 10은 유효한 02-research·08-scenes·09-entities와 scenes 승인, 11은 02-research·03-script·07-cuts·08-scenes·09-entities·10-references의 지정 버전과 실제 기준 PNG다. references/1.png를 보고 그림체를 확인한다.
|
||||||
출력
|
출력
|
||||||
- templates/stages/10-references.json에 gpt-image-2.5-sunburst·references/1.png와 style/character/background 요청을 작성한다. style만 entity_id=null이며 나머지는 유효한 요소 ID를 연결한다. 받은 실제 PNG를 요청 reference_id에 연결한다.
|
- templates/stages/10-references.json에 Blender·references/1.png·RenderProfile과 style/character/background/object 요청을 작성한다. style/object는 entity_id=null이며 나머지는 유효한 09 요소 ID를 연결한다. 실제 .blend·해시·버전과 object_name의 오브젝트/컬렉션, 실제 PNG를 요청 reference_id에 연결한다.
|
||||||
- templates/stages/11-images.json에 각 컷의 start/end 요청과 reference_ids를 작성한다. 받은 실제 PNG를 frame_id에 연결하고 장면 상태·조사 근거·고정 특징·연속성을 확인한다.
|
- templates/stages/11-images.json에 각 컷의 start/end·scene_name·논리 frame_index와 reference_ids를 작성하고 같은 컷 두 위치의 Scene을 일치시킨다. 실제 .blend와 RenderProfile을 기록한다. 받은 실제 PNG를 frame_id에 연결하고 장면 상태·조사 근거·고정 특징·연속성을 확인한다.
|
||||||
완료 조건
|
완료 조건
|
||||||
- 10의 모든 요청 ID·고정 특징과 11의 모든 컷에 start/end가 각각 정확히 하나씩 있으며 실제 PNG의 존재·형식·너비·높이·내용을 확인한다. 세로 9:16 제작에 필요한 출력과 기준 그림체를 검토하고 숫자·글자의 정확성을 확인한다.
|
- 10의 모든 요청 ID·고정 특징과 11의 모든 컷에 start/end가 각각 정확히 하나씩 있으며 실제 PNG의 존재·형식·너비·높이·내용을 확인한다. 세로 9:16 제작에 필요한 출력과 기준 그림체를 검토하고 숫자·글자의 정확성을 확인한다.
|
||||||
보류 기준
|
보류 기준
|
||||||
- scenes 승인·스타일 기준·사실 근거·기준 이미지·실제 PNG 또는 지정 모델·세로 출력 지원이 없으면 누락을 총괄에게 보고한다. 다른 모델이나 확인하지 않은 API 파라미터로 대체하지 않는다. 부정확한 생성 글자·숫자는 검증한 합성 텍스트 배치 대상으로 보고한다.
|
- scenes 승인·스타일 기준·사실 근거·기준 이미지·실제 PNG 또는 Blender 실행·세로 출력 지원이 없으면 누락을 총괄에게 보고한다. 다른 엔진이나 확인하지 않은 실행 파라미터로 대체하지 않는다. 부정확한 생성 글자·숫자는 검증한 합성 텍스트 배치 대상으로 보고한다.
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 프로젝트 작업 지침
|
# 프로젝트 작업 지침
|
||||||
|
|
||||||
ShortVideoGenerator는 혼자 Codex에서 사용하는 짧은 영상 제작 프로젝트다. 주제와 언어를 제작마다 입력하고 14단계의 역할 지침·스킬·JSON 양식과 사용자 검토를 연결한다. 분야별 특화와 실제 생성·합성 도구 연결은 이후 작업에서 다룬다.
|
ShortVideoGenerator는 혼자 Codex에서 사용하는 짧은 영상 제작 프로젝트다. 주제와 언어를 제작마다 입력하고 14단계의 역할 지침·스킬·JSON 양식과 사용자 검토를 연결한다. 분야별 장면 제작은 별도 작업으로 구체화하며 Blender 모델·애니메이션과 기존 Remotion + FFmpeg 합성 경로를 연결한다.
|
||||||
|
|
||||||
## 작업 전에 확인
|
## 작업 전에 확인
|
||||||
|
|
||||||
@@ -12,9 +12,9 @@ ShortVideoGenerator는 혼자 Codex에서 사용하는 짧은 영상 제작 프
|
|||||||
## 유지할 제작 기준
|
## 유지할 제작 기준
|
||||||
|
|
||||||
- 필수 입력은 주제·언어, 출력은 세로 9:16·최종 3분 이내·음성 기준 각 컷 5초 이내다. 쉬운 표현은 어린이 전용이라는 뜻이 아니다.
|
- 필수 입력은 주제·언어, 출력은 세로 9:16·최종 3분 이내·음성 기준 각 컷 5초 이내다. 쉬운 표현은 어린이 전용이라는 뜻이 아니다.
|
||||||
- 스타일은 references/1.png의 그림체다. 음성은 Qwen3-TTS의 기존 qwen3-tts 환경, 이미지는 gpt-image-2.5-sunburst다. 사용자 전체 환경·설정을 변경하거나 도구를 무단 대체하지 않는다.
|
- 원본 references/1.png를 보존하고 단순 형태·정돈된 색을 깔끔한 교육용 3D로 해석한다. 단순한 배경·부드러운 조명·선명한 형태를 사용하며 평면 복제를 강제하지 않는다. 음성은 Qwen3-TTS의 기존 qwen3-tts 환경, 새 시각 제작은 Blender다. 사용자 전체 환경·설정을 변경하거나 도구를 무단 대체하지 않는다.
|
||||||
- topic/story/scenes/final의 실제 사용자 승인 없이 다음 경계를 넘지 않는다. 같은 승인 버전으로 재개하면 다시 묻지 않는다.
|
- topic/story/scenes/final의 실제 사용자 승인 없이 다음 경계를 넘지 않는다. 같은 승인 버전으로 재개하면 다시 묻지 않는다. scenes 승인 전에는 08의 제한된 대표 화면·짧은 움직임만 제작해 검토 근거로 사용하며 정식 10–12 완료로 처리하지 않는다. 새 08·09 승인 전 전체 제작을 시작하지 않는다.
|
||||||
- 총괄만 project.json을 작성한다. 담당은 자기 새 버전의 결과·검토를 제출하고 이전 결과를 보존한다. 요청·예상·예제와 실제 결과·실측·승인을 구분한다.
|
- 새 양식·결과는 계약 1.1, 기존 1.0 결과는 보존·참조한다. .blend 원본은 BlendFile로 기록하며 PNG·MP4 media로 위장하지 않는다. 총괄만 project.json을 작성한다. 담당은 자기 새 버전의 결과·검토를 제출하고 이전 결과를 보존한다. 요청·예상·예제와 실제 결과·실측·승인을 구분한다.
|
||||||
|
|
||||||
## 프로젝트 구조
|
## 프로젝트 구조
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# 프로젝트 작업 지침
|
# 프로젝트 작업 지침
|
||||||
|
|
||||||
ShortVideoGenerator는 혼자 Codex에서 사용하는 짧은 영상 제작 프로젝트다. 주제와 언어를 제작마다 입력하고 14단계의 역할 지침·스킬·JSON 양식과 사용자 검토를 연결한다. 분야별 특화와 실제 생성·합성 도구 연결은 이후 작업에서 다룬다.
|
ShortVideoGenerator는 혼자 Codex에서 사용하는 짧은 영상 제작 프로젝트다. 주제와 언어를 제작마다 입력하고 14단계의 역할 지침·스킬·JSON 양식과 사용자 검토를 연결한다. 분야별 장면 제작은 별도 작업으로 구체화하며 Blender 모델·애니메이션과 기존 Remotion + FFmpeg 합성 경로를 연결한다.
|
||||||
|
|
||||||
## 작업 전에 확인
|
## 작업 전에 확인
|
||||||
|
|
||||||
@@ -12,9 +12,9 @@ ShortVideoGenerator는 혼자 Codex에서 사용하는 짧은 영상 제작 프
|
|||||||
## 유지할 제작 기준
|
## 유지할 제작 기준
|
||||||
|
|
||||||
- 필수 입력은 주제·언어, 출력은 세로 9:16·최종 3분 이내·음성 기준 각 컷 5초 이내다. 쉬운 표현은 어린이 전용이라는 뜻이 아니다.
|
- 필수 입력은 주제·언어, 출력은 세로 9:16·최종 3분 이내·음성 기준 각 컷 5초 이내다. 쉬운 표현은 어린이 전용이라는 뜻이 아니다.
|
||||||
- 스타일은 references/1.png의 그림체다. 음성은 Qwen3-TTS의 기존 qwen3-tts 환경, 이미지는 gpt-image-2.5-sunburst다. 사용자 전체 환경·설정을 변경하거나 도구를 무단 대체하지 않는다.
|
- 원본 references/1.png를 보존하고 단순 형태·정돈된 색을 깔끔한 교육용 3D로 해석한다. 단순한 배경·부드러운 조명·선명한 형태를 사용하며 평면 복제를 강제하지 않는다. 음성은 Qwen3-TTS의 기존 qwen3-tts 환경, 새 시각 제작은 Blender다. 사용자 전체 환경·설정을 변경하거나 도구를 무단 대체하지 않는다.
|
||||||
- topic/story/scenes/final의 실제 사용자 승인 없이 다음 경계를 넘지 않는다. 같은 승인 버전으로 재개하면 다시 묻지 않는다.
|
- topic/story/scenes/final의 실제 사용자 승인 없이 다음 경계를 넘지 않는다. 같은 승인 버전으로 재개하면 다시 묻지 않는다. scenes 승인 전에는 08의 제한된 대표 화면·짧은 움직임만 제작해 검토 근거로 사용하며 정식 10–12 완료로 처리하지 않는다. 새 08·09 승인 전 전체 제작을 시작하지 않는다.
|
||||||
- 총괄만 project.json을 작성한다. 담당은 자기 새 버전의 결과·검토를 제출하고 이전 결과를 보존한다. 요청·예상·예제와 실제 결과·실측·승인을 구분한다.
|
- 새 양식·결과는 계약 1.1, 기존 1.0 결과는 보존·참조한다. .blend 원본은 BlendFile로 기록하며 PNG·MP4 media로 위장하지 않는다. 총괄만 project.json을 작성한다. 담당은 자기 새 버전의 결과·검토를 제출하고 이전 결과를 보존한다. 요청·예상·예제와 실제 결과·실측·승인을 구분한다.
|
||||||
|
|
||||||
## 프로젝트 구조
|
## 프로젝트 구조
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
이 영역은 진행 기록과 14단계 결과의 JSON Schema Draft 2020-12 구조를 관리한다. 실제 파일 측정·모델 추론·사용자 승인 실행을 구현하지 않으며 스킬·양식·예제를 임의로 변경하지 않는다.
|
이 영역은 진행 기록과 14단계 결과의 JSON Schema Draft 2020-12 구조를 관리한다. 실제 파일 측정·모델 추론·사용자 승인 실행을 구현하지 않으며 스킬·양식·예제를 임의로 변경하지 않는다.
|
||||||
|
|
||||||
필드명·타입·단계 종류·상태 열거값을 보존한다. 결과는 공통 버전·입력 참조와 단계별 payload를 갖는다. 진행 기록에는 14단계와 네 검토가 각각 한 번 필요하다. 외부 결과 부재는 null, 미확인 미디어는 verified=false다.
|
기존 1.0 정의·단계 종류·상태 열거값을 보존하고 1.1 Blender 계약을 버전 분기로 추가한다. .blend는 BlendFile이며 기존 여섯 키 media의 종류를 늘리지 않는다. 결과는 공통 버전·입력 참조와 단계별 payload를 갖는다. 진행 기록에는 14단계와 네 검토가 각각 한 번 필요하다. 외부 결과 부재는 null, 미확인 미디어는 verified=false다.
|
||||||
|
|
||||||
구조상 유효한 빈 결과가 완료를 뜻하지 않는다. 사용자 응답·실제 파일·식별자 참조·시간 연속성은 별도 의미 확인이 필요하다. 미검수 또는 blocking 발견이 있는 검수 결과를 pass 구조로 허용하지 않는다.
|
구조상 유효한 빈 결과가 완료를 뜻하지 않는다. 사용자 응답·실제 파일·식별자 참조·시간 연속성은 별도 의미 확인이 필요하다. 미검수 또는 blocking 발견이 있는 검수 결과를 pass 구조로 허용하지 않는다.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"schema_version": {
|
"schema_version": {
|
||||||
"const": "1.0"
|
"enum": [
|
||||||
|
"1.0",
|
||||||
|
"1.1"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"project_id": {
|
"project_id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -1620,6 +1623,687 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"BlendFile": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"verified": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"sha256": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-f0-9]{64}$"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blender_version": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"path",
|
||||||
|
"verified",
|
||||||
|
"sha256",
|
||||||
|
"blender_version"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"verified": {
|
||||||
|
"const": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"sha256": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-f0-9]{64}$"
|
||||||
|
},
|
||||||
|
"blender_version": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"RenderProfile": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"engine": {
|
||||||
|
"enum": [
|
||||||
|
"BLENDER_EEVEE",
|
||||||
|
"CYCLES"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"device": {
|
||||||
|
"enum": [
|
||||||
|
"CPU",
|
||||||
|
"GPU"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fps": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1
|
||||||
|
},
|
||||||
|
"width": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1
|
||||||
|
},
|
||||||
|
"height": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1
|
||||||
|
},
|
||||||
|
"samples": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1
|
||||||
|
},
|
||||||
|
"seed": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"engine",
|
||||||
|
"device",
|
||||||
|
"fps",
|
||||||
|
"width",
|
||||||
|
"height",
|
||||||
|
"samples",
|
||||||
|
"seed"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"engine": {
|
||||||
|
"const": "BLENDER_EEVEE"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"device": {
|
||||||
|
"const": "GPU"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"08-scenes-1.1": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"scenes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"cut_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"start_state": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"end_state": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"camera": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"cut_id",
|
||||||
|
"description",
|
||||||
|
"start_state",
|
||||||
|
"end_state",
|
||||||
|
"camera"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connections": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"from_cut_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"to_cut_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"mode": {
|
||||||
|
"enum": [
|
||||||
|
"continuous",
|
||||||
|
"cut"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"from_cut_id",
|
||||||
|
"to_cut_id",
|
||||||
|
"mode",
|
||||||
|
"reason"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"preview": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"scene_file": {
|
||||||
|
"$ref": "#/$defs/BlendFile"
|
||||||
|
},
|
||||||
|
"render_profile": {
|
||||||
|
"$ref": "#/$defs/RenderProfile"
|
||||||
|
},
|
||||||
|
"samples": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"cut_ids": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"minItems": 1,
|
||||||
|
"uniqueItems": true
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/media"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"image",
|
||||||
|
"video"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"cut_ids",
|
||||||
|
"media"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"scene_file",
|
||||||
|
"render_profile",
|
||||||
|
"samples"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"scenes",
|
||||||
|
"connections",
|
||||||
|
"preview"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"10-references-1.1": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"request": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"style_reference": {
|
||||||
|
"const": "references/1.png"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"style",
|
||||||
|
"character",
|
||||||
|
"background",
|
||||||
|
"object"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"entity_id": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"kind",
|
||||||
|
"entity_id",
|
||||||
|
"prompt"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"style",
|
||||||
|
"object"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"entity_id": {
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"else": {
|
||||||
|
"properties": {
|
||||||
|
"entity_id": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine": {
|
||||||
|
"const": "Blender"
|
||||||
|
},
|
||||||
|
"render_profile": {
|
||||||
|
"$ref": "#/$defs/RenderProfile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"style_reference",
|
||||||
|
"items",
|
||||||
|
"engine",
|
||||||
|
"render_profile"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"scene_file": {
|
||||||
|
"$ref": "#/$defs/BlendFile"
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"reference_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"object_name": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/media"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"const": "image"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"reference_id",
|
||||||
|
"object_name",
|
||||||
|
"media"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"scene_file",
|
||||||
|
"items"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"request",
|
||||||
|
"result"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"11-images-1.1": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"request": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"frames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"cut_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"enum": [
|
||||||
|
"start",
|
||||||
|
"end"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"reference_ids": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scene_name": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"frame_index": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"cut_id",
|
||||||
|
"position",
|
||||||
|
"prompt",
|
||||||
|
"reference_ids",
|
||||||
|
"scene_name",
|
||||||
|
"frame_index"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine": {
|
||||||
|
"const": "Blender"
|
||||||
|
},
|
||||||
|
"scene_path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"render_profile": {
|
||||||
|
"$ref": "#/$defs/RenderProfile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"frames",
|
||||||
|
"engine",
|
||||||
|
"scene_path",
|
||||||
|
"render_profile"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"frames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"frame_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/media"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"const": "image"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"frame_id",
|
||||||
|
"media"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scene_file": {
|
||||||
|
"$ref": "#/$defs/BlendFile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"frames",
|
||||||
|
"scene_file"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"request",
|
||||||
|
"result"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"12-motion-1.1": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"request": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clips": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"cut_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"start_frame_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"end_frame_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"duration_ms": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 5000
|
||||||
|
},
|
||||||
|
"motion_prompt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"scene_name": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"start_frame": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"end_frame": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"cut_id",
|
||||||
|
"start_frame_id",
|
||||||
|
"end_frame_id",
|
||||||
|
"duration_ms",
|
||||||
|
"motion_prompt",
|
||||||
|
"scene_name",
|
||||||
|
"start_frame",
|
||||||
|
"end_frame"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine": {
|
||||||
|
"const": "Blender"
|
||||||
|
},
|
||||||
|
"scene_path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"render_profile": {
|
||||||
|
"$ref": "#/$defs/RenderProfile"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"clips",
|
||||||
|
"engine",
|
||||||
|
"scene_path",
|
||||||
|
"render_profile"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clips": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"cut_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/media"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"const": "video"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"cut_id",
|
||||||
|
"media"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"clips"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"request",
|
||||||
|
"result"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
@@ -1699,9 +2383,43 @@
|
|||||||
"const": "08-scenes"
|
"const": "08-scenes"
|
||||||
},
|
},
|
||||||
"payload": {
|
"payload": {
|
||||||
"$ref": "#/$defs/08-scenes"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/08-scenes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/08-scenes-1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -1719,9 +2437,43 @@
|
|||||||
"const": "10-references"
|
"const": "10-references"
|
||||||
},
|
},
|
||||||
"payload": {
|
"payload": {
|
||||||
"$ref": "#/$defs/10-references"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/10-references"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/10-references-1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -1729,9 +2481,43 @@
|
|||||||
"const": "11-images"
|
"const": "11-images"
|
||||||
},
|
},
|
||||||
"payload": {
|
"payload": {
|
||||||
"$ref": "#/$defs/11-images"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/11-images"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/11-images-1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -1739,9 +2525,43 @@
|
|||||||
"const": "12-motion"
|
"const": "12-motion"
|
||||||
},
|
},
|
||||||
"payload": {
|
"payload": {
|
||||||
"$ref": "#/$defs/12-motion"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/12-motion"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"payload": {
|
||||||
|
"$ref": "#/$defs/12-motion-1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -0,0 +1,303 @@
|
|||||||
|
"""저장소 계약의 회귀 검사. 실제 렌더링·승인·미디어 검수는 수행하지 않는다."""
|
||||||
|
from copy import deepcopy
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import tomllib
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from jsonschema import Draft202012Validator
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
PROFILE = dict(engine="BLENDER_EEVEE", device="GPU", fps=50, width=1080,
|
||||||
|
height=1920, samples=32, seed=1)
|
||||||
|
BLEND = dict(path="examples/blender-contract/preview.blend", verified=False,
|
||||||
|
sha256=None, blender_version=None)
|
||||||
|
IMAGE = dict(path="examples/blender-contract/preview.png", kind="image",
|
||||||
|
verified=False, duration_ms=None, width=None, height=None)
|
||||||
|
|
||||||
|
|
||||||
|
def read(path):
|
||||||
|
return json.loads((ROOT / path).read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def artifact(stage, payload):
|
||||||
|
return dict(schema_version="1.1", project_id="contract-example", stage_id=stage,
|
||||||
|
revision=1, inputs=[], payload=payload)
|
||||||
|
|
||||||
|
|
||||||
|
def samples():
|
||||||
|
frames = [dict(id="c1-" + pos, cut_id="c1", position=pos, prompt="상태 설명",
|
||||||
|
reference_ids=["water"], scene_name="Water", frame_index=index)
|
||||||
|
for pos, index in [("start", 0), ("end", 200)]]
|
||||||
|
return {
|
||||||
|
"08-scenes": artifact("08-scenes", dict(scenes=[], connections=[], preview=None)),
|
||||||
|
"10-references": artifact("10-references", dict(request=dict(engine="Blender",
|
||||||
|
style_reference="references/1.png", render_profile=deepcopy(PROFILE), items=[
|
||||||
|
dict(id="water", kind="object", entity_id=None, prompt="물방울")]), result=None)),
|
||||||
|
"11-images": artifact("11-images", dict(request=dict(engine="Blender",
|
||||||
|
scene_path=BLEND["path"], render_profile=deepcopy(PROFILE), frames=frames), result=None)),
|
||||||
|
"12-motion": artifact("12-motion", dict(request=dict(engine="Blender",
|
||||||
|
scene_path=BLEND["path"], render_profile=deepcopy(PROFILE), clips=[dict(cut_id="c1",
|
||||||
|
start_frame_id="c1-start", end_frame_id="c1-end", duration_ms=4000,
|
||||||
|
motion_prompt="둥글게", scene_name="Water", start_frame=0, end_frame=200)]), result=None)),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def semantic_errors(data, context, complete=False):
|
||||||
|
"""1.1 구조 검사 후 사용. context={stage_id: artifact}; 파일·승인은 별도 확인."""
|
||||||
|
if data["schema_version"] != "1.1":
|
||||||
|
return []
|
||||||
|
errors = []
|
||||||
|
stage = data["stage_id"]
|
||||||
|
payload = data["payload"]
|
||||||
|
|
||||||
|
def require(condition, message):
|
||||||
|
if not condition:
|
||||||
|
errors.append(message)
|
||||||
|
|
||||||
|
def indexed(items, key):
|
||||||
|
ids = [item[key] for item in items]
|
||||||
|
require(all(ids) and len(ids) == len(set(ids)), "빈 식별자 또는 중복: " + key)
|
||||||
|
return {item[key]: item for item in items}
|
||||||
|
|
||||||
|
def walk(value):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
for key, child in value.items():
|
||||||
|
if key in ("path", "scene_path") and isinstance(child, str) and child:
|
||||||
|
parts = child.replace("\\", "/").split("/")
|
||||||
|
require(not child.startswith(("/", "\\")) and ":" not in child
|
||||||
|
and ".." not in parts, "루트 상대 경로 필요: " + child)
|
||||||
|
if "kind" in value:
|
||||||
|
require(not child.lower().endswith(".blend"), ".blend는 media가 아니다")
|
||||||
|
walk(child)
|
||||||
|
elif isinstance(value, list):
|
||||||
|
for child in value:
|
||||||
|
walk(child)
|
||||||
|
|
||||||
|
walk(payload)
|
||||||
|
request = payload.get("request", {})
|
||||||
|
preview = payload.get("preview")
|
||||||
|
profile = request.get("render_profile") or (preview or {}).get("render_profile")
|
||||||
|
if profile:
|
||||||
|
require(profile["width"] * 16 == profile["height"] * 9, "RenderProfile은 9:16 필요")
|
||||||
|
cuts = context.get("07-cuts", {}).get("payload", {}).get("cuts", [])
|
||||||
|
cut_ids = {cut["id"] for cut in cuts}
|
||||||
|
if stage == "08-scenes" and preview:
|
||||||
|
indexed(preview["samples"], "id")
|
||||||
|
require(bool(preview["samples"]), "대표 샘플 필요")
|
||||||
|
for sample in preview["samples"]:
|
||||||
|
require(set(sample["cut_ids"]) <= cut_ids, "대표 샘플의 알 수 없는 컷")
|
||||||
|
require(sample["media"]["verified"], "대표 미디어 미검증")
|
||||||
|
require(preview["scene_file"]["verified"], "대표 .blend 미검증")
|
||||||
|
if stage == "10-references":
|
||||||
|
indexed(request["items"], "id")
|
||||||
|
entities = context.get("09-entities", {}).get("payload", {})
|
||||||
|
for item in request["items"]:
|
||||||
|
if item["kind"] in ("character", "background"):
|
||||||
|
bucket = "characters" if item["kind"] == "character" else "backgrounds"
|
||||||
|
require(item["entity_id"] in {x["id"] for x in entities.get(bucket, [])},
|
||||||
|
"알 수 없는 entity_id")
|
||||||
|
if stage == "11-images":
|
||||||
|
frames = indexed(request["frames"], "id")
|
||||||
|
refs = context.get("10-references", {}).get("payload", {}).get("request", {}).get("items", [])
|
||||||
|
reference_ids = {item["id"] for item in refs}
|
||||||
|
pairs = {}
|
||||||
|
for frame in frames.values():
|
||||||
|
require(frame["cut_id"] in cut_ids, "프레임의 알 수 없는 컷")
|
||||||
|
require(set(frame["reference_ids"]) <= reference_ids, "알 수 없는 reference_id")
|
||||||
|
pairs.setdefault(frame["cut_id"], []).append(frame)
|
||||||
|
require(set(pairs) == cut_ids, "컷별 start/end 누락")
|
||||||
|
for pair in pairs.values():
|
||||||
|
require(len(pair) == 2 and {x["position"] for x in pair} == {"start", "end"}, "start/end 중복 또는 누락")
|
||||||
|
require(len({x["scene_name"] for x in pair}) == 1, "같은 컷은 같은 Scene 필요")
|
||||||
|
if stage == "12-motion":
|
||||||
|
clips = indexed(request["clips"], "cut_id")
|
||||||
|
require(set(clips) == cut_ids, "클립 컷 누락 또는 추가")
|
||||||
|
previous = context.get("11-images", {}).get("payload", {})
|
||||||
|
result = previous.get("result")
|
||||||
|
require(bool(result) and result["scene_file"]["verified"], "11 실제 .blend 필요")
|
||||||
|
if result:
|
||||||
|
require(request["scene_path"] == result["scene_file"]["path"], "11 원본 경로 불일치")
|
||||||
|
require(request["render_profile"] == previous.get("request", {}).get("render_profile"), "11 RenderProfile 불일치")
|
||||||
|
frames = {x["id"]: x for x in previous.get("request", {}).get("frames", [])}
|
||||||
|
for clip in clips.values():
|
||||||
|
require(clip["end_frame"] > clip["start_frame"], "프레임 범위는 양수 필요")
|
||||||
|
for position in ("start", "end"):
|
||||||
|
frame = frames.get(clip[position + "_frame_id"])
|
||||||
|
require(bool(frame), "알 수 없는 frame_id")
|
||||||
|
if frame:
|
||||||
|
require(frame["cut_id"] == clip["cut_id"] and frame["position"] == position
|
||||||
|
and frame["scene_name"] == clip["scene_name"]
|
||||||
|
and frame["frame_index"] == clip[position + "_frame"], "프레임 상태 참조 불일치")
|
||||||
|
cut = next((x for x in cuts if x["id"] == clip["cut_id"]), None)
|
||||||
|
if cut:
|
||||||
|
require(clip["duration_ms"] == cut["end_ms"] - cut["start_ms"], "컷 실측 길이 불일치")
|
||||||
|
require(clip["duration_ms"] is not None and (clip["end_frame"] - clip["start_frame"]) * 1000
|
||||||
|
== clip["duration_ms"] * request["render_profile"]["fps"], "프레임 수와 컷 길이 불일치")
|
||||||
|
if complete and stage in ("10-references", "11-images", "12-motion"):
|
||||||
|
result = payload["result"]
|
||||||
|
require(result is not None, "result=null은 완료가 아니다")
|
||||||
|
if result:
|
||||||
|
key, requested_key, returned_key = {
|
||||||
|
"10-references": ("items", "id", "reference_id"),
|
||||||
|
"11-images": ("frames", "id", "frame_id"),
|
||||||
|
"12-motion": ("clips", "cut_id", "cut_id"),
|
||||||
|
}[stage]
|
||||||
|
returned = indexed(result[key], returned_key)
|
||||||
|
require(bool(request[key]) and set(returned) == {x[requested_key] for x in request[key]}, "요청/결과 누락 또는 추가")
|
||||||
|
require(all(x["media"]["verified"] for x in result[key]), "결과 미디어 미검증")
|
||||||
|
if stage != "12-motion":
|
||||||
|
require(result["scene_file"]["verified"], "결과 .blend 미검증")
|
||||||
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
class ContractTests(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.validators = {}
|
||||||
|
for name in ("project", "artifact"):
|
||||||
|
schema = read("contracts/" + name + ".schema.json")
|
||||||
|
Draft202012Validator.check_schema(schema)
|
||||||
|
cls.validators[name] = Draft202012Validator(schema)
|
||||||
|
|
||||||
|
def valid(self, data):
|
||||||
|
self.validators["artifact" if "stage_id" in data else "project"].validate(data)
|
||||||
|
|
||||||
|
def invalid(self, data):
|
||||||
|
self.assertFalse(self.validators["artifact" if "stage_id" in data else "project"].is_valid(data))
|
||||||
|
|
||||||
|
def test_legacy_templates_examples_and_production(self):
|
||||||
|
count = 0
|
||||||
|
for folder in ("templates", "examples", "projects"):
|
||||||
|
for path in (ROOT / folder).rglob("*.json"):
|
||||||
|
if "node_modules" in path.parts or ".cache" in path.parts:
|
||||||
|
continue
|
||||||
|
data = json.loads(path.read_text(encoding="utf-8"))
|
||||||
|
if isinstance(data, dict) and "schema_version" in data and "project_id" in data:
|
||||||
|
self.valid(data)
|
||||||
|
count += 1
|
||||||
|
self.assertGreaterEqual(count, 30)
|
||||||
|
|
||||||
|
def test_role_skill_and_document_links(self):
|
||||||
|
agents = list((ROOT / ".codex/agents").glob("*.toml"))
|
||||||
|
self.assertEqual(len(agents), 8)
|
||||||
|
for path in agents:
|
||||||
|
role = tomllib.loads(path.read_text(encoding="utf-8"))
|
||||||
|
self.assertEqual(set(role), {"name", "description", "developer_instructions"})
|
||||||
|
self.assertEqual(role["name"], path.stem)
|
||||||
|
skills = list((ROOT / ".agents/skills").glob("*/SKILL.md"))
|
||||||
|
self.assertEqual(len(skills), 15)
|
||||||
|
documents = [ROOT / "AGENTS.md", ROOT / "CLAUDE.md",
|
||||||
|
*list((ROOT / "docs").glob("*.md")),
|
||||||
|
ROOT / "examples/blender-contract/README.md", *skills]
|
||||||
|
for path in documents:
|
||||||
|
text = path.read_text(encoding="utf-8")
|
||||||
|
for target in re.findall(r"\]\(([^)]+)\)", text):
|
||||||
|
if "://" not in target and not target.startswith("#"):
|
||||||
|
self.assertTrue((path.parent / target.split("#")[0]).resolve().exists(), (path, target))
|
||||||
|
|
||||||
|
def test_blender_contracts(self):
|
||||||
|
project = read("templates/project.json")
|
||||||
|
project["schema_version"] = "1.1"
|
||||||
|
project["settings"].pop("image_model", None)
|
||||||
|
project["settings"]["visual_engine"] = "Blender"
|
||||||
|
self.valid(project)
|
||||||
|
for data in samples().values():
|
||||||
|
self.valid(data)
|
||||||
|
|
||||||
|
def test_wrong_version_engine_and_extra_fields(self):
|
||||||
|
for data in samples().values():
|
||||||
|
for version in ("1.0", "2.0"):
|
||||||
|
bad = deepcopy(data)
|
||||||
|
bad["schema_version"] = version
|
||||||
|
self.invalid(bad)
|
||||||
|
if "request" in data["payload"]:
|
||||||
|
bad = deepcopy(data)
|
||||||
|
bad["payload"]["request"]["engine"] = "gpt-image-2.5-sunburst"
|
||||||
|
self.invalid(bad)
|
||||||
|
bad["payload"]["request"]["engine"] = "Blender"
|
||||||
|
bad["payload"]["request"]["model"] = "Blender"
|
||||||
|
self.invalid(bad)
|
||||||
|
|
||||||
|
def test_verified_blend_requires_hash_and_version(self):
|
||||||
|
data = samples()["08-scenes"]
|
||||||
|
data["payload"]["preview"] = dict(scene_file=deepcopy(BLEND),
|
||||||
|
render_profile=deepcopy(PROFILE), samples=[dict(id="p1", cut_ids=["c1"], media=deepcopy(IMAGE))])
|
||||||
|
self.valid(data)
|
||||||
|
blend = data["payload"]["preview"]["scene_file"]
|
||||||
|
blend["verified"] = True
|
||||||
|
self.invalid(data)
|
||||||
|
blend.update(sha256="a" * 64, blender_version="5.2.2 LTS")
|
||||||
|
self.valid(data)
|
||||||
|
for key, value in [("sha256", "A" * 64), ("blender_version", ""), ("path", "")]:
|
||||||
|
bad = deepcopy(data)
|
||||||
|
bad["payload"]["preview"]["scene_file"][key] = value
|
||||||
|
self.invalid(bad)
|
||||||
|
bad = deepcopy(data)
|
||||||
|
bad["payload"]["preview"]["samples"][0]["media"]["kind"] = "blend"
|
||||||
|
self.invalid(bad)
|
||||||
|
|
||||||
|
def test_profile_and_duration_constraints(self):
|
||||||
|
for key, value in [("engine", "UNKNOWN"), ("device", "CPU"), ("fps", 0),
|
||||||
|
("samples", 0), ("width", 0), ("height", 0), ("seed", -1)]:
|
||||||
|
bad = samples()["11-images"]
|
||||||
|
bad["payload"]["request"]["render_profile"][key] = value
|
||||||
|
self.invalid(bad)
|
||||||
|
for duration in (0, -1, 5001):
|
||||||
|
bad = samples()["12-motion"]
|
||||||
|
bad["payload"]["request"]["clips"][0]["duration_ms"] = duration
|
||||||
|
self.invalid(bad)
|
||||||
|
cycles = samples()["11-images"]
|
||||||
|
cycles["payload"]["request"]["render_profile"].update(engine="CYCLES", device="CPU")
|
||||||
|
self.valid(cycles)
|
||||||
|
|
||||||
|
def test_result_shapes_and_missing_fields(self):
|
||||||
|
fixtures = samples()
|
||||||
|
fixtures["10-references"]["payload"]["result"] = dict(scene_file=deepcopy(BLEND),
|
||||||
|
items=[dict(reference_id="water", object_name="Droplet", media=deepcopy(IMAGE))])
|
||||||
|
fixtures["11-images"]["payload"]["result"] = dict(scene_file=deepcopy(BLEND),
|
||||||
|
frames=[dict(frame_id="c1-start", media=deepcopy(IMAGE))])
|
||||||
|
fixtures["12-motion"]["payload"]["result"] = dict(clips=[dict(cut_id="c1",
|
||||||
|
media=dict(IMAGE, kind="video", path="examples/blender-contract/c1.mp4"))])
|
||||||
|
for data in fixtures.values():
|
||||||
|
self.valid(data)
|
||||||
|
if "request" in data["payload"]:
|
||||||
|
for key in data["payload"]["request"]:
|
||||||
|
bad = deepcopy(data)
|
||||||
|
del bad["payload"]["request"][key]
|
||||||
|
self.invalid(bad)
|
||||||
|
|
||||||
|
def test_semantic_references_and_completion(self):
|
||||||
|
data = samples()["11-images"]
|
||||||
|
context = {"07-cuts": {"payload": {"cuts": [dict(id="c1", start_ms=0, end_ms=4000)]}},
|
||||||
|
"10-references": samples()["10-references"]}
|
||||||
|
self.assertEqual(semantic_errors(data, context), [])
|
||||||
|
self.assertIn("result=null은 완료가 아니다", semantic_errors(data, context, complete=True))
|
||||||
|
for change in ("duplicate", "reference", "scene", "aspect", "absolute"):
|
||||||
|
bad = deepcopy(data)
|
||||||
|
request = bad["payload"]["request"]
|
||||||
|
if change == "duplicate":
|
||||||
|
request["frames"][1]["id"] = request["frames"][0]["id"]
|
||||||
|
elif change == "reference":
|
||||||
|
request["frames"][0]["reference_ids"] = ["missing"]
|
||||||
|
elif change == "scene":
|
||||||
|
request["frames"][1]["scene_name"] = "Other"
|
||||||
|
elif change == "aspect":
|
||||||
|
request["render_profile"]["width"] = 1920
|
||||||
|
else:
|
||||||
|
request["scene_path"] = "C:/foreign.blend"
|
||||||
|
self.assertTrue(semantic_errors(bad, context), change)
|
||||||
|
|
||||||
|
def test_blend_media_impersonation(self):
|
||||||
|
data = samples()["08-scenes"]
|
||||||
|
data["payload"]["preview"] = dict(scene_file=dict(BLEND, verified=True, sha256="a" * 64,
|
||||||
|
blender_version="5.2.2"), render_profile=deepcopy(PROFILE), samples=[dict(id="p1", cut_ids=["c1"],
|
||||||
|
media=dict(IMAGE, path="examples/blender-contract/wrong.blend", verified=True, width=1080, height=1920))])
|
||||||
|
self.valid(data)
|
||||||
|
self.assertIn(".blend는 media가 아니다", semantic_errors(data,
|
||||||
|
{"07-cuts": {"payload": {"cuts": [{"id": "c1"}]}}}))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main(verbosity=2)
|
||||||
+112
-36
@@ -2,7 +2,10 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"schema_version": {
|
"schema_version": {
|
||||||
"const": "1.0"
|
"enum": [
|
||||||
|
"1.0",
|
||||||
|
"1.1"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"project_id": {
|
"project_id": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -25,40 +28,7 @@
|
|||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"type": "object",
|
"type": "object"
|
||||||
"properties": {
|
|
||||||
"aspect_ratio": {
|
|
||||||
"const": "9:16"
|
|
||||||
},
|
|
||||||
"max_duration_ms": {
|
|
||||||
"const": 180000
|
|
||||||
},
|
|
||||||
"max_cut_duration_ms": {
|
|
||||||
"const": 5000
|
|
||||||
},
|
|
||||||
"style_reference": {
|
|
||||||
"const": "references/1.png"
|
|
||||||
},
|
|
||||||
"tts_engine": {
|
|
||||||
"const": "Qwen3-TTS"
|
|
||||||
},
|
|
||||||
"conda_env": {
|
|
||||||
"const": "qwen3-tts"
|
|
||||||
},
|
|
||||||
"image_model": {
|
|
||||||
"const": "gpt-image-2.5-sunburst"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"aspect_ratio",
|
|
||||||
"max_duration_ms",
|
|
||||||
"max_cut_duration_ms",
|
|
||||||
"style_reference",
|
|
||||||
"tts_engine",
|
|
||||||
"conda_env",
|
|
||||||
"image_model"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
},
|
||||||
"stages": {
|
"stages": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@@ -496,6 +466,112 @@
|
|||||||
"blocking"
|
"blocking"
|
||||||
],
|
],
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"settings-1.0": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"aspect_ratio": {
|
||||||
|
"const": "9:16"
|
||||||
|
},
|
||||||
|
"max_duration_ms": {
|
||||||
|
"const": 180000
|
||||||
|
},
|
||||||
|
"max_cut_duration_ms": {
|
||||||
|
"const": 5000
|
||||||
|
},
|
||||||
|
"style_reference": {
|
||||||
|
"const": "references/1.png"
|
||||||
|
},
|
||||||
|
"tts_engine": {
|
||||||
|
"const": "Qwen3-TTS"
|
||||||
|
},
|
||||||
|
"conda_env": {
|
||||||
|
"const": "qwen3-tts"
|
||||||
|
},
|
||||||
|
"image_model": {
|
||||||
|
"const": "gpt-image-2.5-sunburst"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"aspect_ratio",
|
||||||
|
"max_duration_ms",
|
||||||
|
"max_cut_duration_ms",
|
||||||
|
"style_reference",
|
||||||
|
"tts_engine",
|
||||||
|
"conda_env",
|
||||||
|
"image_model"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
"settings-1.1": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"aspect_ratio": {
|
||||||
|
"const": "9:16"
|
||||||
|
},
|
||||||
|
"max_duration_ms": {
|
||||||
|
"const": 180000
|
||||||
|
},
|
||||||
|
"max_cut_duration_ms": {
|
||||||
|
"const": 5000
|
||||||
|
},
|
||||||
|
"style_reference": {
|
||||||
|
"const": "references/1.png"
|
||||||
|
},
|
||||||
|
"tts_engine": {
|
||||||
|
"const": "Qwen3-TTS"
|
||||||
|
},
|
||||||
|
"conda_env": {
|
||||||
|
"const": "qwen3-tts"
|
||||||
|
},
|
||||||
|
"visual_engine": {
|
||||||
|
"const": "Blender"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"aspect_ratio",
|
||||||
|
"max_duration_ms",
|
||||||
|
"max_cut_duration_ms",
|
||||||
|
"style_reference",
|
||||||
|
"tts_engine",
|
||||||
|
"conda_env",
|
||||||
|
"visual_engine"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"settings": {
|
||||||
|
"$ref": "#/$defs/settings-1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"schema_version": {
|
||||||
|
"const": "1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"settings": {
|
||||||
|
"$ref": "#/$defs/settings-1.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
# 구성과 데이터 흐름
|
# 구성과 데이터 흐름
|
||||||
|
|
||||||
ShortVideoGenerator는 개인용 Codex 작업 지침으로 구성된다. 서비스·데이터베이스·실행 프로그램이 아니라 역할 TOML, 작업별 SKILL.md, JSON 양식·스키마를 함께 사용하는 구조다.
|
ShortVideoGenerator는 개인용 Codex 작업 지침으로 구성된다. 역할 TOML, 작업별 SKILL.md, JSON 양식·스키마를 함께 사용하고 승인된 로컬 실행 경로에 미디어 제작을 맡긴다. 서비스·데이터베이스는 두지 않는다.
|
||||||
|
|
||||||
`.codex/agents/`의 8개 역할은 `.agents/skills/`의 담당 작업을 사용한다. 스킬은 `templates/`의 빈 양식과 `contracts/`의 전달 구조를 읽고, 제작별 `projects/<project_id>/`에 결과 버전과 사람용 검토를 남긴다. 총괄만 공유 진행 기록을 관리한다. 참고 자료는 이야기 구성·그림체의 입력이고 다른 제작의 상태·승인을 가져오는 저장소가 아니다.
|
`.codex/agents/`의 8개 역할은 `.agents/skills/`의 담당 작업을 사용한다. 스킬은 `templates/`의 빈 양식과 `contracts/`의 전달 구조를 읽고, 제작별 `projects/<project_id>/`에 결과 버전과 사람용 검토를 남긴다. 총괄만 공유 진행 기록을 관리한다. 참고 자료는 이야기 구성·그림체의 입력이고 다른 제작의 상태·승인을 가져오는 저장소가 아니다.
|
||||||
|
|
||||||
주제와 언어 요청은 총괄→주제·조사→작가→내레이션→장면→비주얼→영상·편집→검수 순으로 전달된다. 주제, 대본·제목, 장면, 완성본의 사용자 검토가 다음 구간을 연다. 검토를 기다리는 동안 경계를 넘는 새 후속 작업을 실행하지 않는다.
|
주제와 언어 요청은 총괄→주제·조사→작가→내레이션→장면→비주얼→영상·편집→검수 순으로 전달된다. 주제, 대본·제목, 장면, 완성본의 사용자 검토가 다음 구간을 연다. 검토를 기다리는 동안 경계를 넘는 새 후속 작업을 실행하지 않는다.
|
||||||
|
|
||||||
음성 요청은 기존 conda qwen3-tts 환경의 Qwen3-TTS로, 기준·컷 이미지 요청은 gpt-image-2.5-sunburst로 전달하도록 지정했다. 실제 요청 실행 프로그램은 아직 없다. 모델·화자·지원 언어·결과 파일은 실제 제작 환경에서 확인해야 하며 설치 여부가 추론 성공을 뜻하지 않는다.
|
음성 요청은 기존 conda qwen3-tts 환경의 Qwen3-TTS로, 새 모델·기준·컷 이미지·영상 요청은 Blender로 전달한다. 기존 1.0 이미지 모델 계약과 실제 결과는 보존하고 새 1.1과 함께 읽는다. 모델·화자·지원 언어·결과 파일은 실제 제작 환경에서 확인해야 하며 설치 여부가 추론 성공을 뜻하지 않는다.
|
||||||
|
|
||||||
영상·합성 경계에는 시작/끝 이미지·움직임·컷 길이 또는 클립·음성·자막의 요청과 실제 결과 파일 정보가 오간다. 엔진·API 파라미터·인증정보는 전달 계약에 고정하지 않는다. 외부 결과가 없으면 진행이 멈추며 예상이나 모의 데이터를 실제 결과로 승격하지 않는다.
|
영상·합성 경계에는 시작/끝 이미지·움직임·컷 길이 또는 클립·음성·자막의 요청과 실제 결과 파일 정보가 오간다. 1.1은 Blender의 .blend 원본·RenderProfile·Scene 이름·논리 프레임을 명시하고 PNG·MP4 결과를 별도로 기록한다. 합성은 승인된 기존 Remotion + FFmpeg 경로를 재사용한다. 실행파일의 외부 경로·인증정보는 전달 계약에 기록하지 않는다. 외부 결과가 없으면 진행이 멈추며 예상이나 모의 데이터를 실제 결과로 승격하지 않는다.
|
||||||
|
|
||||||
대표적인 재개 요청은 기존 입력·포인터·승인·파일을 읽고 가장 앞선 미해결 단계에 배정된다. 결과가 갱신되면 실제 inputs 관계로 종속 결과를 다시 확인한다. 제목만 수정한 경우 새 제목은 합성과 검수에 전달되며 기존 음성·이미지는 유지된다.
|
대표적인 재개 요청은 기존 입력·포인터·승인·파일을 읽고 가장 앞선 미해결 단계에 배정된다. 결과가 갱신되면 실제 inputs 관계로 종속 결과를 다시 확인한다. 제목만 수정한 경우 새 제목은 합성과 검수에 전달되며 기존 음성·이미지는 유지된다.
|
||||||
|
|
||||||
|
08의 제한된 대표 화면·짧은 움직임 제작만 scenes 승인 전 품질 검토를 위해 허용한다. 이 자료는 정식 10–12 완료가 아니다. 새 08·09의 scenes 승인 후 전체 모델·끝점·클립을 제작한다. 주제별 모델·장면은 해당 제작의 근거로 작성하며 다른 주제의 3D 자산을 자동 생성한다고 보장하지 않는다.
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
장면은 각 컷의 시작·끝·카메라를 정하고 인접 컷의 이어짐 또는 전환 이유를 기록한다. 이어지는 컷은 인물·배경·행동·카메라 상태가 맞아야 한다. 반복 인물·배경의 고정 특징은 유지하고 이야기상 변화는 명시한다. 모든 영상의 고정 인물로 승격하지 않는다.
|
장면은 각 컷의 시작·끝·카메라를 정하고 인접 컷의 이어짐 또는 전환 이유를 기록한다. 이어지는 컷은 인물·배경·행동·카메라 상태가 맞아야 한다. 반복 인물·배경의 고정 특징은 유지하고 이야기상 변화는 명시한다. 모든 영상의 고정 인물로 승격하지 않는다.
|
||||||
|
|
||||||
이미지는 사용자 기준의 그림체를 따르며 캠핑 소재·상표를 의무로 복제하지 않는다. 각 컷에 start/end가 하나씩 필요하다. 같은 실제 이미지를 재사용해도 두 위치의 참조 기록은 남긴다. 영상은 그 사이의 설명에 필요한 움직임을 표현한다.
|
새 시각 제작은 Blender 교육용 3D이며 사용자 원본의 단순 형태·정돈된 색을 참고한다. 단순 배경·부드러운 조명·선명한 형태를 사용하고 평면 스타일·캠핑 소재·상표를 의무로 복제하지 않는다. 각 컷에 start/end가 하나씩 필요하다. 같은 Scene의 continuous 경계에서 실제 PNG를 공유해도 두 위치의 별도 ID를 남긴다. cut 전환은 Scene 이름을 구분하며 같은 프레임 번호를 같은 상태로 취급하지 않는다. 영상은 그 사이의 설명에 필요한 움직임을 표현한다.
|
||||||
|
|
||||||
결과 파일은 실제 존재·형식·메타데이터를 확인해야 한다. 요청·예상·설명용 예제는 검증 결과가 아니다. 파일 부재·부분 결과는 기다리는 상태이고 전체 완료로 처리할 수 없다. 설치 확인만으로 모델 로딩·추론을 확인했다고 쓰지 않는다.
|
결과 파일은 실제 존재·형식·메타데이터를 확인해야 한다. 요청·예상·설명용 예제는 검증 결과가 아니다. 파일 부재·부분 결과는 기다리는 상태이고 전체 완료로 처리할 수 없다. 설치 확인만으로 모델 로딩·추론을 확인했다고 쓰지 않는다.
|
||||||
|
|
||||||
|
|||||||
+17
-6
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## 공통 출력
|
## 공통 출력
|
||||||
|
|
||||||
진행 기록은 schema_version="1.0", project_id, brief={topic,language}, settings, stages, reviews다. stages의 항목은 {stage_id,status,revision,artifact_path,issues}, issues는 {code,message,blocking}다. reviews의 항목은 {review_id,decision,artifact_refs,feedback}이며 artifact_refs는 {stage_id,revision} 배열이다.
|
진행 기록은 schema_version="1.1"(새 제작) 또는 "1.0"(기존 결과), project_id, brief={topic,language}, settings, stages, reviews다. stages의 항목은 {stage_id,status,revision,artifact_path,issues}, issues는 {code,message,blocking}다. reviews의 항목은 {review_id,decision,artifact_refs,feedback}이며 artifact_refs는 {stage_id,revision} 배열이다.
|
||||||
|
|
||||||
단계 출력은 {schema_version,project_id,stage_id,revision,inputs,payload}다. revision은 1부터 시작하고 inputs는 실제 사용한 선행 버전 배열이다. project_id는 유일한 소문자 영숫자·하이픈이고, 경로는 저장소 루트 기준 상대 경로다. 이전 결과는 보존하며 review.md는 같은 JSON을 사람이 읽는 요약이다. 공통·단계별 필드 타입은 [진행 스키마](../contracts/project.schema.json)와 [단계 스키마](../contracts/artifact.schema.json), 시작 형태는 [양식](../templates/)에 있다.
|
단계 출력은 {schema_version,project_id,stage_id,revision,inputs,payload}다. revision은 1부터 시작하고 inputs는 실제 사용한 선행 버전 배열이다. project_id는 유일한 소문자 영숫자·하이픈이고, 경로는 저장소 루트 기준 상대 경로다. 이전 결과는 보존하며 review.md는 같은 JSON을 사람이 읽는 요약이다. 공통·단계별 필드 타입은 [진행 스키마](../contracts/project.schema.json)와 [단계 스키마](../contracts/artifact.schema.json), 시작 형태는 [양식](../templates/)에 있다.
|
||||||
|
|
||||||
@@ -15,16 +15,27 @@
|
|||||||
| 단계 | 요청 | 결과 |
|
| 단계 | 요청 | 결과 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 06 | engine, conda_env, language, units | engine, model, voice, files, narration, unit_ranges |
|
| 06 | engine, conda_env, language, units | engine, model, voice, files, narration, unit_ranges |
|
||||||
| 10 | model, style_reference, items | items |
|
| 10 (1.1) | engine, style_reference, render_profile, items | scene_file, items |
|
||||||
| 11 | model, frames | frames |
|
| 11 (1.1) | engine, scene_path, render_profile, frames | scene_file, frames |
|
||||||
| 12 | clips | clips |
|
| 12 (1.1) | engine, scene_path, render_profile, clips | clips |
|
||||||
| 13 | timeline, narration_path, captions, title | video, captions_path |
|
| 13 | timeline, narration_path, captions, title | video, captions_path |
|
||||||
|
|
||||||
06 units는 {id,block_ids,display_text,spoken_text,pronunciation_notes}, files는 {unit_id,media}, narration은 media, unit_ranges는 {unit_id,start_ms,end_ms}다. 요청 engine은 Qwen3-TTS, conda_env는 qwen3-tts이며 model·voice는 실제 사용값을 결과에 기록한다.
|
06 units는 {id,block_ids,display_text,spoken_text,pronunciation_notes}, files는 {unit_id,media}, narration은 media, unit_ranges는 {unit_id,start_ms,end_ms}다. 요청 engine은 Qwen3-TTS, conda_env는 qwen3-tts이며 model·voice는 실제 사용값을 결과에 기록한다.
|
||||||
|
|
||||||
10 요청 items는 {id,kind,entity_id,prompt}, 결과 items는 {reference_id,media}다. kind는 style/character/background이며 스타일만 entity_id=null이다. model은 gpt-image-2.5-sunburst, style_reference는 references/1.png다. 11 요청 frames는 {id,cut_id,position,prompt,reference_ids}, 결과 frames는 {frame_id,media}다. position은 start/end이고 컷마다 둘 다 하나씩 필요하다.
|
1.0의 기존 이미지 모델 요청·결과 정의는 그대로 읽고 검증한다. 기존 제작·r1 미디어를 변환하거나 덮어쓰지 않는다. 새 1.1 프로젝트의 settings는 기존 aspect_ratio/max_duration_ms/max_cut_duration_ms/style_reference/tts_engine/conda_env 상수를 유지하고 image_model 대신 visual_engine="Blender"를 갖는다. 1.1 프로젝트의 inputs·포인터는 유효한 기존 1.0 결과를 참조할 수 있다.
|
||||||
|
|
||||||
12 요청 clips는 {cut_id,start_frame_id,end_frame_id,duration_ms,motion_prompt}, 결과 clips는 {cut_id,media}다. 13 timeline은 {cut_id,video_path,start_ms,end_ms}, captions는 {id,start_ms,end_ms,text} 배열이다. video는 media이고 captions_path는 실제 SRT 경로다. 특정 영상·합성 엔진이나 API 파라미터는 계약에 고정하지 않는다.
|
1.1의 08/10/11/12 외 payload는 1.0과 동일하다. 새 객체의 모든 명시된 키는 필수이고 추가 키를 허용하지 않는다.
|
||||||
|
|
||||||
|
- BlendFile={path,verified,sha256,blender_version}. path는 루트 상대 문자열, verified는 불리언, sha256은 null 또는 소문자 64자리 16진수, blender_version은 null 또는 비어 있지 않은 문자열이다. verified=true이면 비어 있지 않은 경로·해시·버전이 모두 필요하다. 실제 파일 해시·재열기·버전을 확인하고 기록한다. .blend를 PNG/MP4 media로 기록하지 않는다.
|
||||||
|
- RenderProfile={engine,device,fps,width,height,samples,seed}. engine은 BLENDER_EEVEE/CYCLES, device는 CPU/GPU, EEVEE는 GPU다. fps/width/height/samples는 양의 정수, seed는 0 이상 정수다. 의미 검사에서 9:16을 확인한다. 값은 렌더 요청이며 실제 지원·성공을 뜻하지 않는다.
|
||||||
|
- 08 payload={scenes,connections,preview}. scenes/connections는 기존 구조다. preview는 null 또는 {scene_file:BlendFile,render_profile:RenderProfile,samples}이고 sample={id,cut_ids,media}다. id는 비어 있지 않고 유일하며 cut_ids는 비어 있지 않은 유일한 기존 컷 ID 배열, media는 실제 PNG 또는 MP4다. 대표 샘플은 scenes 검토 근거로만 사용한다.
|
||||||
|
- 10 request={engine:"Blender",style_reference:"references/1.png",render_profile,items}. item={id,kind,entity_id,prompt}이며 kind는 style/character/background/object, style/object는 entity_id=null, character/background는 실제 09의 해당 ID를 참조한다. result는 null 또는 {scene_file:BlendFile,items}; 결과 item={reference_id,object_name,media:image}. reference_id는 요청 ID, object_name은 비어 있지 않은 실제 .blend 오브젝트/컬렉션 이름이다. 기준 PNG와 실제 자산을 함께 대조한다.
|
||||||
|
- 11 request={engine:"Blender",scene_path,render_profile,frames}. scene_path는 생성할 원본의 루트 상대 경로다. frame={id,cut_id,position,prompt,reference_ids,scene_name,frame_index}; position은 start/end, scene_name은 비어 있지 않은 실제 Scene 이름, frame_index는 0 이상 논리 프레임이다. 같은 컷의 start/end는 같은 Scene을 사용한다. result는 null 또는 {scene_file:BlendFile,frames}; 결과 frame={frame_id,media:image}다.
|
||||||
|
- 12 request={engine:"Blender",scene_path,render_profile,clips}. scene_path는 11의 검증된 실제 .blend 경로이고 render_profile은 11과 동일하다. clip={cut_id,start_frame_id,end_frame_id,duration_ms,motion_prompt,scene_name,start_frame,end_frame}. scene_name과 끝점 참조는 실제 11의 같은 Scene과 일치하고 start_frame/end_frame은 0 이상이며 end_frame>start_frame이다. duration_ms는 미작성 시 null, 작성 시 0 초과 5000 이하 정수이며 실측 07 구간과 같아야 한다. result는 기존 null 또는 {clips:[{cut_id,media:video}]}다.
|
||||||
|
|
||||||
|
13/14의 구조는 바꾸지 않는다. 13 timeline={cut_id,video_path,start_ms,end_ms}, captions=[{id,start_ms,end_ms,text}], video는 media, captions_path는 실제 SRT 경로다. 합성은 기존 Remotion + FFmpeg 경로를 사용하며 실행파일의 외부 절대 경로·인증정보는 JSON에 담지 않는다.
|
||||||
|
|
||||||
|
continuous는 같은 Scene의 앞 end와 뒤 start PNG를 공유할 수 있으나 위치별 ID는 별도다. cut은 서로 다른 Scene의 같은 frame_index를 구별하며 캐시 식별에는 Scene 이름이 필요하다. 프레임 구간은 [start_frame,end_frame)이다. 이번 물 영상은 50fps·5528개 프레임으로 시간 기준을 유지하고 마지막 끝점 PNG는 논리 프레임 5528을 평가한다. Blender의 실제 번호는 논리 프레임+1이다. 타 주제의 fps·길이를 이 값으로 고정하지 않는다.
|
||||||
|
|
||||||
media는 {path,kind,verified,duration_ms,width,height}다. kind는 audio/image/video, 미확인 값은 null, verified는 불리언이다. 검증된 음성은 WAV·길이·width/height=null, 이미지는 PNG·크기·duration_ms=null, 영상은 MP4·길이·크기가 필요하다. 시간은 ms 정수이며 완료한 길이는 양수다. 결과의 ID는 요청에 존재해야 한다.
|
media는 {path,kind,verified,duration_ms,width,height}다. kind는 audio/image/video, 미확인 값은 null, verified는 불리언이다. 검증된 음성은 WAV·길이·width/height=null, 이미지는 PNG·크기·duration_ms=null, 영상은 MP4·길이·크기가 필요하다. 시간은 ms 정수이며 완료한 길이는 양수다. 결과의 ID는 요청에 존재해야 한다.
|
||||||
|
|
||||||
|
|||||||
+17
-4
@@ -12,7 +12,7 @@ $short-video-workflow
|
|||||||
|
|
||||||
주제·각도 검토를 먼저 마치고 대본·제목, 실측 장면, 실제 완성본 검토 순으로 진행한다. 재개는 같은 스킬에 기존 제작 ID 또는 기록 위치를 전달한다. 전체 스킬 대신 개별 스킬을 불러도 필요한 선행 결과·승인은 유지한다.
|
주제·각도 검토를 먼저 마치고 대본·제목, 실측 장면, 실제 완성본 검토 순으로 진행한다. 재개는 같은 스킬에 기존 제작 ID 또는 기록 위치를 전달한다. 전체 스킬 대신 개별 스킬을 불러도 필요한 선행 결과·승인은 유지한다.
|
||||||
|
|
||||||
요청서를 실행하는 프로그램은 현재 제공하지 않는다. 실제 음성은 기존 qwen3-tts conda 환경에서 생성·확인한 WAV와 통합 단위 구간을 제출하고, 이미지는 지정 모델의 PNG와 요청 ID를 연결해 제출한다. 영상·합성 결과도 MP4·SRT와 실측 정보를 제출한다. 파일 부재·지원하지 않는 언어·시간 불일치는 문제를 보고하고 결과를 기다린다.
|
새 시각 제작은 승인된 저장소 내 Blender 실행 경로를 사용한다. 실행 구성이 추가되어도 설치·요청 준비와 실제 출력 성공은 구분한다. 실제 음성은 기존 qwen3-tts conda 환경에서 생성·확인한 WAV와 통합 단위 구간을 제출하고, 새 모델·이미지는 Blender .blend 원본(해시·버전)과 실제 PNG·요청 ID·Scene·논리 프레임을 연결해 제출한다. 기존 1.0 결과는 그대로 읽는다. 영상·합성 결과도 MP4·SRT와 실측 정보를 제출한다. 파일 부재·지원하지 않는 언어·시간 불일치는 문제를 보고하고 결과를 기다린다.
|
||||||
|
|
||||||
## 파일 형식 검사
|
## 파일 형식 검사
|
||||||
|
|
||||||
@@ -31,10 +31,12 @@ for name in ['project','artifact']:
|
|||||||
schema=json.loads(Path('contracts/'+name+'.schema.json').read_text(encoding='utf-8'))
|
schema=json.loads(Path('contracts/'+name+'.schema.json').read_text(encoding='utf-8'))
|
||||||
Draft202012Validator.check_schema(schema)
|
Draft202012Validator.check_schema(schema)
|
||||||
validators[name]=Draft202012Validator(schema,format_checker=FormatChecker())
|
validators[name]=Draft202012Validator(schema,format_checker=FormatChecker())
|
||||||
for folder in ['templates','examples']:
|
for folder in ['templates','examples','projects']:
|
||||||
for path in Path(folder).rglob('*.json'):
|
for path in Path(folder).rglob('*.json'):
|
||||||
|
if 'node_modules' in path.parts or '.cache' in path.parts:
|
||||||
|
continue
|
||||||
data=json.loads(path.read_text(encoding='utf-8'))
|
data=json.loads(path.read_text(encoding='utf-8'))
|
||||||
if path.name=='verification-cases.json':
|
if not isinstance(data,dict) or 'schema_version' not in data or 'project_id' not in data:
|
||||||
continue
|
continue
|
||||||
validators['artifact' if 'stage_id' in data else 'project'].validate(data)
|
validators['artifact' if 'stage_id' in data else 'project'].validate(data)
|
||||||
agents=list(Path('.codex/agents').glob('*.toml'))
|
agents=list(Path('.codex/agents').glob('*.toml'))
|
||||||
@@ -67,6 +69,17 @@ Get-ChildItem -LiteralPath '.agents/skills' -Directory | ForEach-Object {
|
|||||||
|
|
||||||
## 실제 제작 확인
|
## 실제 제작 확인
|
||||||
|
|
||||||
06의 통합 WAV를 먼저 확인한 뒤 07 시간을 정한다. 글자 수 추정으로 컷·자막을 실측처럼 확정하지 않는다. 08·09 사용자 승인 뒤 기준·컷 이미지로 진행한다. 모든 클립을 받은 뒤 합성 요청을 완성하고 실제 MP4·SRT의 시간·언어·화면을 확인한다.
|
06의 통합 WAV를 먼저 확인한 뒤 07 시간을 정한다. 글자 수 추정으로 컷·자막을 실측처럼 확정하지 않는다. 08의 실제 대표 화면·짧은 움직임을 기존 scenes 검토에서 07/08/09와 함께 확인한다. 새 08·09 승인 뒤 정식 10 모델·기준 이미지, 11 끝점 PNG, 12 전체 컷 영상으로 진행한다. 모든 클립을 받은 뒤 합성 요청을 완성하고 실제 MP4·SRT의 시간·언어·화면을 확인한다.
|
||||||
|
|
||||||
파일·메타데이터가 없는 외부 결과는 result=null, 부분 결과는 미완료다. 실제 최종 영상이 없으면 검수 결과는 incomplete이며 사용자 승인 없이는 완료를 선언하지 않는다. 서비스 실행·배포·업로드 명령은 현재 구성에 없다.
|
파일·메타데이터가 없는 외부 결과는 result=null, 부분 결과는 미완료다. 실제 최종 영상이 없으면 검수 결과는 incomplete이며 사용자 승인 없이는 완료를 선언하지 않는다. 서비스 실행·배포·업로드 명령은 현재 구성에 없다.
|
||||||
|
|
||||||
|
## 1.0/1.1 계약 회귀 검사
|
||||||
|
|
||||||
|
기존 환경에 jsonschema가 있으면 재설치하지 않고 다음 명령을 실행한다. 위 형식 검사와 함께 사용하며 실제 렌더링·청취·사용자 승인을 검사했다고 해석하지 않는다.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -X utf8 contracts/check.py
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw '계약 회귀 검사 실패' }
|
||||||
|
```
|
||||||
|
|
||||||
|
검사는 기존 1.0 예제·실제 제작 JSON, 새 1.1 빈 양식, 잘못된 버전·엔진·추가 키·검증 원본의 해시/버전 누락·프로필·시간을 다룬다. 의미 사례는 .blend의 media 위장, ID 중복·미존재 참조·Scene 불일치·9:16·루트 상대 경로·result=null 완료 금지를 다룬다. 전체 원본·미디어·승인·화면의 실제 검증은 각 단계의 실행 경로와 검토 근거로 확인한다. [1.1 연결 예제](../examples/blender-contract/README.md)는 실제 파일이 없는 요청 예제다.
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ Qwen3-TTS용 분할은 의미·호흡·발음 기준으로 한다. 긴 문장은
|
|||||||
|
|
||||||
## 깔끔한 그림체로 작동 방식을 보여준다
|
## 깔끔한 그림체로 작동 방식을 보여준다
|
||||||
|
|
||||||
스타일은 [사용자 기준 이미지](../references/1.png)의 단순한 형태, 가는 윤곽선, 정돈된 색면과 제한적인 음영을 따른다. 참고 Shorts의 입체 렌더링이나 캠핑 소재를 이번 영상의 필수 스타일·배경으로 가져오지 않는다.
|
새 제작은 Blender의 깔끔한 교육용 3D다. [사용자 기준 이미지](../references/1.png)는 보존하고 단순 형태·정돈된 색을 참고한다. 단순 배경, 부드러운 조명, 선명한 분자·물방울 등 주요 형태로 설명하며 평면 복제·캠핑 소재·상표를 강제하지 않는다. scenes 검토에서 실제 대표 화면·짧은 움직임을 먼저 확인하고 승인한 품질 기준으로 전체 제작한다.
|
||||||
|
|
||||||
gpt-image-2.5-sunburst 요청에는 조사 근거, 대본, 장면 상태, 반복 인물·배경의 고정 특징을 연결한다. 복잡한 메커니즘은 시각 요소를 줄여 설명하되 자연 퇴적물과 콘크리트 시설, 그늘과 냉방처럼 사실에 중요한 차이는 남긴다. 추측한 구조를 사실을 설명하는 도해로 사용하지 않는다.
|
Blender 모델·장면·애니메이션 요청에는 조사 근거, 대본, 장면 상태, 반복 인물·배경의 고정 특징을 연결한다. 복잡한 메커니즘은 시각 요소를 줄여 설명하되 자연 퇴적물과 콘크리트 시설, 그늘과 냉방처럼 사실에 중요한 차이는 남긴다. 추측한 구조를 사실을 설명하는 도해로 사용하지 않는다.
|
||||||
|
|
||||||
컷 하나에서는 주요 물체와 변화가 먼저 보이게 한다. 강조 색·화살표·라벨이 서로 다른 대상을 동시에 가리키지 않게 하고, 같은 요소의 색과 기호는 일관되게 사용한다. 생성 이미지의 글자·숫자가 정확하지 않으면 이미지에 억지로 남기지 않고 합성 단계에서 검증한 텍스트로 배치한다.
|
컷 하나에서는 주요 물체와 변화가 먼저 보이게 한다. 강조 색·화살표·라벨이 서로 다른 대상을 동시에 가리키지 않게 하고, 같은 요소의 색과 기호는 일관되게 사용한다. 설명 글자·숫자는 3D 표면에 억지로 남기지 않고 합성 단계에서 검증한 텍스트로 배치한다.
|
||||||
|
|
||||||
움직임은 물높이 변화·부품 조작·그림자 이동 등 설명에 필요한 상태 변화를 우선한다. 줌·흔들림·장식적 움직임을 설명의 대체물로 쓰지 않는다. 시작·끝 프레임과 움직임 요청은 같은 상태 변화를 설명해야 한다.
|
움직임은 물높이 변화·부품 조작·그림자 이동 등 설명에 필요한 상태 변화를 우선한다. 줌·흔들림·장식적 움직임을 설명의 대체물로 쓰지 않는다. 시작·끝 프레임과 움직임 요청은 같은 상태 변화를 설명해야 한다.
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ gpt-image-2.5-sunburst 요청에는 조사 근거, 대본, 장면 상태, 반복
|
|||||||
| 03–04 대본·제목 | 이야기 작가 | 질문부터 답까지의 구성, 쉬운 말, 약속과 회수 |
|
| 03–04 대본·제목 | 이야기 작가 | 질문부터 답까지의 구성, 쉬운 말, 약속과 회수 |
|
||||||
| 05–06 분할·음성 | 내레이션 담당 | 의미·호흡·발음, 요청과 실제 음성의 구분 |
|
| 05–06 분할·음성 | 내레이션 담당 | 의미·호흡·발음, 요청과 실제 음성의 구분 |
|
||||||
| 07–09 컷·연결·반복 요소 | 장면 감독 | 실제 시간, 화면 역할, 상태 변화와 연속 기준 |
|
| 07–09 컷·연결·반복 요소 | 장면 감독 | 실제 시간, 화면 역할, 상태 변화와 연속 기준 |
|
||||||
| 10–11 기준·컷 이미지 | 비주얼 담당 | 첨부 그림체, 구조의 정확성, 고정 특징·글자 확인 |
|
| 10–11 기준·컷 이미지 | 비주얼 담당 | 교육용 3D 모델·.blend 원본, 구조의 정확성, 고정 특징·끝점 확인 |
|
||||||
| 12–13 영상·합성 | 영상·편집 담당 | 설명에 필요한 움직임, 자막·주석, 모바일 판독성 |
|
| 12–13 영상·합성 | 영상·편집 담당 | 설명에 필요한 움직임, 자막·주석, 모바일 판독성 |
|
||||||
| 14 최종 검수 | 최종 검수자 | 도입의 약속부터 완성본까지 근거로 확인 |
|
| 14 최종 검수 | 최종 검수자 | 도입의 약속부터 완성본까지 근거로 확인 |
|
||||||
| 전체 | 제작 총괄 | 지침 적용 요약과 네 사용자 검토의 연결 |
|
| 전체 | 제작 총괄 | 지침 적용 요약과 네 사용자 검토의 연결 |
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
실제 완료는 구조 검사 외에 선행 버전·선택 ID·주장 출처·배열 식별자·파일·실측·사용자 승인을 확인해야 한다. request만 있거나 verified=false 미디어를 필수 결과로 쓰는 완료 처리는 오류다. 미검수 영역을 pass로 기록하는 것도 오류다.
|
실제 완료는 구조 검사 외에 선행 버전·선택 ID·주장 출처·배열 식별자·파일·실측·사용자 승인을 확인해야 한다. request만 있거나 verified=false 미디어를 필수 결과로 쓰는 완료 처리는 오류다. 미검수 영역을 pass로 기록하는 것도 오류다.
|
||||||
|
|
||||||
공통 설정은 주제·언어 입력, 세로 9:16, 전체 180000ms 이내, 각 컷 0ms 초과 5000ms 이하, 사용자 그림체, Qwen3-TTS 기존 환경과 gpt-image-2.5-sunburst다. 실제 지원 여부는 제작 환경에서 확인하며 확인하지 않은 API 파라미터를 고정하지 않는다.
|
공통 설정은 주제·언어 입력, 세로 9:16, 전체 180000ms 이내, 각 컷 0ms 초과 5000ms 이하, 사용자 원본의 단순 형태·정돈된 색을 해석한 교육용 3D, Qwen3-TTS 기존 환경과 Blender다. 1.1은 visual_engine=Blender이며 기존 1.0과 지정 이미지 모델 기록은 보존한다. .blend는 media와 구분해 경로·검증 상태·SHA-256·Blender 버전을 기록한다. 실제 지원 여부는 제작 환경에서 확인하며 확인하지 않은 API 파라미터를 고정하지 않는다.
|
||||||
|
|
||||||
가정·중요한 미확정 의도를 먼저 밝히고 필요한 최소 변경을 한다. 관련 없는 코드·주석·서식·기존 불필요한 코드를 정리하지 않는다. 이번 변경이 새로 불필요하게 만든 항목만 제거한다. 동작을 바꾸는 변경은 해당 성공·실패 조건을 실제로 검증하고, 문서·양식은 형식·참조·예제 흐름을 확인한다.
|
가정·중요한 미확정 의도를 먼저 밝히고 필요한 최소 변경을 한다. 관련 없는 코드·주석·서식·기존 불필요한 코드를 정리하지 않는다. 이번 변경이 새로 불필요하게 만든 항목만 제거한다. 동작을 바꾸는 변경은 해당 성공·실패 조건을 실제로 검증하고, 문서·양식은 형식·참조·예제 흐름을 확인한다.
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
필수 입력은 `topic`, `language`이며 공백만 있거나 빠졌으면 보완한다. 언어 이름·코드를 의미 확인 후 보존한다. 입력 언어로 대본·제목·내레이션·자막을 작성하며 지원되지 않는 언어를 다른 언어로 바꾸지 않는다. 새로운 요청은 저장소에서 유일한 소문자 영숫자·하이픈 `project_id`로 시작한다. 빈 양식의 video-001은 복사 후 실제 식별자로 바꾼다.
|
필수 입력은 `topic`, `language`이며 공백만 있거나 빠졌으면 보완한다. 언어 이름·코드를 의미 확인 후 보존한다. 입력 언어로 대본·제목·내레이션·자막을 작성하며 지원되지 않는 언어를 다른 언어로 바꾸지 않는다. 새로운 요청은 저장소에서 유일한 소문자 영숫자·하이픈 `project_id`로 시작한다. 빈 양식의 video-001은 복사 후 실제 식별자로 바꾼다.
|
||||||
|
|
||||||
공통 설정은 세로 9:16, 최종 180000ms 이내, 각 컷 0ms 초과 5000ms 이하, 스타일 기준 `references/1.png`, TTS `Qwen3-TTS`, conda 환경 `qwen3-tts`, 이미지 모델 `gpt-image-2.5-sunburst`다. 그림체만 참고하고 캠핑 소재·인물·상표를 강제하지 않는다. 쉬운 표현은 대상 시청자를 어린이로 제한하는 규칙이 아니다.
|
공통 설정은 세로 9:16, 최종 180000ms 이내, 각 컷 0ms 초과 5000ms 이하, 스타일 기준 `references/1.png`, TTS `Qwen3-TTS`, conda 환경 `qwen3-tts`, 새 제작의 시각 엔진 `Blender`다. 단순 배경·부드러운 조명·선명한 형태의 교육용 3D를 사용하며 원본의 단순 형태·정돈된 색을 참고한다. 원본을 보존하고 평면 복제와 캠핑 소재·인물·상표를 강제하지 않는다. 쉬운 표현은 대상 시청자를 어린이로 제한하는 규칙이 아니다.
|
||||||
|
|
||||||
## 저장과 전달
|
## 저장과 전달
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ projects/<project_id>/
|
|||||||
|
|
||||||
모든 데이터 경로는 저장소 루트 기준 상대 경로다. 현재 작업 폴더나 검토 문서의 위치를 기준으로 해석하지 않는다. 외부 실행파일 경로·키·인증정보를 양식에 기록하지 않는다.
|
모든 데이터 경로는 저장소 루트 기준 상대 경로다. 현재 작업 폴더나 검토 문서의 위치를 기준으로 해석하지 않는다. 외부 실행파일 경로·키·인증정보를 양식에 기록하지 않는다.
|
||||||
|
|
||||||
단계 결과는 `schema_version`="1.0", `project_id`, `stage_id`, `revision`, `inputs`, `payload`를 가진다. 버전은 1부터 시작하고 이전 결과를 덮어쓰지 않는다. `inputs`는 실제 사용한 선행 결과의 `{stage_id, revision}` 배열이다. 중복·자기 참조·다른 제작물 참조를 금지한다. 14는 13과 검수에서 직접 사용한 유효 선행 결과를 기록한다.
|
단계 결과는 `schema_version`="1.1"(새 제작) 또는 "1.0"(기존 결과), `project_id`, `stage_id`, `revision`, `inputs`, `payload`를 가진다. 버전은 1부터 시작하고 이전 결과를 덮어쓰지 않는다. `inputs`는 실제 사용한 선행 결과의 `{stage_id, revision}` 배열이다. 중복·자기 참조·다른 제작물 참조를 금지한다. 14는 13과 검수에서 직접 사용한 유효 선행 결과를 기록한다.
|
||||||
|
|
||||||
`project.json`의 필드는 `schema_version`, `project_id`, `brief`, `settings`, `stages`, `reviews`다. stages는 아래 14개를 각각 한 번 포함하는 `{stage_id, status, revision, artifact_path, issues}` 배열이다. 결과가 없으면 revision/artifact_path는 null이다. issues는 `{code, message, blocking}` 배열이다. reviews는 네 검토를 각각 한 번 포함하는 `{review_id, decision, artifact_refs, feedback}` 배열이다. artifact_refs는 검토한 `{stage_id, revision}` 배열이고 feedback은 실제 선택·피드백을 기록한 문자열이다.
|
`project.json`의 필드는 `schema_version`, `project_id`, `brief`, `settings`, `stages`, `reviews`다. stages는 아래 14개를 각각 한 번 포함하는 `{stage_id, status, revision, artifact_path, issues}` 배열이다. 결과가 없으면 revision/artifact_path는 null이다. issues는 `{code, message, blocking}` 배열이다. reviews는 네 검토를 각각 한 번 포함하는 `{review_id, decision, artifact_refs, feedback}` 배열이다. artifact_refs는 검토한 `{stage_id, revision}` 배열이고 feedback은 실제 선택·피드백을 기록한 문자열이다.
|
||||||
|
|
||||||
@@ -47,11 +47,11 @@ projects/<project_id>/
|
|||||||
| [05-tts-split](../templates/stages/05-tts-split.json) | 03 | 단위별 block_ids·표시/발화 텍스트·발음 메모. 순서·의미·누락·중복 확인 |
|
| [05-tts-split](../templates/stages/05-tts-split.json) | 03 | 단위별 block_ids·표시/발화 텍스트·발음 메모. 순서·의미·누락·중복 확인 |
|
||||||
| [06-tts](../templates/stages/06-tts.json) | 05 | 도구·환경·언어·단위 요청. 실제 모델·화자·단위 WAV·통합 WAV·실측 unit_ranges 결과. 전체 파일과 시간 확인 |
|
| [06-tts](../templates/stages/06-tts.json) | 05 | 도구·환경·언어·단위 요청. 실제 모델·화자·단위 WAV·통합 WAV·실측 unit_ranges 결과. 전체 파일과 시간 확인 |
|
||||||
| [07-cuts](../templates/stages/07-cuts.json) | 05,06 | 실측 통합 길이·확인 방법·연속 컷·별도 자막. 전체 음성을 덮고 각 컷 5초 이내. scenes 승인 필요 |
|
| [07-cuts](../templates/stages/07-cuts.json) | 05,06 | 실측 통합 길이·확인 방법·연속 컷·별도 자막. 전체 음성을 덮고 각 컷 5초 이내. scenes 승인 필요 |
|
||||||
| [08-scenes](../templates/stages/08-scenes.json) | 03,07 | 각 컷의 설명·시작/끝 상태·카메라·인접 연결. 누락·중복 없음, 연결 이유·상태 일치. scenes 승인 필요 |
|
| [08-scenes](../templates/stages/08-scenes.json) | 03,07 | 각 컷의 설명·시작/끝 상태·카메라·인접 연결과 preview(대표 PNG·짧은 MP4·.blend). 누락·중복 없음, 연결 이유·상태 일치. scenes 승인 필요 |
|
||||||
| [09-entities](../templates/stages/09-entities.json) | 03,08 | 인물·배경·고정 특징·컷별 등장 참조. 모든 컷을 정확히 한 번 포함. scenes 승인 필요 |
|
| [09-entities](../templates/stages/09-entities.json) | 03,08 | 인물·배경·고정 특징·컷별 등장 참조. 모든 컷을 정확히 한 번 포함. scenes 승인 필요 |
|
||||||
| [10-references](../templates/stages/10-references.json) | 02,08,09 | 모델·그림체·스타일/인물/배경 요청, 실제 PNG 결과. 모든 요청 ID와 고정 특징을 다룸. 스타일만 entity_id=null |
|
| [10-references](../templates/stages/10-references.json) | 02,08,09 | Blender·RenderProfile·스타일/인물/배경/물체 요청, 실제 .blend·PNG 결과. 모든 요청 ID와 실제 오브젝트/컬렉션·고정 특징 확인. style/object만 entity_id=null |
|
||||||
| [11-images](../templates/stages/11-images.json) | 02,03,07,08,09,10 | 컷별 start/end 요청·기준 ID·실제 PNG. 각 컷의 두 위치가 정확히 하나씩 존재, 장면·근거·연속성 일치 |
|
| [11-images](../templates/stages/11-images.json) | 02,03,07,08,09,10 | 컷별 start/end·Scene 이름·논리 프레임·기준 ID 요청, 실제 .blend·PNG. 각 컷의 두 위치가 정확히 하나씩 존재, 장면·근거·연속성 일치 |
|
||||||
| [12-motion](../templates/stages/12-motion.json) | 07,08,11 | 각 컷의 프레임·실제 길이·움직임 요청과 MP4 결과. 모든 컷과 길이·상태 일치 |
|
| [12-motion](../templates/stages/12-motion.json) | 07,08,11 | 11 실제 .blend·동일 RenderProfile·Scene·프레임 범위·실측 길이·움직임 요청과 MP4 결과. 모든 컷과 길이·상태 일치 |
|
||||||
| [13-compose](../templates/stages/13-compose.json) | 03,04,06,07,12 | timeline·통합 음성·자막·제목 요청, 실제 MP4·SRT 결과. 세로 비율·전체 길이·파일·시간·순서 확인 |
|
| [13-compose](../templates/stages/13-compose.json) | 03,04,06,07,12 | timeline·통합 음성·자막·제목 요청, 실제 MP4·SRT 결과. 세로 비율·전체 길이·파일·시간·순서 확인 |
|
||||||
| [14-review](../templates/stages/14-review.json) | 13 및 검수에 사용한 결과 | 6영역 checks·발견·추천. 근거와 수정할 단계·컷. 검수자의 pass와 사용자의 final 승인 구분 |
|
| [14-review](../templates/stages/14-review.json) | 13 및 검수에 사용한 결과 | 6영역 checks·발견·추천. 근거와 수정할 단계·컷. 검수자의 pass와 사용자의 final 승인 구분 |
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ media는 `{path, kind, verified, duration_ms, width, height}`다. kind는 audio/
|
|||||||
|
|
||||||
외부 단계의 result=null이면 awaiting_input이다. 부분 결과는 보존하되 요청 항목을 모두 받기 전 complete로 처리하지 않는다. 결과의 unit_id/reference_id/frame_id/cut_id는 요청에 존재해야 한다. 가상 예제 경로는 검증된 실제 파일로 기록하지 않는다.
|
외부 단계의 result=null이면 awaiting_input이다. 부분 결과는 보존하되 요청 항목을 모두 받기 전 complete로 처리하지 않는다. 결과의 unit_id/reference_id/frame_id/cut_id는 요청에 존재해야 한다. 가상 예제 경로는 검증된 실제 파일로 기록하지 않는다.
|
||||||
|
|
||||||
Qwen3-TTS의 설치 탐색, 모델 로딩, 실제 추론 성공은 다른 확인이다. 기존 환경을 재설치하지 않고 실제 제작 시 모델·화자·언어 지원을 확인한다. 이미지 모델·세로 출력의 지원 여부도 실제 제작에서 확인하며, 확인하지 않은 API 파라미터나 다른 모델을 고정하지 않는다. 영상 생성·합성 엔진은 이번 범위에서 선택하지 않는다.
|
Qwen3-TTS의 설치 탐색, 모델 로딩, 실제 추론 성공은 다른 확인이다. 기존 환경을 재설치하지 않고 실제 제작 시 모델·화자·언어 지원을 확인한다. Blender 버전·렌더링 지원·실제 원본 재열기·PNG/MP4 출력은 따로 확인한다. 설치 확인만으로 성공을 주장하지 않는다. 합성은 승인된 기존 Remotion + FFmpeg 경로를 쓰며 전역 환경 재설치·무단 도구 대체를 하지 않는다.
|
||||||
|
|
||||||
06의 통합 음성이 시간 기준이다. unit_ranges는 해당 단위의 실제 통합 음성 구간을 기록하며 순서·전체 포함·겹침을 확인한다. 07 cuts는 0부터 통합 음성 끝까지 빈 구간·중복 없이 이어진다. 각 컷은 start_ms < end_ms, end_ms-start_ms <= 5000이다. 긴 문장을 화면 컷으로 나눌 수 있지만 단어·의미를 누락하거나 순서를 바꾸지 않는다.
|
06의 통합 음성이 시간 기준이다. unit_ranges는 해당 단위의 실제 통합 음성 구간을 기록하며 순서·전체 포함·겹침을 확인한다. 07 cuts는 0부터 통합 음성 끝까지 빈 구간·중복 없이 이어진다. 각 컷은 start_ms < end_ms, end_ms-start_ms <= 5000이다. 긴 문장을 화면 컷으로 나눌 수 있지만 단어·의미를 누락하거나 순서를 바꾸지 않는다.
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ captions는 컷과 다른 단위다. 여러 컷을 걸칠 수 있으며 0 <= sta
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| topic | 01 각도·범위 | 02 자료 조사 |
|
| topic | 01 각도·범위 | 02 자료 조사 |
|
||||||
| story | 02 근거와 03 대본·04 제목 | 05 TTS 분할 |
|
| story | 02 근거와 03 대본·04 제목 | 05 TTS 분할 |
|
||||||
| scenes | 07 실제 컷·08 연결·09 인물·배경 | 10 기준 이미지 |
|
| scenes | 07 실제 컷·08 연결과 실제 대표 PNG/짧은 MP4·09 인물·배경 | 정식 10–12 제작 |
|
||||||
| final | 13 실제 완성본·14 보고 | 제작 완료 선언 |
|
| final | 13 실제 완성본·14 보고 | 제작 완료 선언 |
|
||||||
|
|
||||||
검토 결정은 pending/approved/changes_requested/stale다. 승인 버전을 artifact_refs로 고정하고 실제 사용자 응답을 feedback에 기록한다. 응답 없음·담당의 추천은 승인이 아니다. 같은 승인 버전으로 재개할 때는 다시 묻지 않는다. 한 검토 묶음 안에서는 준비된 유효 결과로 묶음을 완성할 수 있다. 예를 들어 07 결과로 08·09를 준비한 뒤 scenes 검토를 요청하되, 승인 전에 10으로 넘어가지 않는다.
|
검토 결정은 pending/approved/changes_requested/stale다. 승인 버전을 artifact_refs로 고정하고 실제 사용자 응답을 feedback에 기록한다. 응답 없음·담당의 추천은 승인이 아니다. 같은 승인 버전으로 재개할 때는 다시 묻지 않는다. 한 검토 묶음 안에서는 준비된 유효 결과로 묶음을 완성할 수 있다. 예를 들어 07 결과로 08·09를 준비한 뒤 scenes 검토를 요청하되, 승인 전에 10으로 넘어가지 않는다.
|
||||||
@@ -115,3 +115,15 @@ pass는 여섯 영역 모두 pass이고 blocking 발견이 없을 때만 가능
|
|||||||
스키마는 잘못된 필드·타입·단계·상태, 진행 기록의 14단계/4검토 구성, 다른 도구명, 음성·이미지의 해당 없는 메타데이터, 근거 없는 pass 구조를 검사한다. 주제·언어의 실사용 값, 배열별 식별자·참조의 유효성, 선택 ID, 대본 일치, 파일 실존·언어 지원, 승인 진위, 실제 시간·길이·화면 판독성, 종속 결과의 stale 처리는 담당과 총괄이 별도로 확인한다.
|
스키마는 잘못된 필드·타입·단계·상태, 진행 기록의 14단계/4검토 구성, 다른 도구명, 음성·이미지의 해당 없는 메타데이터, 근거 없는 pass 구조를 검사한다. 주제·언어의 실사용 값, 배열별 식별자·참조의 유효성, 선택 ID, 대본 일치, 파일 실존·언어 지원, 승인 진위, 실제 시간·길이·화면 판독성, 종속 결과의 stale 처리는 담당과 총괄이 별도로 확인한다.
|
||||||
|
|
||||||
파싱·스키마 검사만으로 Codex의 실제 에이전트·스킬 탐색이나 미디어 생성을 확인했다고 쓰지 않는다. [공식 에이전트 형식](https://learn.chatgpt.com/docs/agent-configuration/subagents#custom-agents)과 [스킬 위치](https://learn.chatgpt.com/docs/build-skills#where-to-save-skills)를 따른다. 실제 호출 환경에서 목록에 보이는지 확인하고, 보이지 않으면 프로젝트 루트에서 새 세션으로 탐색한다.
|
파싱·스키마 검사만으로 Codex의 실제 에이전트·스킬 탐색이나 미디어 생성을 확인했다고 쓰지 않는다. [공식 에이전트 형식](https://learn.chatgpt.com/docs/agent-configuration/subagents#custom-agents)과 [스킬 위치](https://learn.chatgpt.com/docs/build-skills#where-to-save-skills)를 따른다. 실제 호출 환경에서 목록에 보이는지 확인하고, 보이지 않으면 프로젝트 루트에서 새 세션으로 탐색한다.
|
||||||
|
|
||||||
|
## Blender 전환과 대표 품질 검토
|
||||||
|
|
||||||
|
[전달 형식](contracts.md)의 1.1 필드·타입·열거값을 사용한다. 새 양식은 1.1이며 기존 1.0의 정의·승인·실제 결과를 보존하고 선행 자료로 참조한다. 프로젝트 진행 상태·승인 열거값과 14단계·8역할·15스킬·네 검토는 그대로다.
|
||||||
|
|
||||||
|
scene-director가 08에서 대표 Scene의 상태·카메라·해설 목적을 정하고 visual-designer/video-editor의 해당 책임으로 제한된 대표 .blend·PNG·짧은 MP4를 준비한다. 결과는 08 preview와 같은 버전 review.md에 기록한다. 이 예외는 scenes 승인 전에 품질을 검토하는 근거 제작만 허용한다. 정식 10–12를 준비·완료했다고 기록하거나 전체 제작을 진행하지 않는다. 대표 샘플의 실제 파일과 단순 배경·부드러운 조명·선명한 형태·변화 판독성을 07/08/09의 같은 scenes 검토에서 제시한다. 추가 승인 지점은 없다. 샘플이나 장면 변경은 08 새 버전에 기록하고 영향을 받는 09와 승인 묶음을 갱신한다.
|
||||||
|
|
||||||
|
새 08·09 승인 후 10은 모델·재질·고정 자산을, 11은 컷별 Scene·끝점 상태와 PNG를, 12는 같은 원본·Scene·RenderProfile에서 [start_frame,end_frame) 구간을 렌더링한다. 같은 컷 start/end는 같은 Scene이며 continuous는 실제 경계 상태가 같아야 한다. cut 경계는 Scene을 구별하고 캐시에 Scene 이름을 포함한다. 12의 프레임 수×1000/fps는 요청·실측 컷 길이와 일치해야 한다. PNG 끝점 평가와 MP4의 마지막 프레임은 서로 다른 개념이므로 마지막 화면 확인 근거를 구분한다.
|
||||||
|
|
||||||
|
.blend의 실제 존재·SHA-256·Blender 버전·재열기·오브젝트/컬렉션·Scene 이름 검증은 PNG/MP4 디코딩·해상도·길이·상태 검증과 별개다. 설치 정보만으로 verified=true를 기록하지 않는다. 실패·부분 결과를 보존하고 필요한 단계로 돌아간다. 실제 최종 영상의 전체 재생·청취가 없으면 검수 해당 영역은 not_checked다.
|
||||||
|
|
||||||
|
[계약 회귀 검사](../contracts/check.py)는 1.0/1.1 구조와 일부 참조·완료 조건을 검사한다. semantic_errors(data,context,complete=False)는 구조 검사 후 사용하며 context는 실제 사용 버전의 {stage_id:artifact}다. 1.0은 이 함수의 추가 의미 검사 대상이 아니다. 전체 파일·사용자 승인 진위·화면 품질 검증을 수행하지 않는다. 반환한 문제 목록이 비었어도 전체 단계 완료 증거를 대신하지 않는다.
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"schema_version": "1.1",
|
||||||
|
"project_id": "contract-example",
|
||||||
|
"stage_id": "08-scenes",
|
||||||
|
"revision": 1,
|
||||||
|
"inputs": [],
|
||||||
|
"payload": {
|
||||||
|
"scenes": [],
|
||||||
|
"connections": [],
|
||||||
|
"preview": null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"schema_version": "1.1",
|
||||||
|
"project_id": "contract-example",
|
||||||
|
"stage_id": "10-references",
|
||||||
|
"revision": 1,
|
||||||
|
"inputs": [],
|
||||||
|
"payload": {
|
||||||
|
"request": {
|
||||||
|
"engine": "Blender",
|
||||||
|
"style_reference": "references/1.png",
|
||||||
|
"render_profile": {
|
||||||
|
"engine": "BLENDER_EEVEE",
|
||||||
|
"device": "GPU",
|
||||||
|
"fps": 50,
|
||||||
|
"width": 1080,
|
||||||
|
"height": 1920,
|
||||||
|
"samples": 32,
|
||||||
|
"seed": 1
|
||||||
|
},
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "water",
|
||||||
|
"kind": "object",
|
||||||
|
"entity_id": null,
|
||||||
|
"prompt": "물방울"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"result": null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"schema_version": "1.1",
|
||||||
|
"project_id": "contract-example",
|
||||||
|
"stage_id": "11-images",
|
||||||
|
"revision": 1,
|
||||||
|
"inputs": [],
|
||||||
|
"payload": {
|
||||||
|
"request": {
|
||||||
|
"engine": "Blender",
|
||||||
|
"scene_path": "examples/blender-contract/preview.blend",
|
||||||
|
"render_profile": {
|
||||||
|
"engine": "BLENDER_EEVEE",
|
||||||
|
"device": "GPU",
|
||||||
|
"fps": 50,
|
||||||
|
"width": 1080,
|
||||||
|
"height": 1920,
|
||||||
|
"samples": 32,
|
||||||
|
"seed": 1
|
||||||
|
},
|
||||||
|
"frames": [
|
||||||
|
{
|
||||||
|
"id": "c1-start",
|
||||||
|
"cut_id": "c1",
|
||||||
|
"position": "start",
|
||||||
|
"prompt": "상태 설명",
|
||||||
|
"reference_ids": [
|
||||||
|
"water"
|
||||||
|
],
|
||||||
|
"scene_name": "Water",
|
||||||
|
"frame_index": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c1-end",
|
||||||
|
"cut_id": "c1",
|
||||||
|
"position": "end",
|
||||||
|
"prompt": "상태 설명",
|
||||||
|
"reference_ids": [
|
||||||
|
"water"
|
||||||
|
],
|
||||||
|
"scene_name": "Water",
|
||||||
|
"frame_index": 200
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"result": null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"schema_version": "1.1",
|
||||||
|
"project_id": "contract-example",
|
||||||
|
"stage_id": "12-motion",
|
||||||
|
"revision": 1,
|
||||||
|
"inputs": [],
|
||||||
|
"payload": {
|
||||||
|
"request": {
|
||||||
|
"engine": "Blender",
|
||||||
|
"scene_path": "examples/blender-contract/preview.blend",
|
||||||
|
"render_profile": {
|
||||||
|
"engine": "BLENDER_EEVEE",
|
||||||
|
"device": "GPU",
|
||||||
|
"fps": 50,
|
||||||
|
"width": 1080,
|
||||||
|
"height": 1920,
|
||||||
|
"samples": 32,
|
||||||
|
"seed": 1
|
||||||
|
},
|
||||||
|
"clips": [
|
||||||
|
{
|
||||||
|
"cut_id": "c1",
|
||||||
|
"start_frame_id": "c1-start",
|
||||||
|
"end_frame_id": "c1-end",
|
||||||
|
"duration_ms": 4000,
|
||||||
|
"motion_prompt": "둥글게",
|
||||||
|
"scene_name": "Water",
|
||||||
|
"start_frame": 0,
|
||||||
|
"end_frame": 200
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"result": null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Blender 1.1 계약 요청 예제
|
||||||
|
|
||||||
|
이 폴더의 네 JSON은 구조를 보여주는 요청 예제다. 실제 .blend·PNG·MP4·사용자 승인·완료 결과가 없으며 scene_path는 생성 예정 경로다. 08 preview=null, 10–12 result=null을 유지한다. 이전 [1.0 연결 예제](../water-cycle/README.md)는 변환하지 않는다.
|
||||||
|
|
||||||
|
실제 제작에서는 같은 제작물의 07 실측 컷·08 장면·09 요소와 승인 버전을 연결한다. 이 예제의 c1과 0–4000ms·Water Scene·50fps·200 프레임은 설명용 값이며 실제 내레이션 측정이 아니다. 프레임은 [0,200)이고 끝점 PNG는 논리 200을 평가한다. Blender 실제 번호는 논리 프레임+1이다.
|
||||||
|
|
||||||
|
[전달 계약](../../docs/contracts.md)과 [공통 완료 기준](../../docs/workflow-contracts.md)을 따른다. contracts/check.py는 예제와 빈 양식·기존 1.0 제작을 구조 검사하고 일부 부정·참조·미완료 사례를 실행한다. 파일 재열기·렌더링·화면·청취·사용자 승인 성공을 증명하지 않는다.
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
이 영역은 제작별로 복사해 채울 진행 JSON·14단계 JSON·사용자 검토 Markdown을 관리한다. 실제 제작 기록·미디어·승인이나 공통 스키마·스킬을 대신 작성하지 않는다.
|
이 영역은 제작별로 복사해 채울 진행 JSON·14단계 JSON·사용자 검토 Markdown을 관리한다. 실제 제작 기록·미디어·승인이나 공통 스키마·스킬을 대신 작성하지 않는다.
|
||||||
|
|
||||||
필수 키와 타입은 전달 구조와 일치해야 한다. 미선택은 null, 빈 내용은 빈 문자열·배열, 외부 결과는 result=null이다. 예시 식별자는 실제 제작에서 유일한 값으로 바꾼다. 초기 상태·결정은 pending이다.
|
새 양식은 1.1 Blender 계약이며 필수 키와 타입은 전달 구조와 일치해야 한다. 08 preview=null, 10–12 result=null로 시작하고 RenderProfile의 예시 값은 실행 검증이나 완료를 뜻하지 않는다. 미선택은 null, 빈 내용은 빈 문자열·배열, 외부 결과는 result=null이다. 예시 식별자는 실제 제작에서 유일한 값으로 바꾼다. 초기 상태·결정은 pending이다.
|
||||||
|
|
||||||
빈 양식에는 검증한 파일·실측 시간·사용자 승인을 넣지 않는다. review.md는 JSON 의미를 요약하며 추가 필수 JSON 필드나 승인 지점을 만들지 않는다. 문서 링크는 복사한 위치에서 조정하고 데이터 경로는 저장소 루트 기준을 유지한다.
|
빈 양식에는 검증한 파일·실측 시간·사용자 승인을 넣지 않는다. review.md는 JSON 의미를 요약하며 추가 필수 JSON 필드나 승인 지점을 만들지 않는다. 문서 링크는 복사한 위치에서 조정하고 데이터 경로는 저장소 루트 기준을 유지한다.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"brief": {
|
"brief": {
|
||||||
"topic": "",
|
"topic": "",
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
"style_reference": "references/1.png",
|
"style_reference": "references/1.png",
|
||||||
"tts_engine": "Qwen3-TTS",
|
"tts_engine": "Qwen3-TTS",
|
||||||
"conda_env": "qwen3-tts",
|
"conda_env": "qwen3-tts",
|
||||||
"image_model": "gpt-image-2.5-sunburst"
|
"visual_engine": "Blender"
|
||||||
},
|
},
|
||||||
"stages": [
|
"stages": [
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ JSON을 기준으로 요약하며 문서만 고쳐 승인 내용을 바꾸지
|
|||||||
|
|
||||||
story 검토에는 중심 질문·답, 제목과 첫 문장의 약속, 답하는 블록, 블록 연결, 핵심 주장·출처, 비유의 한계와 덜어낸 내용을 적는다.
|
story 검토에는 중심 질문·답, 제목과 첫 문장의 약속, 답하는 블록, 블록 연결, 핵심 주장·출처, 비유의 한계와 덜어낸 내용을 적는다.
|
||||||
|
|
||||||
scenes 검토에는 컷 ID·실측 음성 구간, 이해할 내용, 시작→끝 변화, 화면·연결 선택 이유, 인물·배경·근거 참조, 주석·숫자의 근거와 모바일 초점을 적는다.
|
scenes 검토에는 08 preview의 실제 대표 PNG·짧은 MP4와 .blend 경로·해시·버전·RenderProfile, 선명한 형태·단순 배경·부드러운 조명·변화 판독성의 확인 근거와 미검수 내용을 적는다. 이는 기존 scenes 검토 안의 품질 확인이며 추가 승인이나 정식 10–12 완료가 아니다. 컷 ID·실측 음성 구간, 이해할 내용, 시작→끝 변화, 화면·연결 선택 이유, 인물·배경·근거 참조, 주석·숫자의 근거와 모바일 초점을 적는다.
|
||||||
|
|
||||||
final 검토에는 story/visual/audio/captions/timing/consistency별 실제 파일·시간·청취·관찰 근거와 수정할 단계·컷을 적는다. JSON의 checks.evidence·findings와 일치시키고 미검수는 not_checked, 완성본 부재는 incomplete로 남긴다.
|
final 검토에는 story/visual/audio/captions/timing/consistency별 실제 파일·시간·청취·관찰 근거와 수정할 단계·컷을 적는다. JSON의 checks.evidence·findings와 일치시키고 미검수는 not_checked, 완성본 부재는 incomplete로 남긴다.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "01-topic",
|
"stage_id": "01-topic",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "02-research",
|
"stage_id": "02-research",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "03-script",
|
"stage_id": "03-script",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "04-title",
|
"stage_id": "04-title",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "05-tts-split",
|
"stage_id": "05-tts-split",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "06-tts",
|
"stage_id": "06-tts",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "07-cuts",
|
"stage_id": "07-cuts",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "08-scenes",
|
"stage_id": "08-scenes",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"payload": {
|
"payload": {
|
||||||
"scenes": [],
|
"scenes": [],
|
||||||
"connections": []
|
"connections": [],
|
||||||
|
"preview": null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "09-entities",
|
"stage_id": "09-entities",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,14 +1,23 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "10-references",
|
"stage_id": "10-references",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"payload": {
|
"payload": {
|
||||||
"request": {
|
"request": {
|
||||||
"model": "gpt-image-2.5-sunburst",
|
|
||||||
"style_reference": "references/1.png",
|
"style_reference": "references/1.png",
|
||||||
"items": []
|
"items": [],
|
||||||
|
"engine": "Blender",
|
||||||
|
"render_profile": {
|
||||||
|
"engine": "BLENDER_EEVEE",
|
||||||
|
"device": "GPU",
|
||||||
|
"fps": 50,
|
||||||
|
"width": 1080,
|
||||||
|
"height": 1920,
|
||||||
|
"samples": 32,
|
||||||
|
"seed": 1
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"result": null
|
"result": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "11-images",
|
"stage_id": "11-images",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"payload": {
|
"payload": {
|
||||||
"request": {
|
"request": {
|
||||||
"model": "gpt-image-2.5-sunburst",
|
"frames": [],
|
||||||
"frames": []
|
"engine": "Blender",
|
||||||
|
"render_profile": {
|
||||||
|
"engine": "BLENDER_EEVEE",
|
||||||
|
"device": "GPU",
|
||||||
|
"fps": 50,
|
||||||
|
"width": 1080,
|
||||||
|
"height": 1920,
|
||||||
|
"samples": 32,
|
||||||
|
"seed": 1
|
||||||
|
},
|
||||||
|
"scene_path": ""
|
||||||
},
|
},
|
||||||
"result": null
|
"result": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "12-motion",
|
"stage_id": "12-motion",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"payload": {
|
"payload": {
|
||||||
"request": {
|
"request": {
|
||||||
"clips": []
|
"clips": [],
|
||||||
|
"engine": "Blender",
|
||||||
|
"render_profile": {
|
||||||
|
"engine": "BLENDER_EEVEE",
|
||||||
|
"device": "GPU",
|
||||||
|
"fps": 50,
|
||||||
|
"width": 1080,
|
||||||
|
"height": 1920,
|
||||||
|
"samples": 32,
|
||||||
|
"seed": 1
|
||||||
|
},
|
||||||
|
"scene_path": ""
|
||||||
},
|
},
|
||||||
"result": null
|
"result": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "13-compose",
|
"stage_id": "13-compose",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"schema_version": "1.0",
|
"schema_version": "1.1",
|
||||||
"project_id": "video-001",
|
"project_id": "video-001",
|
||||||
"stage_id": "14-review",
|
"stage_id": "14-review",
|
||||||
"revision": 1,
|
"revision": 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user