Community코딩 & 개발github.com

AppLoidx/record-demo

Playwright 기반의 에이전트 스킬로, 데모 또는 제품 출시 비디오를 자동으로 녹화하고 편집합니다.

record-demo란 무엇인가요?

이 스킬은 Playwright를 사용하여 웹 애플리케이션의 데모 비디오를 자동으로 제작하는 기술 전문가용 도구입니다. CLI 명령어 하나로 Playwright 스토리보드를 작성하고, 자체 엔진을 실행하여 고품질의 제품 데모 비디오를 MP4와 GIF 형식으로 출력합니다. 지원하는 포맷은 16:9, 1:1, 9:16이며, 다양한 화면 비율과 크롬 테두리 스타일(none, macos, browser)을 선택할 수 있습니다. 또한 Remotion Studio와 통합되어 자막, 스포트라이트, 줌 효과 등을 타임라인에서 편집할 수 있고, 인증이 필요한 사이트의 경우 안전하게 로그인 세션을 저장하여 녹화할 수 있습니다. 모션 규칙(예: 장면당 한 번의 카메라 이동, 'd.zoomTo'와 'd.spotlight' 사용)을 엄격히 준수해야 하며, 최종 결과물을 내보내기 전에 타입 체크, 테스트, 모션 점수 확인, 실제 프레임 검토를 통해 품질을 보장합니다.

지원 대상✓Claude Code~Codex CLI✓Cursor
npx skills add AppLoidx/record-demo

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

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

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

문서

데모 비디오 녹화하기

임시 Playwright 스토리보드를 작성한 후, 어떤 작업 디렉토리에서든 자체 포함 엔진을 실행하세요. 사용자가 요청하지 않는 한 스토리보드를 애플리케이션 저장소에 추가하지 마세요. 스토리보드는 자체 포함 상태로 유지하세요. 실행기는 Playwright가 로드하기 전에 해당 파일을 엔진 내부에 배치하므로, 스토리보드 상대 헬퍼 임포트를 사용하지 마세요. <skill-dir>는 이 저장소가 클론된 디렉토리를 의미합니다. 예: ~/.claude/skills/record-demo.

스토리보드 작성하기

다음의 이식 가능한 임포트를 사용하여 DSL을 가져오세요:

import { demo } from "record-demo/storyboard";

실행기는 이 지정자를 스테이징할 때 엔진의 실제 경로로 다시 작성하므로, 스토리보드 파일은 어디든 있을 수 있습니다. record-demo/storyboard에 대한 편집기 타입 해석은 engine/tsconfig.json의 paths에서 제공됩니다. 저장소 외부에서는, tsconfig paths에서 record-demo/storyboard를 절대 경로 <skill-dir>/engine/lib/storyboard.ts로 매핑하거나, 파일을 engine/scripts/ 안에 유지하세요.

engine/scripts/example-site.demo.ts를 참고 자료로 사용하세요. getByRole 선택자를 선호하고, locator.click() 대신 d.click(locator)를 사용하며, d.hold(...)로 동작 간격을 조절하고, 최종 상태를 어설트하거나 대기하세요.

demo("storyboard-title", async (d) => {
  await d.seed(async (page) => {
    await page.getByRole("heading", { name: "Example Domain" }).waitFor();
  });

  await d.step("Read the page", async (page) => {
    const heading = page.getByRole("heading", { name: "Example Domain" });
    await d.zoomTo(heading, { padding: 48 });
    await d.hold(2_000);
    d.zoomOut();
    await heading.waitFor({ state: "visible" });
  });
});

엔진은 타임라인 이름을 --name 또는 스크립트 기본 이름으로 재정의하므로, demo(...)에 전달된 문자열이 출력 슬러그와 일치할 필요는 없습니다.

사전 점검 (캡처 전)

로컬에서 서비스 중인 체크아웃을 대상으로 녹화할 경우: 서빙 체크아웃에서 git fetch origin을 실행하고 HEAD == origin/main(또는 사용자가 지정한 브랜치)인지 확인하세요. 오래된 체크아웃은 오래된 디자인을 녹화합니다. 오래된 경우 먼저 서버를 재빌드/재시작하세요. 모든 녹화물에 대해 서빙 SHA를 테이크 노트에 출력하여 추적 가능하도록 만드세요.

녹화

Node >= 22.18 (nvm 또는 시스템), ffmpeg, Xvfb, xdpyinfo가 필요합니다. engine/ 내부에서 pnpm install로 종속성을 한 번 설치하세요.

