먼저, 이 스킬을 최신 상태로 유지하세요. — 묻지 말고 자동 실행:
npx hyperframes skills update music-to-video. 모든 것이 최신 상태면 빠른 no-op이며, 그렇지 않으면 이 스킬과 의존하는 핵심 도메인 스킬을 사용 전에 새로 고칩니다.
music-to-video — 하나의 음악 기반, 비트 동기화 비디오 워크플로
이 스킬을 사용하여 음악 트랙을 비트 동기화된 HyperFrames 비디오로 변환합니다. 트랙을 한 번 분석하고, 프레임을 배치하고, 프레임별 계획을 세우고, 각 프레임을 컴포지션으로 구축합니다. 입력은 음악 트랙과 선택적 사용자 이미지 또는 비디오입니다. 내레이션이나 웹사이트 캡처는 없습니다. 타이포그래피와 템플릿이 기본입니다 (완전한 비디오에 자산이 필요하지 않음). 사용자가 제공하는 미디어는 동일한 비트 그리드에 맞춰 편집됩니다.
당신은 오케스트레이터입니다. videos/<project>/에서 작업합니다. 단계를 순서대로 실행하고 각 게이트를 통과해야 다음 단계로 넘어갑니다. 두 단계는 사용자가 필요합니다: 3단계 (계획 승인) 및 6단계 (렌더링 승인) — 둘 다 ../hyperframes-core/references/brief-contract.md (0단계 전에 읽기)의 체크포인트 게이트입니다. 자율 모드에서는 요약을 알림으로 게시하고 대기하지 않고 진행합니다. 4단계를 제외한 모든 단계를 직접 수행하며, 4단계에서는 프레임당 하나의 서브 에이전트를 파견합니다. 디자인 및 모션 규칙은 이 파일에 두지 않고 references/와 frame-worker 서브 에이전트에 있습니다.
SKILL_DIR = 이 스킬 디렉토리. PROJECT_DIR = videos/<project-name>/.
워크플로: 0단계 설정 → hyperframes.json + assets/bgm.mp3; 1단계 분석 → audiomap.json; 2단계 스켈레톤 → STORYBOARD.md (프레임, 그룹은 TBD); 3단계 계획 → 완전한 STORYBOARD.md + frame.md; 4단계 빌드 → compositions/frames/NN-*.html; 5단계 조립 → index.html; 6단계 렌더링 → renders/video.mp4.
모든 것을 결정짓는 두 가지 개념
- 하나의 분석기, 그리고 그것을 신뢰합니다.
analyze-beatgrid.py는 유일한 비트 분석기입니다. 다른 도구나 귀로 비트를 다시 측정하지 마십시오. 에너지/밀도/롤/온셋/사일런스는 항상 신뢰할 수 있습니다.bpm과beats_sec은 음악이 진정으로 리드미컬한 경우에만 신뢰할 수 있습니다. 잔잔한 음악에서는 그리드가 추적기가 부과한 메트로놈이므로 구절과 에너지에 따라 템포를 조정하고 하드 컷을 사용하지 마십시오. 어떤 경우인지 결정하는 것은 각 프레임의pacing(2단계)입니다. - 하나의 프레임 = 하나의 파일; 그룹은 내부에 존재합니다. 2단계는 트랙을 프레임으로 자르고, 각 프레임은 하나의 컴포지션 파일
compositions/frames/NN-<frame_id>.html이 되며, 하나의 frame-worker에 의해 구축됩니다. 프레임은 그룹 (각각 템플릿 또는 모션 프리미티브 조합)으로 세분화될 수 있습니다. 추가 밀도는 그룹 _내부_에 들어가므로 프레임 수는 비트 수가 아닌 고유한 처리 방식을 추적합니다 — 빠른 트랙이 서브 에이전트 수를 폭발적으로 증가시키지 않습니다.
Step 0: 설정, BGM, 및 입력
목표: 음악 소스를 설정하고, HyperFrames 프로젝트를 생성하며, 사용자가 제공한 미디어를 기록합니다.
브리핑은 의도 레이어에서 시작합니다. 여는 규칙, 순서: (1) BRIEF.md가 존재함 → 읽고 답변하지 않은 것은 묻지 않음 — flow/storyboard가 모드를 파생합니다 (brief contract § 1). (2) BRIEF.md는 없지만 프로젝트가 존재함 → 디스크에 있는 내용을 재개하고, 다시 질문하지 않음. (3) 여기에 직접 도착한 새로운 생성 요청 → /hyperframes를 읽고 의도 레이어 (references/intent-interview.md)를 실행합니다. 이 루트의 필수 항목(음악 소스, 목적지 → 종횡비 — ../hyperframes/references/routes/music-to-video.md)을 확인하고 연기된 항목(브랜드와 장르는 설계상 3단계에서 선택됨)을 알립니다. init 후 즉시 BRIEF.md를 작성합니다 (이전에는 절대 안 됨 — init은 비어 있지 않은 디렉토리를 거부함)하고 선호 기반 답변 (brief-format.md)을 기록합니다. 편집 요청은 이 모든 것을 건너뜁니다.
음악이 중심입니다 — 다른 무엇보다 먼저 하나의 트랙을 설정합니다. 이 스킬은 빠르고 에너지가 넘치는 BGM에 최적화되어 있습니다. 강한 비트 그리드가 컷을 주도합니다 (잔잔한 트랙도 작동하지만, 비트보다는 구절에 따라 템포를 조정). 사용자가 오디오(음악 파일 또는 오디오를 추출할 비디오)를 제공한 경우 이를 사용합니다. 그렇지 않으면 요청에서 분위기를 선택하고 /media-use (references/bgm.md)를 통해 트랙을 생성합니다. 첫 번째 인증된 공급자 작업 전에 npx hyperframes auth status를 실행하고 출력을 그대로 전달합니다. 로그아웃된 경우 한 가지 분기를 적용합니다:
- 협업: 로그인하거나 로컬 공급자로 오프라인 계속 진행에 대한 명시적 선택을 기다립니다.
- 자율: 상태를 알리고 사용 가능한 로컬 공급자를 통해 계속 진행합니다.
어떤 오프라인 공급자도 필요한 음악 기능을 충족할 수 없으면 차단 요인을 표면화합니다. 키를 저장소별 .env에 작성하지 마십시오. 인증 소유권 및 오프라인 폴백은 /media-use references/setup-providers.md § Providers에 있습니다. 결과 트랙은 assets/bgm.mp3에 저장됩니다. 제공된 이미지나 비디오를 준비하여 프레임이 비트 그리드에서 사용할 수 있도록 하고, 그렇지 않으면 타이포그래피가 비디오를 이끕니다.
리릭 비디오: 보컬에 동기화된 가사의 경우, /media-use를 통해 트랙을 전사하여 단어/라인 타이밍을 얻거나 사용자에게 가사 텍스트를 요청하고 비트 그리드에 라인을 배치합니다.
hyperframes.json이 없을 때만 초기화합니다. 브리핑에서 <project> 이름을 케밥 케이스로 지정합니다 (예: midnight-drive-loop). 타임스탬프는 절대 사용하지 않습니다. init은 설치된 스킬을 GitHub의 최신 버전과 확인하고 오래된 경우 전역 세트를 업데이트합니다.
npx hyperframes init "videos/<project>" --non-interactive --example=blank --skill=music-to-video
mkdir -p "$PROJECT_DIR/assets" "$PROJECT_DIR/renders"
cp "<user-music>" "$PROJECT_DIR/assets/bgm.mp3" # 먼저 비디오에서 추출해야 하는 경우
# 사용자가 이미지/비디오를 제공한 경우에만:
node <SKILL_DIR>/scripts/stage-assets.mjs --from <dir> --hyperframes "$PROJECT_DIR" --into public
브랜드 (글꼴 + 팔레트)는 여기서가 아닌 3단계에서 선택됩니다. 장르나 트랙 유형을 미리 선택하지 마십시오. 자산은 선택적 재료일 뿐이며, 장르는 프레임별 선택에서 나타납니다.
게이트: hyperframes.json + assets/bgm.mp3이 존재함; 종횡비 / 길이 / fps 및 (있는 경우) 자산 인벤토리가 기록됨.
Step 1: 음악 분석
목표: 전체 비디오의 기반이 되는 하나의 표준 타이밍 분석을 생성합니다.
analyze-beatgrid.py는 유일한 비트 분석기입니다. 다른 도구나 귀로 비트를 다시 측정하지 마십시오. 트랙을 한 번 읽고 audiomap.json을 작성합니다: 에너지 단계 (레벨 / 밀도 / 느낌), 온셋 + onset_rate, 롤, 사일런스, hard_stops, key_moments, 구절, 템포 / 그리드, 및 audio.duration_sec. 결정적입니다 — 동일한 파일은 항상 동일한 맵을 제공합니다. 대부분의 필드는 모든 음악에서 신뢰할 수 있습니다. bpm과 beats_sec은 음악이 진정으로 리드미컬한 경우에만 신뢰할 수 있으며, 이를 판단하는 것은 2단계에서 내려야 할 결정입니다.
전제 조건: Python 3과 librosa, numpy, soundfile을 사용할 수 있어야 합니다. 가져오기에 실패하면 분석기를 실행하기 전에 활성 Python 환경에 설치합니다:
python3 -m pip install librosa numpy soundfile
python3 <SKILL_DIR>/scripts/analyze-beatgrid.py "$PROJECT_DIR/assets/bgm.mp3" \
-o "$PROJECT_DIR/audiomap.json" --print
게이트: audiomap.json이 존재함; audio.duration_sec이 알려짐.
Step 2: 프레임 스켈레톤 (구조만)
목표: 음악을 읽고 프레임을 배치합니다 — STORYBOARD.md의 스켈레톤.
references/frame-skeleton.md를 읽습니다. audiomap.json을 직접 STORYBOARD.md의 스켈레톤으로 변환합니다 — 중간 JSON은 없습니다. 실제 음악적 변화 (hard_stops, SURGE / DROP key_moments, 롤의 가장자리, 온셋이 없는 구간, 큰 에너지 점프)에서 트랙을 프레임으로 자르고, 모든 경계를 오디오맵 앵커에 스냅합니다. 각 프레임에 대해 span_sec, pacing (1단계 신뢰 호출의 결과 — 그리드가 실제일 때 beat_cut, 잔잔한 음악에 부과된 메트로놈일 때 phrase_flow), mood, 및 한 줄 feel (3단계가 템플릿과 매칭할 음악 상황)을 설정합니다. 여기서는 분류하고 배치만 합니다. 모든 프레임의 ### Groups는 TBD (Step 3)으로 남겨두고 프론트매터 style은 비워둡니다 — 템플릿, 카피, 색상, 글꼴이 없음. 예상 약 1–6개 프레임.
게이트: 프레임이 트랙을 타일링함 (첫 번째는 0, 마지막은 duration_s). 각 프레임은 span_sec + pacing + mood + feel을 가지고 있음. 모든 ### Groups는 TBD임. 내용이 전혀 없음.
Step 3: 계획 채우기 (사용자 게이트)
목표: 스켈레톤을 승인된 완전한 STORYBOARD.md로 전환합니다.
references/planning.md, storyboard-format.md, template-catalog.md, motion-primitive-catalog.md, 및 montage.md (사용자가 자산을 제공한 경우에만)를 읽습니다. 동일한 파일을 제자리에서 편집하여 두 가지 작업을 수행합니다:
- 브랜드를 선택합니다.
../hyperframes-creative/frame-presets/에서../hyperframes-creative/references/design-spec.md의 테이블을 사용하여 하나의 프리셋을 선택합니다 (트랙의 분위기와 일치시킴; 글꼴과 색상만 중요함 — 템플릿이 컴포지션을 소유함).frame.md에 수정 없이 복사하고 프론트매터style(글꼴 + 최대 4-6개 견본 팔레트)을 채웁니다. - 모든 프레임을 채웁니다. 그룹을 결정하고 각 그룹에 처리를 부여합니다: 카탈로그에서 일치하는 템플릿 (바인딩된 매개변수와 실제 오디오맵 앵커 포함), 프리미티브 카탈로그의 자유 구성, 또는
pacing에 따라야 하는 자산 처리. 카피를 작성합니다. 당신은 WHAT (템플릿 / 프리미티브 + 내용 + 앵커)을 소유합니다. frame-worker는 HOW를 소유합니다 — 스토리보드에 밀리초 트윈을 작성하지 마십시오.
node <SKILL_DIR>/scripts/validate-plan.mjs --storyboard "$PROJECT_DIR/STORYBOARD.md" \
--audiomap "$PROJECT_DIR/audiomap.json" --templates <SKILL_DIR>/references/templates
모든 ✗ (심각한 오류: 지속 시간 불일치, 프레임이 트랙을 타일링하지 않음, src 누락)를 수정합니다. 경고는 최선의 노력으로 처리합니다. 그런 다음 사용자에게 프레임별 요약을 보여주고 승인할 때까지 반복합니다. 자율 모드에서는 이것이 체크포인트 게이트입니다: 요약을 알림으로 게시하고 진행합니다 (validate-plan.mjs 통과는 품질 게이트이며 여전히 차단함).
게이트: frame.md는 있는 그대로의 프리셋 사본임. validate-plan.mjs가 0으로 종료됨. 사용자가 계획을 승인함 (자율 모드: 요약이 알림으로 게시됨).
Step 4: 계획에서 프레임 빌드
목표: 각 프레임을 독립적인 컴포지션 파일로 빌드합니다.
compositions/frames/를 생성합니다. sub-agents/frame-worker.md 및 ../hyperframes-core/references/subagent-dispatch.md를 읽습니다. 프레임당 하나의 frame-worker를 가능하면 병렬로 (그렇지 않으면 웨이브로) 파견합니다. 각 작업자는 정확히 하나의 프레임과 이 컨텍스트를 받습니다:
PROJECT_DIR: <abs path>
frame_id: <NN-frame_id> # = 프레임 파일 스템, 예: 02-f2; 컴포지션 ID
Your block: `## Frame N — <frame_id>` 블록 in PROJECT_DIR/STORYBOARD.md
audiomap: PROJECT_DIR/audiomap.json
frame.md: PROJECT_DIR/frame.md
Materials: for each group, <SKILL_DIR>/references/templates/<id>/index.html (템플릿) and
<SKILL_DIR>/references/motion-primitives/<id>/ (자유 구성); staged assets/ (자산 그룹)
Contracts: ../hyperframes-core/references/sub-compositions.md + determinism-rules.md
Canvas: <w>×<h> Pacing: <beat_cut|phrase_flow>
Write to: PROJECT_DIR/compositions/frames/<frame_id>.html
작업자는 인용된 자료를 포크하고, 모든 앵커를 프레임 로컬 초로 변환하고 (local_t = track_t − span_sec[0]), 그룹을 0ms 컷으로 게이트하고, 하나의 시크 안전 프레임 파일을 작성합니다. 작업자는 hyperframes CLI를 절대 실행하지 않습니다 — 해당 명령어는 조립된 프로젝트에서 작동하며, 아직 존재하지 않으므로 잘못된 파일에 대해 보고합니다. 작업자는 계약에 따라 쓰기만 하고 중지합니다. 조립 후 (6단계) 확인합니다. 각 작업자가 반환되면 파일이 디스크에 기록되었는지 확인할 수 있습니다.
게이트: 모든 프레임에 대한 compositions/frames/NN-*.html이 디스크에 존재함.
Step 5: 조립
목표: 빌드된 프레임 + BGM을 재생 가능한 index.html에 연결합니다.
assemble-index.mjs는 결정적입니다 — 서브 에이전트도, 판단도 없습니다. 각 프레임 파일을 누적 data-start에서 참조하고, assets/bgm.mp3를 트랙 11에 마운트하고, 프레임 간을 하드 컷합니다 (프레임이 트랙을 타일링하고 간격이 없으므로 전환 인젝터가 없습니다).
node <SKILL_DIR>/scripts/assemble-index.mjs --storyboard "$PROJECT_DIR/STORYBOARD.md" \
--hyperframes "$PROJECT_DIR" --audiomap "$PROJECT_DIR/audiomap.json"
보고된 ✗를 수정합니다 — 프레임 파일이 없거나 비어 있다면 해당 작업자가 부분 파일을 작성한 것입니다. 다시 파견하고 (Step 4) 다시 조립합니다.
게이트: index.html이 존재함. 총 지속 시간 == audiomap.audio.duration_sec.
Step 6: 확인 및 렌더링
목표: 조립된 비디오를 확인하고, 사용자 승인을 받고, 최종 MP4를 렌더링합니다.
조립된 프로젝트에서 CLI를 실행합니다 — 이것이 올바른 단위입니다 (프레임별 작업자는 실행할 수 없었음). check는 구조적 린트와 헤드리스 브라우저 런타임, 레이아웃, 모션, 대비 게이트를 한 번에 실행합니다. --snapshots는 리뷰 프레임도 내보냅니다.
( cd "$PROJECT_DIR" && npx hyperframes check . --snapshots )
t=0, 각 프레임 시작, 가장 강한 DROP / SURGE, 모든 hard_stops[].t, 및 마지막 프레임에서 검사합니다. 실패 시 가장 저렴한 안전한 수정을 직접 수행합니다: 문제가 있는 compositions/frames/NN-*.html을 편집합니다. 동기화 문제를 숨기기 위해 지속 시간이나 오디오 타이밍을 변경하지 마십시오. 게이트를 통과하면 사용자 리뷰를 위해 일시 중지한 다음 승인 시에만 렌더링합니다 (자율 모드: 하나의 유지된 질문 — "미리보기 먼저, 또는 렌더링?" —을 묻고 연락처 시트와 함께 MP4를 전달):
( cd "$PROJECT_DIR" && npx hyperframes render . --skill=music-to-video -q draft -o renders/video.mp4 --fps 30 )
게이트: check 통과 및 스냅샷 검사 완료. 사용자가 승인함 (자율 모드: 검사 통과 및 연락처 시트 포함 전달). renders/video.mp4가 오디오와 함께 존재하며 지속 시간이 audiomap.audio.duration_sec과 일치함. 최종 응답은 MP4 경로와 지속 시간을 명시합니다.
재개 테이블
| 상황 | 재개 위치 |
|---|---|
BRIEF.md 없음, 프로젝트 없음, 명령 없음 | Step 0: intent-interview + init |
BRIEF.md 있음, hyperframes.json 없음 | Step 0: init (이미 읽은 BRIEF.md 건너뜀) |
hyperframes.json 있음, audiomap.json 없음 | Step 1 |
audiomap.json 있음, STORYBOARD.md 없음 | Step 2 |
STORYBOARD.md 있음 (그룹이 TBD) | Step 3 |
STORYBOARD.md 완전, 일부 compositions/frames/NN-*.html 누락 | Step 4 (누락된 프레임 다시 파견) |
모든 compositions/frames/NN-*.html 있음, index.html 없음 | Step 5 |
index.html 있음, renders/video.mp4 없음 | Step 6 |
| 모든 파일 존재, 의도하지 않음 | 재개 허용 안 됨 (의도가 필요함) |