자동화된 데모 비디오 녹화 (Playwright)
모드 (먼저 결정)
수신된 인수: $ARGUMENTS
| 인수 | 모드 | 템플릿 |
|---|---|---|
audio 포함 (또는 요청에 음성 / 음성 내레이션 / 음성 해설이 있는 경우) | 내레이션 — TTS 음성 + 자막 | record-demo-narrated-template.mjs + narrate.py |
| 비어 있음 / 그 외 | 무음 — 자막만 (기본값) | record-demo-template.mjs |
내레이션 모드: 언어 en (기본값) 또는 pt (브라질 포르투갈어); 엔진 auto (기본값: 영어 → kokoro 오프라인; 포르투갈어 → edge, 오프라인 시 kokoro로 폴백), 또는 kokoro / edge 강제 지정. 예: audio, audio pt, audio pt kokoro, audio en edge. 아래 내레이션 모드도 따르세요.
선택한 언어로 자막과 내레이션을 작성하세요 (pt가 주어지거나 사용자가 포르투갈어로 작성하지 않는 한 en).
개요
데모 비디오는 코드이지, 수동 캡처가 아닙니다: Playwright 스크립트가 기본 녹화, 오버레이 자막 및 시각적 하이라이트로 브라우저를 구동합니다. 제품이 변경될 때마다 (npm run demo:record) 재녹화 가능하며, 통제된 페이스와 스토리를 갖춥니다.
핵심 원칙: 비디오는 피치(pitch)이지, E2E 테스트가 아닙니다. 모든 장면은 하나의 주장을 증명하기 위해 존재하며 — 생성된 비디오를 프레임 단위로 직접 검증(VERIFY)한 후에야 작업이 완료된 것입니다.
사용 시기 / 사용하지 말아야 할 때
- ✅ 웹 제품 POC/데모 (투자자, 고객, 이해관계자, 온보딩용)
- ✅ 계속 진화하는 엔드투엔드 플로우 문서화 (재녹화 가능)
- ✅ 음성 포함: 내레이션 모드 (로컬/오프라인 TTS) — 위 참조
- ❌ 자동화된 테스트 (Playwright Test 사용) · ❌ 비웹 앱 · ❌ 앱 자체 사운드 캡처 (Playwright는 브라우저 오디오를 녹음하지 않음)
프로세스
- 먼저 결정론적 상태를 확보하세요. 비디오는 실제 작업(로그인, 클릭, DB 쓰기)을 수행합니다. 녹화 전에 멱등성(idempotent) 시드/데모 데이터와 전용 계정을 준비하세요. 서버를 프로덕션 모드(
build && start)로 실행하거나 개발 모드에서 라우트를 웜업하세요 — 지연 컴파일은 비디오에서 흰 화면으로 나타납니다. - 코딩 전에 스크립트를 먼저 작성하세요. 4막 피치 구조: 비전 (오프닝) → 작동 방식 (차별점, 내부) → 최종 사용자 경험 → 증거/결과 (비전으로 마무리). 각 장면 = 1개 주장 + 1개 자막 (강력한 헤드라인 + 설명적 부제목). 목표: 총 60
120초, 주요 화면당 35초. - 템플릿을 수정하세요 — 자막, 하이라이트, 로그인, 페이스 조절 및 변환을 위한 즉시 사용 가능한 도우미가 포함되어 있습니다. 프로젝트의 브랜드 색상을 자막에 사용하세요.
- 녹화하고, 선택자 실패는 깨진 스크립트로 간주하여 해결하세요 (우회하지 말고 수정).
- 비디오 검증(VERIFY) — 필수. 지속 시간 및 장면:
프레임을 검사한 후에만 전달하세요. 장면이 실패하면 다시 녹화하세요.ffprobe -v error -show_entries format=duration -of csv=p=0 demo.mp4 # 장면당 1프레임을 캡처하여 각각 확인 (올바른 자막? 올바른 화면? 깨진 부분 없음?) ffmpeg -y -ss <t> -i demo.mp4 -frames:v 1 -vf scale=800:-1 frame_<t>.png .mp4를 전달하세요 (PowerPoint/Slack/WhatsApp에서 작동)..webm도 함께 제공하세요. npm 스크립트(demo:record)를 남기고 출력물은 gitignore하세요 (재생성 가능).
내레이션 모드 (audio)
위와 동일한 프로세스이며, 다음 차이점이 있습니다:
- 전제 조건: PATH에
uv와ffmpeg가 있어야 합니다 (uv --version,ffmpeg -version).narrate.py를 녹화 스크립트와 동일한 폴더에 복사하세요. 첫 실행 시 Kokoro 모델(~120 MB,~/.cache/recording-demo-videos에 캐시)을 다운로드합니다. - 페이스는 오디오에서 결정됩니다.
SCRIPT의 각 장면에는caption(화면) +say(음성, 1~2문장, 피치 톤)이 있습니다.await narrate(page, "id")는 자막을 표시하고 음성을 배치하며 종료될 때까지 기다립니다 — 음성 장면에 고정된pause()를 사용하지 마세요. 상호작용 중 음성:narrate(page, id, { wait: false }); 다음narrate()는 이전 음성이 끝날 때까지 기다립니다 (겹치지 않음). - 언어/음성은 env를 통해 설정:
DEMO_LANG=en|pt,DEMO_TTS=auto|kokoro|edge,DEMO_VOICE=<voice>(Kokoro:af_heart,am_michael,bf_emma,pf_dora,pm_alex; edge:en-US-AvaMultilingualNeural,pt-BR-FranciscaNeural...).kokoro= 오프라인, Apache-2.0, 영어 기본값; 포르투갈어는 눈에 띄게 덜 자연스럽습니다.edge= 포르투갈어 기본값, 최고의 음성, 하지만 비공식 Microsoft 엔드포인트를 통한 온라인 — 내부 데모에는 적합; 상업용으로는kokoro또는 공식 TTS를 선호하세요. - 동기화는 자동입니다: 템플릿은 마젠타 플래시(
syncMarker)로 시작하여 실제 비디오 시작 지연을 측정하고 플래시를 잘라냅니다.syncMarker를 첫 번째 동작으로 유지하세요; 로그에 "Sync marker not found"가 표시되면 음성이 동기화되지 않습니다 —syncMarker가 첫 번째 동작이고 첫 1초 동안 아무것도 화면을 가리지 않는지 확인한 후 다시 녹화하세요. - 출력:
demo.mp4(내레이션 — 최종 전달물),demo.srt,timeline.json,demo.raw.webm(원시, 무음),audio/(캐시: 변경된 줄만 다시 합성하여 재녹화). - 추가 검증 (필수): 프레임 외에도 음성이 올바른 위치에 있는지 확인하세요:
ffprobe -v error -show_entries stream=codec_type,duration -of csv=p=0 demo.mp4 # 비디오와 오디오가 모두 있어야 함 ffmpeg -i demo.mp4 -af silencedetect=n=-45dB:d=0.6 -f null - 2>&1 | grep silence_end # 각 silence_end ≈ timeline.json의 장면 atVideo (±0.2초); 해당 시간의 프레임을 캡처하여 자막 확인
함정 (어렵게 배운 교훈)
| 함정 | 해결책 |
|---|---|
| 비디오 파일명이 랜덤함 | page.video()를 닫기 전에 가져오고; context.close() 후 await video.path(); 이름 변경 |
| 탐색 시 자막 사라짐 | 모든 goto 후 자막 재주입 (caption() 도우미), 또는 addInitScript + sessionStorage 사용 |
| 비디오가 사람에게 너무 빠름 | slowMo: 100~150 + 장면당 명시적 3~5초 일시 정지 + 가시적 타이핑에 pressSequentially({ delay: 40~60 }) 사용 |
| mp4가 PowerPoint/플레이어에서 열리지 않음 | ffmpeg -c:v libx264 -pix_fmt yuv420p |
| 비디오가 작거나 잘림 | recordVideo.size가 viewport와 일치해야 함 |
| 비디오에 흰색/대기 화면 | waitUntil: "networkidle" + 작업 후 waitForURL; 개발 모드에서 라우트 웜업 |
| 시청자가 어디를 봐야 할지 모름 | 클릭 전 요소에 호박색 하이라이트(box-shadow) 또는 주입된 가짜 커서 |
| 재녹화 시 데이터 중복 | 멱등성 작업 또는 재실행을 허용하는 시드 (접미사 slug, upsert) |
| 사용자 전환 간 로그인 정보 누출 | context.clearCookies() 사용 |
| (내레이션) 음성이 화면과 동기화되지 않음 | Playwright 비디오는 페이지 시작 후 0.2~1.5초 후에 시작됨 (실행/버전마다 다름) — 템플릿의 syncMarker 사용, 절대 고정 오프셋 사용 금지 |
| (내레이션) 음성 잘림 또는 장면이 급하게 진행됨 | 음성 장면에 고정된 pause() 사용 — 대신 narrate()로 대체, 음성 종료 대기 |
| (내레이션) 약어/브랜드 발음 오류 | say에서 음성적으로 철자 (예: "S Q L" 또는 "sequel"); 자막은 올바르게 유지 |
흔한 실수
- 프레임 검증 생략 ("에러 없이 실행됨" ≠ "비디오가 괜찮음") — 항상 확인하세요.
- UI를 설명하는 자막 ("로그인 화면") 대신 주장을 서술하는 자막 ("팀이 로그인합니다 — 세분화된 역할 제어").
- 작성된 스크립트 없이 녹화: 스토리 없는 긴 화면 녹화가 생성됩니다.
- 실제 자격 증명을 하드코딩 — 데모/시드 계정 사용, 민감한 경우 env를 통해 주입.