node <skill-dir>/engine/record.mjs \
  --script /absolute/or/cwd-relative/demo.demo.ts \
  --url https://example.org \
  [--name output-slug] [--formats 16x9,1x1,9x16] \
  [--chrome none|macos|browser] [--storage-state <path>] [--raw]

--formats를 사용하여 하나 이상의 구성 프리셋(기본값 16x9)을 선택하고, --chrome으로 렌더링된 창 프레임(기본값 none)을 선택하세요. 포맷은 요청된 순서대로 렌더링되며, 첫 번째 포맷이 GIF 인코딩에 사용됩니다. 9x16 포맷은 공격적인 가운데 크롭입니다(와이드 샷에서 페이지 너비의 약 44%만 보임). 따라서 세로 모드로 제작할 때는 동작을 중앙에 유지하세요.

--raw를 사용하면 정리된 캡처 후 중단합니다. 그렇지 않으면 다음 산출물이 생성됩니다:

  • engine/out/<name>-raw.mp4
  • 요청된 각 포맷에 대한 engine/out/<name>-<format>.mp4
  • 기본 포맷에서 인코딩된 engine/out/<name>.gif

실행기는 완료 시 산출물의 절대 경로를 출력합니다. 라이브 사이트의 재현 가능성은 대상 사이트의 책임으로 간주하고, 스토리보드에 실제 자격 증명을 절대 포함하지 마세요.

인증된 사이트

인증된 흐름은 스테이징 또는 테스트 계정으로만 녹화하고, 프로덕션 자격 증명은 절대 사용하지 마세요. 에이전트는 먼저 자체 도구를 사용하여 한 번 로그인하고, 헤드리스 Playwright 스크립트를 사용하세요. 로그인에 이메일로 전송된 OTP나 매직 링크가 필요한 경우, 선호하는 방법은 에이전트의 자체 메일 접근(Claude Code의 연결된 Gmail 커넥터/MCP, 또는 다른 런타임의 메일 CLI)을 사용하여 코드를 직접 읽는 것입니다. 그렇지 않으면 사용자에게 붙여넣기를 요청하세요. 로그인 후, await context.storageState({ path: storageStatePath })로 세션을 저장하세요. 여기서 storageStatePath는 storageStatePath="$(mktemp -d)/<account>.storage-state.json"으로 생성된 일회성 임시 경로입니다. 그런 다음 --storage-state "$storageStatePath"를 사용하여 녹화 명령을 실행하세요.

Playwright storageState는 쿠키와 localStorage만 복원합니다. IndexedDB나 sessionStorage에 인증을 유지하는 앱은 조용히 로그아웃된 화면을 녹화하므로, 캡처 전에 인증된 페이지를 확인하세요. storage-state 파일은 비밀입니다: 절대 출력하거나 커밋하지 마세요. 녹화기는 로드 직후 이 파일을 삭제합니다. 일회성 핸드오프이므로, 재녹화하려면 새로 로그인해야 하며 디스크에 인증 관련 항목이 남지 않습니다. 일회성 로그인 헬퍼 스크립트도 자격 증명을 보유하므로: 임시로 유지하고 절대 커밋하지 마세요.

Remotion Studio에서 녹화된 데모 편집하기

녹화 후 자체 포함 프로젝트를 내보내고, Studio를 설치하여 실행하세요:

node <skill-dir>/engine/scripts/export-project.mjs <name>
cd <skill-dir>/engine/out/<name>-project
pnpm install
pnpm studio

Studio의 타임라인 패널에는 편집기 스타일의 트랙(화면 필름스트립, 캡션당 하나의 명명된 클립, 스포트라이트, 줌 이동, 아웃트로)이 표시됩니다. 재생 헤드를 드래그하여 스크러빙하고, 클립의 행을 클릭하여 해당 이벤트를 찾으세요. 속성 패널 또는 fixtures/timeline.json을 사용하여 캡션, 줌 타이밍(줌 이동은 1650ms 기준 이상 유지), 스포트라이트 타이밍, 및 아웃트로 제목을 편집하세요. remotion/theme.ts를 편집하여 색상, 타이포그래피, 간격 및 모션을 변경하세요. pnpm render로 완성된 16:9 비디오를 렌더링하세요.

