Communitygithub.com

피치 덱 실앱 데모 영상

Playwright로 실제 앱을 구동하고, 측정된 나레이션·요소 박스로 1–2분 제품 데모를 Remotion으로 생성합니다. 자막·카드·음악 포함. UI 변경 후 약 2분 재컷. README에 완성 데모 영상.

피치 덱 실앱 데모 영상란 무엇인가요?

Launch Video 1단계: 실앱 Playwright 녹화 → 나레이션 동기 Remotion 편집.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add RoderickQiu/pitch-deck-video-skill

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

/pitch-deck-video

실행 중인 로컬 웹 앱에서 나레이션이 포함된 제품 데모 비디오를 생성합니다. 편집은 파생되며, 수동 타이밍이 전혀 없습니다. 따라서 프론트엔드가 변경되면 다시 녹화하기만 하면 컷이 자동으로 따라옵니다 — 프레임 번호를 수정할 필요가 없습니다.

실제 발생하는 상황, 즉 UI가 계속 움직이는 동안 비디오가 필요한 경우를 위해 제작되었습니다.

사용법

/pitch-deck-video                          # 현재 디렉토리의 앱을 촬영합니다
/pitch-deck-video <path-to-app>            # 특정 앱을 촬영합니다
/pitch-deck-video --rebuild                # 기존 비디오 프로젝트를 다시 녹화하고 재편집합니다
/pitch-deck-video --script                 # 나레이션만 변경되었습니다; 마지막 테이크를 재사용합니다
/pitch-deck-video --render                 # 카드/캡션만 변경되었습니다; 다시 렌더링합니다

구조

네 개의 생성된 파일이 모든 것을 제어합니다. 첫 번째 파일만 사람이 작성합니다.

파일내용작성 주체
shots.json말할 내용, 음성, 음악, 테마, 브라우저 동작사용자
src/vo-durations.json각 대사가 실제로 소요되는 시간scripts/tts.mjs
capture/marks.json각 샷이 테이크에서 시작된 시간과 찾아야 할 위치scripts/record.mjs
src/frames.json테이크에서 생성된 프레임 수scripts/frames.mjs

src/timeline.ts는 이 파일들로부터 전체 편집을 도출합니다. 장면 길이는 측정된 나레이션 오디오를 기반으로 합니다. 푸티지는 이에 맞춰 늘어납니다. 카메라 움직임은 녹화 중 실시간으로 측정된 요소 경계 상자에서 비롯되므로, 이동된 버튼은 샷을 깨뜨리는 대신 샷을 이동시킵니다.

워크플로우

1 · 스캐폴딩

이 스킬의 template/을 앱 옆에 <app-name>-video/로 복사한 후 npm install을 실행합니다. 템플릿에는 시드 JSON이 포함되어 있어 첫 녹화 전에도 타입 검사와 렌더링이 가능합니다.

하나의 프로젝트를 위해 ~/.claude/skills/pitch-deck-video/template/ 아래의 파일을 절대 편집하지 마세요 — 이것은 공유 템플릿입니다. 복사본을 편집하세요.

2 · 먼저 저장된 로그인 정보 확인

