saas-demo-maker
개요
이 스킬은 모든 웹 또는 로컬 앱의 스크린샷을 캡처하고, 세련되고 무음인 SaaS 데모 비디오(MP4)를 렌더링합니다. 이는 ~/SaaS/castify/generate_castify_demo.py에서 입증된 Castify 파이프라인을 모델로 하여 모든 Aperone 프로젝트에 일반화한 것입니다.
호출되면 세션 종료 시까지 반드시 MP4를 생성해야 합니다. "여기 계획이 있습니다"라고 멈추지 말고 실행하십시오.
사용 시기
다음 중 하나라도 해당되면 반드시 시작하십시오(부분 일치 및 의역 포함).
한국어 트리거
- 데모 동영상 / 데모 MP4 / 데모 영상 만들어 줘
- 프로모션 동영상 / 소개 영상 / 서비스 소개 영상
- 스크린샷 찍어서 동영상으로 / 스크린샷을 동영상으로
- 동영상 만들어 줘(SaaS나 앱 맥락에서)
- 기존 스크린샷으로 동영상 만들어 줘
- 화면 녹화 (정지 화면 합성으로 대체한다는 점을 알린 후 대응)
영어 트리거
- demo video / demo MP4 / product demo
- promotional video / promo video / intro video
- screenshot to video / capture and render
- make a video from screenshots
/saas-demo-maker 명령 직접 지정
판단이 어려운 경우(시작해도 됨)
- "동영상", "MP4", "스크린샷"을 포함하고 앱, SaaS, 도구 맥락이 있음
- 로컬 앱 또는 공개 URL에 대한 언급이 있음
- "기존 이미지로 동영상 만들어 줘"라는 요청
입력
사용자 메시지에서 파싱:
| 입력 | 기본값 | 참고 사항 |
|---|---|---|
url | — | 전체 URL 또는 http://localhost:3000 |
product_name | 프로젝트에서 추론 | 필(pill) 및 설정에 사용 |
brand_color | #7c3aed | VIOLET 상수 재정의 |
screens | 5 | 캡처할 스크린샷 수 |
output_path | output/saas_demo.mp4 | 프로젝트 루트 기준 상대 경로 |
mode | full | full / capture / render |
locale | 한국어 메시지면 ko, 아니면 en | 단계 텍스트에 영향 |
steps | templates.md 프리셋에서 가져옴 | 사용자가 제공한 텍스트가 우선함 |
assets_dir | output/screenshots | 렌더 모드의 소스 이미지 디렉토리 |
모드
full 모드
라이브 URL 또는 로컬 앱에서 스크린샷을 캡처한 다음 비디오를 렌더링합니다.
트리거 예시:
/saas-demo-maker https://castify.aperone.com 에서 서비스 카드용 데모 동영상 만들어 줘. 5화면, 20초 이내, 브랜드 색상은 #7c3aed, 출력은 output/castify_demo.mp4
/saas-demo-maker http://localhost:3000 의 LP, 로그인, 대시보드, 입력, 결과 화면을 찍어서, 무음 루프용 SaaS 데모 MP4 만들어 줘
capture 모드
스크린샷 캡처만 수행 — 비디오 렌더링은 하지 않음.
트리거 예시:
/saas-demo-maker 스크린샷만 찍어 줘. LP, 로그인, 대시보드, 입력, 결과 5장
render 모드
기존 스크린샷에서 비디오 렌더링만 수행 — 캡처 단계 없음.
트리거 예시:
/saas-demo-maker assets의 기존 스크린샷 5장으로 동영상만 만들어 줘. 제품명은 Aperone Academy, 브랜드 색상은 #7c3aed
/saas-demo-maker assets의 5장으로 동영상만 만들어 줘. 제품명은 Castify, 출력은 output/castify_demo.mp4
워크플로우
0단계 — 사전 점검
- 현재 프로젝트에
demo_config.json이 있으면 읽습니다. output/screenshots/또는assets/에 기존 스크린샷이 있는지 확인합니다.- 사용자 메시지에서 모드를 감지합니다(기본값:
full). output/디렉토리가 있는지 확인하고 없으면 생성합니다.
1단계 — 설정 생성
프로젝트 루트에 demo_config.json을 작성합니다:
- 사용자 메시지에서 파싱한 값을 사용합니다.
product_name에 일치하는templates.md프리셋에서 단계 텍스트를 선택하거나, 화면 수에 맞는 일반 템플릿을 사용하거나, 사용자가 제공한 텍스트를 사용합니다.- 스크립트를 생성하기 전에 지금 파일을 작성합니다.
2단계 — 스크립트 작성(full 또는 capture 모드)
프로젝트 루트에 capture_screenshots.py를 작성합니다.
프로젝트 루트에 generate_saas_demo.py를 작성합니다.
프로젝트 루트에 README_demo_video.md를 작성합니다(처음에만; 이미 있으면 건너뜁니다).
render 모드의 경우 capture_screenshots.py를 건너뜁니다.
3단계 — 의존성 설치(누락된 경우)
필요에 따라 확인 및 설치합니다(reference.md 명령어 참조):
ffmpeg—which ffmpeg || brew install ffmpegpillow—python3 -c "import PIL" || python3 -m pip install pillow- TypeScript 캡처:
node_modules/playwright존재 여부 확인
4단계 — 캡처(full 또는 capture 모드)
캡처 스크립트를 실행합니다:
python3 capture_screenshots.py
또는 프로젝트에 기존 Playwright TypeScript 캡처 스크립트(예: scripts/demo-screenshots.ts)가 있으면 그것을 우선 사용합니다:
npx tsx scripts/demo-screenshots.ts
캡처 후에 output/screenshots/에 최소 2개의 PNG 파일이 있는지 확인합니다.
캡처에 실패하면 오류를 읽고 capture_screenshots.py를 수정한 후 재시도합니다.
5단계 — 렌더링(full 또는 render 모드)
다음을 실행합니다:
python3 generate_saas_demo.py
오류를 주시합니다. 스크립트가 중단되면 역추적(traceback)을 읽고 스크립트를 수정한 후 다시 실행합니다. 사용자에게 묻지 말고 최대 3번까지 자가 치유하십시오.
6단계 — 품질 검사
ffprobe를 실행하여 확인합니다:
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,duration,codec_name,pix_fmt \
-of default output/saas_demo.mp4
reference.md의 품질 체크리스트 10개 항목을 모두 확인합니다.
항목 중 하나라도 실패하면 수정하고 다시 렌더링합니다.
7단계 — 보고
최종 응답을 출력합니다(아래 "최종 응답 형식" 참조).
스크린샷 캡처 명세
해상도
1280 × 720 (Chromium 뷰포트)
브라우저
Playwright Chromium, 헤드리스.
대기 전략
await page.goto(url, wait_until="networkidle")
await page.wait_for_timeout(800) # 추가 안정화 시간
후보 로컬 URL (순서대로 시도)
http://localhost:3000
http://localhost:5173
http://localhost:8000
http://localhost:8080
출력 디렉토리
프로젝트 루트 기준 output/screenshots/
표준 파일 이름
01-landing.png
02-login.png
03-dashboard.png
04-input.png
05-result.png
06-options.png (6화면 이상인 경우)
07-processing.png (7화면인 경우)
로컬 앱 시작
package.json을 읽어 dev 스크립트(dev,start등)를 찾습니다.- 백그라운드에서 dev 서버를 시작합니다.
- 후보 URL이 응답할 때까지 기다립니다(최대 30초).
- 스크린샷을 캡처합니다.
- dev 서버를 중지합니다.
인증 처리
.env에 테스트 자격 증명과 dev 우회 플래그(예:DEV_BYPASS_AUTH=true)가 있으면 실행 전에 환경에 설정합니다.- 로그인 화면의 경우: 데모 이메일(
demo@<product>.io)을 입력하되 제출하지는 않고 — 입력된 상태를 로그인 화면으로 캡처합니다. - 실제 인증 우회나 무차별 로그인을 시도하지 마십시오.
- 페이지가 로그인으로 리디렉션되고 우회가 불가능하면 로그인 화면을 데모 화면 중 하나로 사용합니다(그럴듯해 보입니다).
Dev 모드 아티팩트
Clerk 개발 모드 배너, Next.js dev 표시기, 디버그 오버레이 — 브라우저에서 제거하려고 시도하지 마십시오. 대신 렌더링 단계에서 카드 하단에 그라데이션 오버레이나 어두운 패널로 덮으십시오.
렌더링 명세
아키텍처
모든 프레임을 output/frames/에 PNG 파일로 생성한 다음 ffmpeg로 인코딩합니다.
인코딩에 moviepy를 사용하지 말고 ffmpeg 서브프로세스를 직접 사용하십시오.
이미지 크기 조정
card = ImageOps.fit(image.convert("RGBA"), (card_w, card_h),
method=Image.Resampling.LANCZOS)
이것이 유일하게 허용되는 이미지 크기 조정 방법입니다. 스크린샷은 각 장면(scene) 내에서 완전히 정적이어야 합니다 — 확대/축소, 패닝, Ken Burns 효과 금지.
Ken Burns — 금지
스크린샷에 프레임별 배율 조정이나 위치 오프셋을 적용하지 마십시오. 장면의 프레임 0과 프레임 98 사이에서 스크린샷 픽셀 내용이 변경되어서는 안 됩니다. 오버레이(캡션, 필, 진행률 표시줄, 글로우)만 애니메이션될 수 있습니다.
캡션 애니메이션 (허용됨)
캡션 패널은 장면의 처음 20%(scene_t < 0.2) 동안 페이드 인되면서 위로 8픽셀 이동할 수 있습니다. 이것이 이미지 레이어에 허용되는 유일한 애니메이션입니다.
타이밍
SCENE_SECONDS = 3.3 # 고정 — 변경하지 마십시오
TRANSITION_SECS = 0.4 # 고정 — 변경하지 마십시오
FPS = 30
SCENE_FRAMES = 99
TRANSITION_FRAMES = 12
전환
수평 슬라이드: 나가는 프레임이 왼쪽으로 나가고 들어오는 프레임이 오른쪽에서 들어옵니다.
ease_in_out_cubic을 사용합니다. 절단 경계에 좁은 이음새 부드럽힘 베일을 추가합니다.
전체 알고리즘은 reference.md를 참조하십시오.
ffmpeg 명령어
reference.md의 정확한 명령어를 사용하십시오. 주요 플래그:
-c:v libx264 -pix_fmt yuv420p -movflags +faststart -an -crf 18
시각적 디자인 규칙
배경
#020617 (BG) — 카드 뒤를 채움
카드 레이아웃
card_box = (34, 22, WIDTH-34, HEIGHT-22)
radius = 30
상단 크롬 강조선은 card_box[1] + 48 위치에 있습니다.
카드 테두리: 1px CARD_EDGE.
오버레이 (모두 필수)
- 진행률 표시줄 — 세그먼트로 나뉨, 카드 상단, 완료된 단계는 보라색으로 채움
- 캡션 패널 — 왼쪽 아래, 유리 어두운 패널, STEP N / 이름 / 본문
- 제품 필(Pill) — 오른쪽 아래, 브랜드 색상 점 + 제품 이름
- 초점 글로우 — 주요 UI 요소 주위에 보라색 글로우 (추론 방법은 reference.md 참조)
- 비네트(Vignette) — 전체 프레임에 미묘한 어두운 둥근 가장자리
- 하단 그라데이션 — 필요한 경우 카드 하단 영역의 dev 모드 아티팩트를 덮음
금지된 디자인 요소
- 일반 검은색 상자에 흰색 텍스트 (유리 효과 없음)
- 과도한 블룸 / 포화된 글로우
- 3D 변환이나 원근 왜곡
- 스크린샷 UI의 모든 왜곡
- 스크린샷에 보이는 텍스트 편집 또는 대체
설정 규칙
스크립트를 실행하기 전에 demo_config.json을 작성하십시오.
렌더 모드에서 다시 실행할 때는 기존 설정을 먼저 읽고 사용자 재정의를 병합하되 덮어쓰지 마십시오.
스키마:
{
"product_name": "string",
"brand_color": "#7c3aed",
"output_path": "output/saas_demo.mp4",
"screenshots": ["output/screenshots/01-landing.png"],
"steps": [{ "step": 1, "name": "...", "body": "...", "focus": null }],
"fps": 30,
"resolution": [1280, 720],
"mode": "full",
"locale": "ko"
}
구현 요구 사항
capture_screenshots.py 책임:
- Playwright Chromium 헤드리스 실행
- 뷰포트 1280 × 720 설정
- 각 대상 URL로 이동, networkidle + 800ms 정착 시간 대기
- 표준 파일 이름으로
output/screenshots/에 PNG 저장 - 각 스크린샷 전에 마우스를 화면 밖으로 이동 (
page.mouse.move(1400, 800)) - 스크린샷별 성공/실패 출력
- 성공 시 종료 코드 0, 실패 시 1
generate_saas_demo.py는 reference.md에 나열된 모든 함수를 포함해야 합니다.
주요 불변 조건:
SCENE_SECONDS = 3.3— 하드코딩, 설정 재정의 불가TRANSITION_SECONDS = 0.4— 하드코딩, 설정 재정의 불가fit_cover()는ImageOps.fit()을 호출 — 확대/축소 산술 없음render_scene()은 프레임별로 배율을 수정하지 않음encode_video()는-an플래그와 함께 ffmpeg 서브프로세스를 호출
품질 체크리스트
encode_video()가 성공한 후, 완료를 보고하기 전에 다음 모든 항목을 확인하십시오:
output/saas_demo.mp4가 존재하고 크기가 100KB보다 큼- 지속 시간이 (화면 수 × 3.3초)의 ±2초 이내
- 너비=1280, 높이=720 (ffprobe로 확인)
- 오디오 스트림 없음
- codec_name = h264
- pix_fmt = yuv420p
- 모든 스크린샷이 올바른 순서로 나타남
- 눈에 띄는 dev 모드 배너가 보이지 않음 (필요한 경우 오버레이로 덮음)
- 결과/출력 화면이 제품 가치를 명확하게 전달함
- 모든 장면에서 캡션 텍스트를 읽을 수 있음
다음 검사를 실행하십시오:
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,duration,codec_name,pix_fmt \
-of default output/saas_demo.mp4
실패 복구
| 실패 | 복구 |
|---|---|
ffmpeg를 찾을 수 없음 | brew install ffmpeg 실행 후 재시도 |
PIL을 찾을 수 없음 | python3 -m pip install pillow 실행 후 재시도 |