모션 및 스토리보드 규칙 (포스팅 가능한 클립을 만드는 조건)

  • 장면당 카메라 이동은 한 번, 필드당이 아닙니다. 한 섹션으로 한 번 줌하고 그 안에서 동작하세요. 입력당 줌은 지나치게 날카로운 컷으로 읽힙니다.
  • 페이지 전환 시 와이드로 이동하고, 빈 페이지에서는 와이드로 유지하세요. 내비게이션하는 클릭 전에 d.zoomOut()을 호출하세요. 거의 빈 페이지에서 상태 표시로 줌하지 마세요.
  • 페이지 하단 근처의 섹션: d.zoomTo([...locators], { scroll: "center", padding: 48 })
    • 카메라 클램프가 페이지 가장자리 rect를 중앙에 배치할 수 없습니다. 스크롤 중앙 정렬이 루트에서 이를 수정합니다. Locator[]는 유니온 bbox를 통해 전체 섹션을 프레임화합니다.
  • d.spotlight([...locators]) = Apple 스타일의 초점 디밍(컷아웃 + 링). 충분한 holdMs를 사용하고, 단계가 끝나기 전에 d.spotlightOff() + hold(600)으로 명시적으로 종료하세요. 스포트라이트 rect는 뷰포트에 맞아야 합니다(강제됨). 줌 rect는 설계상 넘칠 수 있습니다.
  • Seed는 실제 데이터를 기다립니다. 트리거 요소만 기다리지 마세요. 그렇지 않으면 비디오가 스켈레톤 위에서 열립니다. 알려진 콘텐츠 노드 + 약 600ms를 기다리세요.
  • 결과 캡션 전에 d.settle(locator)를 사용하세요. 제출 후 다시 가져오는 뷰는 잠시 빈 상태가 됩니다. 일반 waitFor는 첫 번째 페인트에서 해결되고, 결과 캡션이 빈 페이지 위에 나타납니다.
  • 캡션은 커서 동작과 연결된 명령형으로 작성합니다. 닫는 장면에는 결과 캡션(d.caption(...)을 단계 후반에)을 넣고, 단계 캡션을 다듬어 명령형이 완료된 동작 위에 걸리지 않도록 하세요.
  • d.outro(title)은 마지막 장면 후에 조용한 종료 슬레이트로 포스팅 가능한 클립을 마무리합니다.
  • 항상 최종 상태를 어설트하세요 - 그렇지 않으면 파이프라인이 깨진 흐름의 세련된 비디오를 렌더링합니다.
  • localhost URL, 내부 호스트 이름, 공급자 이름 또는 실제 자격 증명이 화면에 표시된 클립을 절대 배포하지 마세요. 프레젠테이션 전용 문자열을 시드에서 마스킹하세요(window.open 패치 및 MutationObserver 입력 재작성).

작업 완료 보고 전 확인 사항

  1. engine/에서 pnpm typecheck && pnpm test.
  2. node scripts/score-motion.mjs out/timeline.json - FAIL은 차단됨; WARN 줌 속도 ~0.78/s가 허용된 정상 상태입니다; 불연속 판정은 카메라 버그입니다; 데드 에어 WARN은 정적 구간 >= 3.5초에 커서 이동이 40px 미만인 경우를 의미합니다 - 간격을 다시 조정하거나 캡션을 추가하세요.
  3. 엔진 변경 후 node scripts/prove-composition.mjs.
  4. 실제 렌더링을 시청하세요: ffmpeg -i out/<name>-16x9.mp4 -vf fps=1 out/frames/%03d.png를 실행하고 프레임을 읽으세요. 줌 클리핑, 캡션 지연, 컷아웃 동기화 불일치 및 화면상의 개발자 URL은 초록색 테스트 실행에서 보이지 않습니다.

문제 해결

증상원인 / 해결책
Invalid demo viewport ... 중단지오메트리 변경 - 실행 플래그를 수정하고, 어설션을 완화하지 마세요.
커서 오프셋이 수직으로 약 174pxChrome이 --app이 아닌 탭 모드로 실행되었습니다.
클래퍼보드 프레임을 찾을 수 없음디텍터 허용 오차는 64입니다(외부 캡처는 평균적으로 불순함). 여전히 놓치면 캡처가 검은색이 아닌지 확인하세요(Chrone이 잘못된 DISPLAY에 있음).
캡션/커서가 클립 위에서 표류클래퍼보드 동기화 - 벽시계 시간을 빼지 마세요.
스포트라이트 컷아웃이 대상에서 벗어남Rect가 부드러운 스크롤과 경쟁했습니다. measureTarget의 안정성 루프가 유지되어야 합니다. 반복되면 타임아웃을 높이세요.
크롭 가장자리에서 단어가 문자 중간에 잘림모달의 경우 zoomTo(locator, { padding: 120 }).
줌이 프레임 밖으로 콘텐츠를 클리핑maximumScale 취향 문제(1.45가 작동함), 클램프 버그가 아닙니다.

엔진 변경 검증

engine/에서 실행:

pnpm typecheck && pnpm test
node scripts/prove-composition.mjs

관련 스킬