앱에 인증이 필요한 경우, 저장소가 자체 e2e 테스트를 위해 이미 보관하고 있는 Playwright 저장 상태(.auth/*.json, storageState, playwright/.auth/)를 찾으세요. app.storageState를 해당 파일로 지정하면 카메라에 로그인 과정 없이 로그인된 상태로 녹화가 시작됩니다. 그러한 파일이 없을 경우에만 로그인 샷을 구축하세요 — 그리고 {"type": {"sel": "…", "env": "DEMO_PASSWORD"}}를 사용하여 비밀번호가 shots.json에 기록되지 않도록 하세요.

3 · 한 글자도 쓰기 전에 앱을 익히세요

앱의 개발 서버를 시작하고 모든 라우트를 1920×1080으로 스크린샷한 후 이미지를 읽으세요. 소스 코드에서 나레이션을 작성하지 마세요. 심사위원이 보게 될 내용에 대해 작성하는 것이며, 스크린샷만이 그것을 알려줍니다.

// 일회성 스크립트; Playwright는 템플릿과 함께 제공됩니다
for (const r of routes) {
  await p.goto(base + r, { waitUntil: 'networkidle' });
  await p.waitForTimeout(700);
  await p.screenshot({ path: `/tmp/shots/${r}.png` });
  console.log(r, await p.evaluate(() => document.documentElement.scrollHeight));
}

스크롤 높이를 기록하세요: 1080을 초과하는 모든 것은 scroll 액션이 필요하며, 그렇지 않으면 카메라에 절대 나타나지 않습니다.

4 · shots.json 작성

template/shots.example.json에서 시작하세요. 모든 필드와 액션은 references/shots-reference.md를 참조하세요.

theme.colors를 앱 자체 디자인 토큰에서 가져와 카드와 푸티지가 하나의 작품처럼 읽히도록 하세요. cards.arch.nodes를 실제 아키텍처(어느 박스가 모델 호출이고 어느 것이 결정적 코드인지)로 채우세요. 이 부분이 데모와 단순 래퍼를 구분짓는 요소이며, 심사위원들이 찾는 부분입니다.

중요한 나레이션 규칙:

  • 12–16 비트, 총 1:30–1:50. 2:00 제한 아래에서 10초의 여유를 남겨두세요.
  • 비트당 하나의 아이디어. 아이디어가 끝나면 비트도 끝납니다.
  • 숫자를 말하세요. "6명이 점수를 받았고, Priya가 승리합니다"가 "누군가를 선택합니다"보다 낫습니다.
  • UI를 나레이션하지 마세요. "여기서 승인을 클릭합니다"가 아니라 그것이 의미하는 바를 말하세요.
  • 제품 이름이 나오기 전에 사용자의 언어로 문제를 제시하세요.
  • 화면에 남기고 싶은 한 문장으로 마무리하세요.

5 · 빌드

APP_DIR=/path/to/app npm run all

나레이션 → 녹화 → 프레임 → 렌더링. app.url을 서빙하는 것이 없으면 개발 서버를 시작하며, 앱 자체의 dev 스크립트를 읽어 해당 프레임워크가 포트를 어떻게 사용하는지 파악합니다. 특별한 것이 필요하면 app.devCommand를 설정하세요. 일반적인 전체 재빌드: 약 2분.

shots.json은 먼저 검증되므로, 중복된 id나 알 수 없는 액션은 2분 후에 혼란스러운 비디오를 생성하는 대신 2초 안에 실패합니다.

6 · 직접 보고 QA — 선택 사항이 아닙니다

npm run qa          # 샷당 하나의 스틸 이미지, 연속 시트로 쌓임
npm run qa 3        # 샷당 세 개, 전환을 확인하려는 경우

그런 다음 시트를 이미지로 읽으세요. 비디오를 스크러빙하는 것은 느리고 많은 것을 놓칠 수 있습니다; 연속 시트는 몇 초면 되고 정말 중요한 실패를 정확히 잡아냅니다.

확인 사항: capture/marks.json → warnings가 비어 있는지 (선택자를 찾을 수 없는 것은 충돌이 아닌 경고입니다 — 여전히 비디오가 생성되며, 무엇이 깨졌는지 목록이 제공됩니다). 그런 다음: 각 캡션이 그것을 뒷받침하는 프레임에 위치하는가? 빈 프레임이나 흰색 프레임은 없는가? 작은 텍스트가 읽을 수 있는가, 아니면 focus가 필요한가?

references/troubleshooting.md에는 이 파이프라인이 실제로 겪었던 모든 실패와 각각의 수정 방법이 있습니다. 처음부터 디버깅하기 전에 읽어보세요.

UI 변경 후 재편집

이것이 이 모든 것의 핵심입니다.

APP_DIR=/path/to/app npm run all

대부분의 변경 사항은 다른 것이 필요하지 않습니다 — 이동된 요소, 스타일이 변경된 페이지, 새로운 복사본. 여전히 판단이 필요한 것:

  • 페이지가 삭제되거나 이름이 변경됨 → 해당 샷을 다시 지정하거나 교체하세요.
  • 기능이 다시 작성됨 → 해당 비트의 나레이션은 더 이상 존재하지 않는 것에 대한 주장이 됩니다. 대사를 다시 작성하세요.
  • 선택자가 실제로 사라짐 → 경고 목록을 확인하고 거기서 수정하세요.

나레이션은 라인별로 캐시되므로, 편집된 라인만 다시 합성됩니다.

음성

음성은 완성된 비디오의 가장 큰 품질 차이이며, 기본값은 확실히 좋지 않습니다. 첫 번째 빌드 전에 미리 솔직하게 말하세요.

  • tts.provider: "minimax" — 좋습니다. 사용자에게 MiniMax 키가 어디에 있는지 물어보고 tts.envFile을 해당 파일로 지정하세요. 음성 ID는 MiniMax의 시스템 음성 목록에서 가져옵니다; 음성의 언어 태그는 제한이 아닌 힌트입니다(우크라이나어 태그가 붙은 음성은 languageBoost: "English"로 영어를 잘 읽습니다).
  • tts.provider: "say" — macOS의 내장 합성기이며, 레거시 음성만 일반적으로 설치되어 있습니다. 로봇 같고 제품 이름을 잘못 발음하며, 보는 사람이 누구나 알 수 있습니다. 타이밍 확인용으로는 사용 가능하지만, 심사위원이나 고객이 볼 것에는 약합니다.
  • 인간 녹음이 둘 다를 능가합니다. <id>.wav 파일을 public/vo/에 넣고 npm run script를 실행하면; 지속 시간이 다시 측정되고 전체 비디오가 다른 편집 없이 스스로 재타이밍됩니다.

키가 없으면 어쨌든 비디오를 빌드하세요 — 하지만 음성이 약한 부분이며, 키나 마이크로 10분이면 해결된다는 것을 사용자에게 미리 알리세요. 완성된 것처럼 say 음성 해설을 조용히 제공하지 마세요.

MiniMax는 API에 연결할 수 없는 경우 라인별로 say로 대체되므로, 실행이 완전히 실패하지는 않습니다.

API 키를 프로젝트에 복사하지 마세요. scripts/tts.mjs는 환경 변수 MINIMAX_API_KEY / MINIMAX_GROUP_ID를 읽거나, 그렇지 않으면 tts.envFile이 지정한 파일에서 구문 분석합니다. 사용자에게 키가 어디에 있는지 물어보고 envFile을 그곳으로 지정하세요.

인간 녹음은 어떤 합성기보다 뛰어납니다: <id>.wav 파일을 public/vo/에 넣고 npm run script를 실행하세요 — 파일을 다시 측정하고 전체 비디오를 재타이밍합니다.

음악

scripts/music.mjs는 music.url에 지정된 트랙을 yt-dlp로 가져와 현재 비디오 길이에 맞게 배경 음악을 자릅니다. 게시하기 전에 사용자에게 트랙의 라이선스를 확인하라고 알리세요 — 라이브러리 트랙은 일반적으로 설명에 출처 표시를 하면 무료이고, 그렇지 않으면 유료입니다. 제목과 URL은 public/music/SOURCE.txt에 저장되어 출처를 쉽게 복사할 수 있습니다.

하지 말아야 할 것

  • 타이밍을 수동으로 조정하지 마세요. 비트가 너무 빠르게 느껴진다면, 나레이션이 샷에 비해 너무 긴 것입니다 — 타임라인이 아닌 shots.json을 수정하세요.
  • <Sequence> 안에 <Screen />을 넣지 마세요. 설계상 절대 시간을 읽습니다; Sequence 내부의 useCurrentFrame()은 Sequence-로컬 프레임을 반환합니다. 이로 인해 이전에 비디오가 깨진 적이 있으며, 증상(푸티지가 음성과 미묘하게 동기화되지 않음)을 발견하기 어렵습니다.
  • 설정 시간이 카메라에 찍히도록 두지 마세요. 탐색, 데이터 로딩, 배너 닫기는 모두 샷의 캡처 창 내에서 발생하며 나레이션 아래로 늘어납니다. 설정 단계 후에 {"cut": true}를 넣으면; 푸티지가 그 지점부터 시작됩니다.
  • 스텁된 것은 촬영하지 마세요. 버튼이 "백엔드 연결"을 반환한다면, 그 샷을 제외하고 연결이 완료되면 추가해야 할 샷을 사용자에게 알리세요.
  • 경고 목록을 확인하지 않고 출시하지 마세요.
  • 실행 간에 변동하는 숫자를 나레이션하지 말고, 이 계정의 버전이 비어 있을 때 화면이 가득 찼다고 설명하지 마세요. 하나의 거짓 주장을 발견한 심사위원은 나머지도 신뢰하지 않게 됩니다.

관련 스킬