mkt-hyperframe-talking-head-video-16-9
전용 16:9 (1920×1080) 가로 편집기 — 입력은 voiceover.mp3 + source.mp4 + script.txt가 이미 있는 워크스페이스 폴더 1개이며, 출력은 동일 폴더가 npx hyperframes preview로 바로 미리보기 가능한 HyperFrames 프로젝트로 완전히 스캐폴딩된 것입니다.
이는 오케스트레이터 mkt-full-video-with-11-hyperframe-heygen-16-9 아래의 운영 레이어입니다. 오케스트레이터가 Phase 1(TTS) + Phase 2(HeyGen 아바타)를 처리한 후 폴더를 이 스킬에 넘겨 Phase 3(전사 + 스캐폴딩 + 린트 + 미리보기)을 수행합니다.
이 스킬이 생성하는 것
<workspace_folder>/
├── voiceover.mp3 # 입력 (변경 없음)
├── source.mp4 # 입력 (HeyGen 아바타 립싱크, 변경 없음)
├── script.txt # 입력 (변경 없음)
├── transcript.json # 생성됨 — 단어 수준 Whisper 출력
├── transcript-cleaned.json # 생성됨 — 베트남어 오타 정리
├── scenes-outline.json # 생성됨 — 사전 체크포인트 개요 (5개 장면)
├── scenes.json # 생성됨 — 최종 장면별 메타데이터
├── index.html # 생성됨 — 루트 컴포지션 1920×1080
├── compositions/
│ ├── scene-1.html # N에 관계없이 장면당 1개 파일
│ ├── scene-2.html # 병렬 LLM 하위 에이전트가 작성 (Phase 3d)
│ ├── scene-3.html # Python 템플릿으로 생성되지 않음 (더 이상 사용하지 않음)
│ ├── ...
│ └── scene-N.html
├── sfx/ # 스킬 에셋에서 6개 SFX 심볼릭 링크/복사
│ ├── camera-flash.mp3
│ ├── Whoosh sound effect (1).mp3
│ ├── búng tay.mp3
│ ├── Laser.mp3
│ ├── ting.mp3
│ └── Discord Notification - Sound Effect.mp3
└── (선택 사항) infographics/
├── 1.png 2.png 3.png # --with-infographics 사용 시
└── prompts.md # 장면별 크림 페이퍼 편집 프롬프트
캔버스:
- 루트:
data-width="1920" data-height="1080". - 아바타 프레임 기본 SPLIT:
top:100, left:1290, width:540, height:880, borderRadius:32. - 아바타 프레임 PIP 코너:
top:600, left:1540, width:320, height:420, borderRadius:20. - 슬라이드 마운트:
1200×1080SPLIT, PIP 중에1920×1080으로 애니메이션 가능. - 각 컴포지션의 고유 크기:
data-width="1200" data-height="1080"(마운트의 100%를 채우며, 마운트가 넓어지면 확장됨).
필요한 입력 (워크스페이스 폴더 규칙)
| 파일 | 필수 | 참고 |
|---|---|---|
voiceover.mp3 | 예 | ElevenLabs TTS 출력 (Hoàng 목소리). |
source.mp4 | 예 | HeyGen 아바타 립싱크. 현재 9:16 세로 — 가로 프레임은 object-fit: cover; object-position: center 25%를 사용하여 적절히 크롭. references/source-mp4-cropping.md 참조. |
script.txt | 예 | voiceover.mp3를 생성한 베트남어 스크립트. 오타 수정 및 장면 제목 도출에 사용됨. |
scenes-outline.json | 아니요 | 사용자가 5개 장면을 미리 정의한 경우 자동 감지를 건너뜀. 스키마: Step 3 참조. |
슬러그 = 워크스페이스 폴더의 기본 이름 (도출 불필요). 모든 스크립트는 해당 폴더 내에서 읽고 씁니다. 스크립트는 --workspace <path> 플래그를 허용하며 기본값은 CWD입니다.
파이프라인 (순차적 스크립트 호출)
voiceover.mp3 + source.mp4 + script.txt
│
▼
1. transcribe_audio.py ── Whisper VN → transcript.json (단어 수준)
│
▼
2. clean_transcript.py ── Whisper 아티팩트 제거, VN 사전 적용
│
▼
3. detect_scenes.py ── transcript + script.txt → scenes-outline.json (5개 장면)
│
▼
4. [선택 사항 CHECKPOINT] ── 사용자가 개요 검토 / kicker, heading 수정
│
▼
5. scaffold_project.py ── scenes.json (전체 스키마) 작성, sfx/ + logos/ + avatar.jpg + yt-lower-third.html 생성
│
▼
6. 🔥 LLM 하위 에이전트 FANOUT 🔥 ── 오케스트레이터가 단일 메시지에서 N개의 병렬 범용
에이전트(장면당 1개)를 생성하고, 각 에이전트는
visual-plan.json + references/composition-patterns.md를 참조하여
compositions/scene-{num}.html을 작성합니다.
NOT generate_compositions.py (Jinja2 생성기
DEPRECATED — 5개 아키타입으로 축소되어 장면별
메타포를 적용할 수 없고, 6개 이상의 장면이 있는 리스트클을 망가뜨림).
│
▼
7. generate_root_index.py ── 슬라이드 마운트(모든 장면에 대해 scene-{num}.html 마운트,
kind→fs-lesson 매핑 없음) + 아바타 프레임(claude-orange #d97757 브랜드 테두리) +
GSAP 타임라인(SPLIT↔PIP, 호흡, 펀치인, PIP_EVENTS, 하이브리드 훅 줌) +
6개 SFX 연결 + 루트의 크림 페이퍼 b-roll 이미지 레이어(전체 1920×1080)를 포함한 index.html 작성
│
▼
8. [선택 사항] scaffold_infographic_slots.py
── <img onerror> 플레이스홀더 추가 + prompts.md 작성
(장면 메타포별 크림 페이퍼 편집)
│
▼
9. lint_and_preview.py ── npx hyperframes lint → 오류 0개, 그런 다음 미리보기
│
▼
HAND-OFF — Studio URL 출력; 사용자 검토; 오케스트레이터가 렌더링 결정.
미리보기 우선 규칙(협상 불가): 스킬은 Step 9에서 Studio URL을 출력하며 종료됩니다. MP4 렌더링은 사용자가 명시적으로 확인한 후에만 실행됩니다 — 해당 단계는 오케스트레이터 또는 사용자 수동 작업에 속합니다.
Step 1: transcribe_audio.py
python3 scripts/transcribe_audio.py --workspace <folder>
로컬에 사용 가능한 경우 기존 스킬 mkt-ai-video-extract-srt-segment를 래핑하고, 그렇지 않으면 whisper CLI로 직접 폴백합니다:
whisper voiceover.mp3 --model medium --language vi --word_timestamps True \
--output_format json --output_dir .
베트남어 오디오에 --model medium.en을 절대 사용하지 마십시오 — .en은 받아쓰지 않고 번역합니다. 항상 --language vi를 사용하세요.
출력: transcript.json — {text, start, end} 단어 수준 항목의 배열.
Step 2: clean_transcript.py
형제 9:16 편집기(mkt-hyperframe-talking-head-video/scripts/clean_transcript.py)의 로직을 재사용합니다. U+FFFD를 제거하고, VN 단어 수준 및 구문 수준 사전(alphabit→Alphabet, Cod→Code 등)을 적용하고, 3-5개 단어 구문으로 그룹화합니다. 출력: transcript-cleaned.json. (16:9에서는 caption-groups.json 없음 — 자막이 꺼져 있음.)
Step 3: detect_scenes.py
transcript-cleaned.json + script.txt를 읽어 표준 지식 비디오 스켈레톤을 사용하여 5개 장면 경계를 추론합니다:
| # | 종류 | 기본 kicker 힌트 | 변형 |
|---|---|---|---|
| 1 | hook | 스크립트의 첫 번째 문장 | tier-row (kind=hook을 통한 포스트-스택 느낌) |
| 2 | problem | 스크립트가 "ChatGPT/AI cũ", "khó", "đứt mạch", "vấn đề"… 로 전환되는 지점 | chats-stack |
| 3 | solution | 스크립트가 도구/방법을 소개하는 지점 | hero-orb |
| 4 | recap | 스크립트가 숫자 결과("X tiếng", "Y khách hàng")를 표시하는 지점 | counter-row |
| 5 | cta | 댓글/저장/팔로우 트리거가 포함된 마지막 문장 | terminal-row |
스크립트에 명확한 5개 부분이 없으면 더 적게 출력(최소 3개)하고 사용자에게 경고합니다. 휴리스틱: 문장 경계로 전사를 대략 5개 청크로 분할하고 장면 3(해결책이 일반적으로 가장 김)에 1.5배 가중치를 부여합니다.
출력 scenes-outline.json:
[
{ "num": 1, "kind": "hook", "start": 0.07, "end": 13.73, "kicker": "...", "heading": "...", "variant": "tier-row" },
{ "num": 2, "kind": "problem", "start": 13.73, "end": 27.37, "kicker": "...", "heading": "...", "variant": "chats-stack" },
{ "num": 3, "kind": "solution", "start": 27.37, "end": 47.75, "kicker": "...", "heading": "...", "variant": "hero-orb" },
{ "num": 4, "kind": "recap", "start": 47.75, "end": 53.80, "kicker": "...", "heading": "...", "variant": "counter-row" },
{ "num": 5, "kind": "cta", "start": 53.80, "end": 60.68, "kicker": "...", "heading": "...", "variant": "terminal-row" }
]
CHECKPOINT — 검토를 위해 개요를 사용자에게 출력합니다. 사용자는 kicker/heading/variant를 인라인으로 편집한 후 계속할 수 있습니다. 스킬이 --auto(오케스트레이터 모드)로 호출된 경우 체크포인트를 건너뜁니다.
Step 4: scaffold_project.py
scenes-outline.json을 읽고 각 장면을 다음으로 보강합니다:
accent_words— heading에서 파생(숫자 + 마지막 2-3개 명사 추출)content— 패턴별 스키마(assets/templates/참조)badges— 장면당 1-3개의 떠다니는 배지brollEnd,hasBreath— SPLIT↔PIP 스케줄링용pip_events— 장면 내accent_words타이밍에서 파생
scenes.json을 작성합니다. 또한 스킬 번들에 포함된 assets/의 다음 자체 포함 에셋을 워크스페이스로 자동 복사합니다:
| 에셋 | 소스 | 대상 | 목적 |
|---|---|---|---|
| 6개 SFX 파일 | assets/sfx/ | <workspace>/sfx/ | 비트 사운드(camera-flash, whoosh, búng-tay, Laser, ting, Discord-notification) |
| 브랜드 로고 | assets/logos/{chatgpt,gemini,claude,claude-code}.{png,jpg} | <workspace>/assets/logos/ | 컴포지션에 자동 첨부(chats-stack 아바타, hero-orb, tier-row 도구 배지) |
| 아바타 | assets/avatar.jpg | <workspace>/assets/avatar.jpg | yt-lower-third 구독 배너용 채널 썸네일 |
| YT 하단 3분의 1 | assets/compositions/yt-lower-third.html | <workspace>/compositions/yt-lower-third.html | 구독 배너 마운트, 비디오의 마지막 3초 |
스킬 번들에 소스 에셋이 없으면 자동으로 레거시 워크스페이스 경로(workspace/assets/...)로 자동 폴백합니다. 둘 다 없으면 해당 에셋은 건너뛰어집니다(컴포지션이 정상적으로 저하됨 — 로고 대신 텍스트 아바타, 하단 3분의 1 없음).
Step 5: 🔥 LLM 하위 에이전트 FANOUT (컴포지션 작성) 🔥
generate_compositions.py는 더 이상 사용되지 않습니다. 호출하지 마십시오. Python Jinja2 생성기는 모든 장면을 5개의 고정 아키타입(hook → tier-row, problem → chats-stack, solution → hero-orb, recap → counter-row, cta → terminal-row) 중 하나로 축소하여 장면별 메타포(예: "scroll-tape-wasted", "two-clock-comparison", "right-tool-vehicles")를 적용할 수 없고, 6개 이상의 장면이 있는 리스트클을 망가뜨립니다(여러 tip-N이 동일한 파일 이름으로 축소되어 덮어쓰기됨).
표준 방법: 오케스트레이터(또는 사용자)가 단일 메시지에서 N개의 병렬 general-purpose 에이전트(장면당 1개)를 생성하여 동시에 실행합니다. 각 하위 에이전트는:
visual-plan.json(경로:<workspace>/visual-plan.json, 장면 인덱스num-1)에서 해당 장면 블록을 읽습니다.- 오케스트레이터 스킬의 참조를 읽습니다:
references/composition-patterns.md(8개의 프로덕션 출시 패턴),references/slide-design-tokens.md(팔레트 + 타이포그래피) - 장면 메타포에 맞는 올바른 패턴을 선택하여 자유롭게 적용합니다(hero-orb는 vault+spokes가 될 수 있고, stats-3card는 two-clock-comparison이 될 수 있음).
- 처음부터
compositions/scene-{num}.html을 작성합니다: 1200×1080 뷰포트,[data-composition-id="scene-{num}"]를 통한 범위 지정 CSS,window.__timelines["scene-{num}"]에 등록된 GSAP 타임라인,!important없음,image-slot없음(크림 페이퍼 이미지는 루트 레이어에만 있음).
결과: 각 장치는 고유하고 메타포에 맞는 컴포지션 파일을 얻습니다. 충돌 없음, 지루한 5-아키타입 고정 없음.
전체 하위 에이전트 프롬프트 템플릿은 오케스트레이터의 mkt-full-video-with-11-hyperframe-heygen-16-9/SKILL.md Step 4d를 참조하십시오.
컴포지션의 브랜드 로고 (하위 에이전트가 참조)
하위 에이전트는 패턴에 필요한 경우 브랜드 로고를 포함합니다. 로고는 <workspace>/assets/logos/에 있습니다:
| 패턴 사용 | 브랜드 요소 |
|---|---|
| Hook tier-row "after" | tool-badge 알약(오른쪽 상단) — Claude 로고 + 이름. |
| Problem chats-stack 실패 행 | ChatGPT/Gemini 로고는 name이 키워드(chatgpt/gpt → chatgpt.png; gemini/google → gemini.jpg)와 일치할 때 자동 첨부됨. |
| Solution hero-orb / vault | Brand logo inside the orb glow (기본 Claude). |
| CTA terminal-row | 기본적으로 로고 없음. |
하위 에이전트는 assets/logos/가 없으면 텍스트 아바타로 폴백합니다(깜빡임 없음).
패턴 참조 (8개 아키타입, 하위 에이전트가 선택 및 적용)
오케스트레이터의 references/composition-patterns.md는 8개의 프로덕션 테스트 패턴을 제공합니다:
| 패턴 | 최적 사용 | 내부 모티프 |
|---|---|---|
tier-row before-after | Hook 대비 | 2개의 티어 행(이전 rose/red + 이후 lime/green) + 문자 + 항목 |
chats-stack | Problem / 실패 / Edit-Regen 데모 | 사용자 행 + 2-3개 AI 실패 행 + 끊어진 체인 스탬프 |
hero-orb + spec-trio | Solution / 메커니즘 / 중앙 볼트 | 빛나는 구체 + 작업 아이콘 + 3개의 사양 티어 행 |
counter-row | Recap / 숫자 증명 | 큰 카운터(FROM → TO) + 클라이언트 + 델타 태그 |
comment-terminal | CTA / "comment X" | 티어 문자 + macOS 터미널 모형 + 2개의 기프트 카드 |
stats-3card | 지식 소개 / 3가지 사실 공개 | // LBL + 그래드 숫자가 있는 3열 랜딩 스타일 |
comparison-2col | "When to use which" | 2열 Yes/Yes 칩 |
image-slot | (DEPRECATED — 루트 레이어의 이미지) | — |
하위 에이전트는 자유롭게 적용합니다: 예: hero-orb → "vault + 5 chat spokes", stats-3card → "two-clock-comparison", comparison-2col → "3-tier vehicle cards". 패턴 문서는 골격(HTML + CSS + GSAP)을 제공하고, LLM이 창의적인 맞춤화를 수행합니다.
Step 6: generate_root_index.py
scenes.json + transcript의 total_duration을 읽고 assets/templates/index.html.j2를 렌더링합니다:
#slide-bg,#heygen-bg,#avatar-frame > .avatar-breathing > .avatar-punch > #v-source가 있는 1920×1080 루트<audio id="a-source">가 원본 source.mp4 오디오(트랙 1)를 추적함- 절대
data-start(장면 경계)가 있는 6개의<audio>SFX 연결 - 왼쪽 상단의 브랜드 마크
- GSAP 블록:
- 초기 진입(아바타 페이드인, 브랜드 페이드인)
- SPLIT/PIP 상수 +
goPIP(t)/goSplit(t)헬퍼 - scenes.json의 장면별
pip_events에 의해 구동되는PIP_EVENTS배열 - ".avatar-breathing"의 "Hybrid Hook" 시각적 줌 전략:
- HOOK 장면: 장면 지속 시간 동안 느린 램프 1.0 → 1.10(드라마 구축,
power2.in) - HOOK→BODY 전환: 스냅 리셋 1.10 → 1.0(긴장 완화, 0.5초
power3.in) - BODY 장면(2..N-1) PIP-IN 이벤트 시: 1.06 펀치 비트(리듬,
power2.out→power3.out) - CTA 장면: 부드러운 1.0 → 1.04 푸시(마무리,
sine.inOut)
- HOOK 장면: 장면 지속 시간 동안 느린 램프 1.0 → 1.10(드라마 구축,
- 장면별 시작 시
.avatar-punch의 작은 펀치(1.06) for transition be