데모 비디오은(는) 무엇을 하나요?
실제 애플리케이션(모의 또는 오래된 비디오가 아님)을 신규 헤드리스 브라우저에서 녹화하고, Edge TTS로 내레이션을 추가하며, 자막을 입히고 MP4로 렌더링합니다. 데모는 해당 프로세스를 위한 narration.json과 flow.cjs 두 파일로 구성됩니다. 나머지 모든 것은 이 폴더에 있는 demo-video-kit 명령어가 처리합니다. 실제 예제는 examples/todomvc/에 있습니다.
<kit>은 node <this folder>/bin/demo-video-kit.js를 의미합니다(이 폴더는 예를 들어 ~/.claude/skills/demo-video). 사용자 프로젝트에 키트가 설치된 경우 npx demo-video-kit도 동일하게 작동합니다. <kit> help는 모든 명령어를 나열합니다.
요청에 따른 작업 결정
| 요청 | 작업 |
|---|---|
| "<프로세스>에 대한 데모 생성" | 사용자 프로젝트의 demos/<process>/에서 아래 전체 워크플로 실행 |
| "<프로세스> 화면이 변경됨, 데모 재실행" | 새 화면을 드라이런(2단계)하고, flow.cjs를 수정하고, 단어가 더 이상 맞지 않으면 narration.json도 수정한 후, 4~8단계 실행 |
| "기존 <프로세스> 비디오에 상자 추가" (새 녹화 없음) | 실행 중인 앱에서 상자 측정, annotations.json 작성, <kit> annotate <demo-dir> 실행 (하이라이트 참조) |
| "... 하이라이트 없이" | 모든 highlight 옵션 제외; 나머지는 동일 |
| "음성 / 속도 / 문구 변경" | narration.json(voice, rate, 세그먼트 text) 편집 후 4~8단계 실행: 클립 길이가 화면 타이밍을 결정하므로 항상 비디오를 다시 녹화함 |
규칙 (항상)
- 실제 데이터와 신규 세션. 새로운 브라우저 세션; 실제 애플리케이션; 실제 데이터. 결과, 숫자 또는 상태를 절대 가짜로 만들지 않음; 애플리케이션이 표시한 후에만 성공을 알림.
- 안전. 로컬 또는 테스트 환경만: 실행할 때마다 실제로 워크플로가 생성하는 것을 실제로 생성함. 자격 증명을 인쇄하거나 저장하지 않음: 환경 변수(예:
DEMO_EMAIL,DEMO_PASSWORD)에서 가져오며, 비밀번호는 점으로만 표시됨. 알려진 테스트 계정이 없으면 요청할 것. - 화면. 1920x1080, 16:9, 30fps, H.264 + AAC MP4, 헤드리스로 녹화하여 아무것도 잘리지 않음. 각 대상으로 부드럽게 이동하는 보이는 커서와 가벼운 클릭 링; 확대/축소, 카메라 이동, 화려한 전환 효과 없음. 어떤 작업을 하기 전에 요소를 완전히 보이도록 스크롤; 긴 페이지는 읽을 수 있을 정도로 천천히 위에서 아래로 읽음.
- 소리. Edge TTS, 기본 음성
en-IN-NeerjaNeural(다른 음성은<kit> voices en-또는 다른 필터로 확인). 내레이션 세그먼트당 하나의 클립; 클립은 절대 겹치지 않음; 내레이션은 해당 장면에서 화면에 보이거나 곧 일어날 일만 설명함. - 7초 이상의 간격 없음. 내레이션이 없는 구간이 7초에 도달해서는 안 됨. 레코더가 경고하거나
verify.py가 실패하면 해당 세그먼트의 내레이션을 늘리거나 분할하고, 또는 해당 작업 속도를 높인 후 다시 녹화. - 속도. 서두르지 않음: 입력된 모든 값이 다음으로 넘어가기 전에 화면에 보여야 함.
- 애플리케이션 따르기. 경로, 레이블 및 버튼은 (드라이런에서) 실행 중인 앱에서 파생하며, 절대 기억에서 유추하지 않음. 버튼 이름은 앱이 지정한 대로 사용.
- 출력물은 Git에 추가하지 않음. 생성된 오디오, 빌드 및 MP4는 요청되지 않는 한 커밋하지 않음.
- 하이라이트. 모든 데모는 요청에 "하이라이트 없이"라고 명시되지 않는 한 내레이션이 가리키는 대상을 빨간색 상자로 표시함.
하이라이트
빨간색 상자(4px, #E11D48, 요소로부터 6px 여백)는 비디오 녹화 중에 페이지에 실시간으로 그려지므로 스크롤을 따라가며 화면의 일부가 됩니다. 기본 상자: 화면으로 이동하는 경로에서 클릭된 각 메뉴 항목, 프로세스를 시작하는 버튼, 검토 페이지에서 입력된 각 데이터 블록, 최종 제출 버튼. 입력 중인 모든 필드에 상자를 표시하지 않음: 커서와 타이핑으로 이미 표시되기 때문입니다.
flow.cjs의 API:
goto / click / type / pick (loc, ..., { highlight }):highlight: true는 커서가 이동하는 요소에 상자를 표시함;highlight: <locator>는 대신 다른 요소(예: 전체 행 또는 블록)에 상자를 표시함.- 상자는 커서가 다음 대상으로 이동할 때까지 유지됨.
{ keep: true }는 현재 상자도 유지함;k.clearHighlights()는 상자를 제거함;k.highlight(loc)는 커서를 이동하지 않고 상자를 추가함. - 각 상자는
build/timeline-raw.json의marks에highlight항목을 추가함.
이미 녹화되었지만 상자가 없는 비디오의 경우, <kit> annotate <demo-dir> 명령어로 annotations.json을 기반으로 나중에 상자를 그릴 수 있습니다. 이는 대체 방법이며, 다시 녹화하는 것이 더 쉽고 정확합니다.
워크플로
- 설정.
<kit> doctor실행(설정 참조)하고 앱이 해당 URL에서 응답하는지 확인. - 드라이런. Playwright 브라우저 도구를 사용하여 녹화 없이 실제 워크플로를 따라가고 최종 제출은 하지 않음: 각 화면의 경로, 레이블 및
getByRole이름, 드롭다운 옵션, 대화 상자, 최종 버튼 및 그 이후의 동작을 기록. - 데모 작성:
<kit> init <demo-dir> --url <app url>명령어로 이미 실행 가능한 스타터를 만들거나,examples/todomvc/를 복사. 그런 다음 편집:narration.json: 제목, 음성, 속도,pronounce(쓰여진 대로 → 말하는 대로), 및 세그먼트{id, scene, text}. 장면의 작업이 오래 걸리는 경우 여러 세그먼트로 분할하여 각 세그먼트의 내레이션 길이가 해당 작업 시간과 비슷하도록 함.flow.cjs:runDemo(__dirname, async (k) => { ... })형태로, 각 내레이션 세그먼트당 하나의k.segment(id, async (at, clip) => { ... })를 포함.k.click / k.type / k.pick / k.goto / k.scrollBy사용;at(seconds)는 클립의 특정 시점을 기다림(예:clip.cues[0].end). 요소를 기다리되 'network idle'은 기다리지 않음. 검증된 내용을 반환.require(process.env.DEMO_KIT || 'demo-video-kit')유지: 명령어가DEMO_KIT을 설정함.
- 생성하기.
<kit> run <demo-dir>(환경에DEMO_BASE_URL및 자격 증명 포함)은 오디오, 녹화, 렌더링 및 검증을 순차적으로 실행. 레코더의 각WARNING라인과 검증기의 각FAIL라인은 규칙 5를 위반한 것이므로 수정 후 다시 실행.flow.cjs만 변경한 경우--from record로 오디오 생략; 자막 또는 인코딩만 변경한 경우--from render로 녹화 생략. - 확인하기.
build/check/contact-sheet.png: 모든 프레임이 전체 화면, 커서, 올바른 단계, 읽을 수 있는 자막, 그리고 내레이션이 언급하는 요소의 상자를 보여줌. 비디오는<demo-dir>/<folder name>.mp4에 위치. - 전달하기. MP4 경로, 길이, 형식, 가장 긴 간격, 실행으로 생성된 내용, 그리고 앱이 다르게 작동하여 요청과 다른 점을 보고.
설정
Node 18+ 및 Google Chrome (또는 Microsoft Edge: 레코더가 대체로 사용하거나 DEMO_BROWSER=msedge 설정). 이 폴더에서 npm install을 한 번 실행; 음성(msedge-tts), ffmpeg(ffmpeg-static) 및 playwright-core가 함께 설치되며, 레코더는 첫 실행 시 Playwright 자체 작은 ffmpeg를 가져옴. <kit> doctor는 모든 것을 확인하며, 음성에 필요한 인터넷 액세스도 확인.
알려진 함정
| 함정 | 해결 방법 |
|---|---|
| 회색 띠, 페이지 하단 잘림 | 보이는 브라우저 창에서 절대 녹화하지 않음; demo-kit.cjs는 1920x1080 헤드리스로 녹화 |
waitForLoadState('networkidle')가 폴링하는 앱에서 중단됨 | 대신 요소를 기다림 |
| 헤드리스 UI 대화 상자가 숨겨진 것으로 보고됨 | 대화 상자 자체 대신 내부의 필드를 기다림 |
| 드롭다운 내에서 Escape 누르면 전체 대화 상자가 닫힘 | Escape 대신 옵션 선택 |
| 여러 필드를 입력하는 동안 무음 구간 발생 | 해당 세그먼트의 내레이션 분할; type()은 { delay } 옵션 사용(기본값 32ms) |
| CSS로 대문자로 표시된 레이블 | 표시된 대소문자가 아닌 실제 텍스트와 일치시킴 |
| 레이블만 상자로 감싸고 블록 전체를 감싸지 않음 | 레이블의 부모(xpath=..) 또는 조부모(xpath=../..)에 상자 표시 |