B 비디오은(는) 무엇을 하나요?
추가 트리거
PR 비디오 둘러보기, 데모 녹화 만들기, 음성 해설 데모, 두 스택 녹화, 설명 비디오, drawtext 필터 없음, Playwright recordVideo, 헤드리스 셸 없음
주장 집합당 하나의 mp4: 제목 카드, A 클립, B 클립, 증거 카드, 판정 카드, 각각 음성 처리됨.
Apple Silicon을 탑재한 macOS용으로 제작됨 (say, ~/Library/Caches/ms-playwright 아래 Playwright 캐시, chrome-mac-arm64). 다른 환경에서는 CHROMIUM_EXE를 설정하고 --eleven을 사용하세요. Bun, ffmpeg 및 Python 3이 필요합니다.
실행 방법
S=${SKILL_DIR:-~/.claude/skills/narrated-ab-video}
$S/preflight.sh /tmp/vid # chromium, playwright ffmpeg, ffmpeg, say 음성
bun $S/record.ts a.json raw/a-run # 측당 하나의 시나리오 (examples/scenario.json 복사)
bun $S/record.ts b.json raw/b-run
bun $S/cards.ts cards.json cards # 제목/증거/판정 PNG + banner-A/B.png
python3 $S/build.py plan.json # [--voice Samantha] [--rate 182]
open -a "QuickTime Player" demo.mp4 # 일시 정지 상태로 열림; 직접 재생하지 마세요
예제는 examples/에 있습니다: scenario.json (단계: wait, select, click, clickIfPresent, type, send, waitStable, expand, fetchText, waitText, probeEnabled, reload; 자세한 내용은 record.ts의 헤더 참조), cards.json, plan.json. 계획 파일의 경로는 상대 경로입니다. 실제 두 클립으로 구성된 4세그먼트, 40초 빌드에서 종단 간 검증되었습니다.
이렇게 만든 이유 (발견된 문제점)
- Playwright의 고정 헤드리스 셸이 종종 다운로드되지 않음.
record.ts와cards.ts는 실패하는 대신 가장 최근에 캐시된chromium-*전체 빌드(또는$CHROMIUM_EXE)를 실행합니다. - recordVideo는 Playwright 자체 ffmpeg 빌드가 필요함. 없으면 webm이 생성되지 않습니다. preflight가
browsers.json에서 리비전을 읽고bunx playwright install ffmpeg를 실행합니다. - Homebrew ffmpeg에는
drawtext가 없을 수 있음. 배너는cards.ts에서 생성된 투명 PNG이며build.py에서 오버레이됩니다. 글꼴이나 필터를 찾을 필요가 없습니다. - 모델 응답 시간이 10~60초의 정적 구간을 만듦.
send는 "전송됨"을 표시하고waitStable은 "응답됨"을 표시합니다.build.py는 해당 구간을speed(기본 10배속)로 재생하고 나머지는 1배속으로 재생합니다. - 나레이션이 일반적으로 클립보다 김.
build.py는 음성이 끝날 때까지 마지막 프레임을 유지(tpad stop_mode=clone)하므로, 응답이 화면에 설명되는 동안 그대로 표시됩니다. - 동적 입력(OTP 코드, 이전 턴의 ID):
type단계에{{fn:NAME}}을 넣고 시나리오 옆에 있는hooks.ts에서NAME(page, state)를 내보냅니다.state.lastJson은captureJsonFrom과 일치하는 마지막 POST JSON을 보관합니다. - 선택자: 버튼은 역할과 이름 정규식(
"Tools used","^Send$")으로 일치시킵니다. CSS는 입력과 선택에만 사용됩니다. 스크립팅 전에 빠른 스크린샷으로 이름을 찾으세요. - 연결하려면 동일한 인코딩이 필요함. 모든 세그먼트는 동일한 코덱, 비트율 및 오디오 레이아웃으로 다시 인코딩된 후
-c copy로 결합됩니다. - 더 나은 음성:
ELEVENLABS_API_KEY=... build.py plan.json --eleven <voice_id>(모델 eleven_multilingual_v2; 음성+텍스트 해시로 클립이 캐시되므로 재실행 시 캐릭터를 소모하지 않음). 키는 0600 권한의 파일에 보관하고 절대 계획 파일에 넣지 말며, 사용 후 삭제하세요. - 단일 측 데모 (A/B 없음): 하나의 시나리오를 녹화하고
cards.json에 배너 하나를 제공한 후, 동일한 클립을 여러 계획 세그먼트로 나누고 각 주장에 대해spans로 대기 시간을 단축(예: 5배속)합니다. 동일한 빌드이며 A 측이 없습니다. - 사용자가
<voice_id> <key>만 붙여넣을 수 있음. 이는--eleven <voice_id>로 다시 빌드한다는 의미입니다. 느린 음성은 비디오 길이를 늘립니다(say로 72초가 92초가 됨).build.py는 음성이 끝날 때까지 마지막 프레임을 유지하기 때문입니다. - 촬영 전 해체된 데모 재구축: 수명이 짧은 인증(로컬 JWT, 터널 URL, 임시 클라우드 리소스)은 보통 다음 날이면 만료됩니다. 녹화 전에 한 번의 API 실행으로 재확인하세요. 401 "JWT 토큰 만료" 오류가 발생하면 결과가 도착하지 않는 턴을 촬영하게 됩니다.
- 원본 클립 손실: 이전 출력 mp4에서 해당 측의 영상을 잘라내고(배너 코너 색상을 샘플링하여 해당 스팬을 찾음),
<dir>/a.webm으로-f mp4와 빈 marks.json과 함께 저장한 후 하나의 명시적 스팬을 사용합니다. 배너가 이미 포함되어 있으므로banner는 생략합니다. - 오디오:
say -o는 파일만 씁니다. 사용자의 명시적 동의 없이 비디오나 오디오를 재생하지 마세요. 일시 정지 상태로 열고 사용자에게 넘기세요. - 촬영 전에 증명하세요. 먼저 A/B를 실행하고 결과(API 또는 로그)를 확인하세요. 비디오는 입증된 결과를 보여줄 뿐, 테스트 자체가 아닙니다.
- 카드는 클립 크기와 일치해야 함.
build.py는 크기를 조정하지 않습니다."viewport": [1440, 900]으로 녹화하려면cards.json에서"size": [1440, 900]이 필요합니다. 그렇지 않으면 연결 시 프레임 크기가 혼합됩니다. - 비동기 UI는 고정 대기 시간이 아닌 마크가 필요함.
waitText는 정규식이 나타나면 마크를 표시하고(또는timeout:<mark>),probeEnabled는waitMs로 버튼을 폴링하여marks.json에probes[]를 기록하며,type/send/click에tryMs는 중단 대신skipped:<step>을 표시하므로 "비활성 상태 유지" 측도 클립을 완료할 수 있습니다. - 클릭할 요소와 동일한 요소를 프로브하세요. CSS 프로브(
button[aria-label=...])가 역할-이름send와 다른 일치하는 버튼을 찾아probeEnabled가 비활성 상태를 읽는 동안 전송이 진행될 수 있습니다.probeEnabled에서는"role"을 사용하세요. - 개발 모드 오버레이(쿼리 개발자 도구, 오류 토스트)가 클립에 포함됨. 첫 번째 wait 후에
{"clickIfPresent": "^Close .* devtools$"}를 추가하세요. - "안정화"되지 않는 응답을 기다리는 경우: 라이브 경과 시간 배지가 매초 본문 텍스트를 변경합니다. 빌드 전에
marks.json에서replied마크가 있는지 확인하세요. - 증거가 보이는 텍스트에 있는지 확인하세요. 접힌 도구 카드는 확장되지 않을 수 있습니다(
expand는 조용히 아무것도 클릭하지 않음).marks.jsonbody에서 주장 문자열을 읽으세요. 없으면 프롬프트를 변경하거나 대신 카드에서 증명하세요. - "기본 측 실패" 주장을 촬영하기 전에 동등성을 증명하세요. 실제 환경에서는 발생하지 않는 이유(로컬에서는 켜져 있고 원격에서는 꺼져 있는 플래그)로 로컬 기본 측이 실패하여 나레이션에서 잘못 주장하는 경우가 있었습니다. 먼저 원격의 플래그와 일치시킨 후 촬영하세요.
- 제목 카드: 테스트된 커밋과 각 측의 플래그. 클립 세그먼트당 하나의 주장. 판정 카드로 종료.
관련 스킬
narrated-screenshot: 비디오 대신 주석이 추가된 단일 스틸 이미지.pr-ab-evidence: 이 비디오가 촬영하는 빨간색/초록색 A/B 방법의 결과.