티저 영상
실행 중인 앱의 런치 수준 티저(~30-45초)를 제작합니다: 스토리보드를 작성하고, 실제 UI를 구동하여 촬영한 후, ffmpeg로 편집하여 MP4와 README용 GIF를 제공합니다.
출력물은 화면 녹화가 아닌 제품 영상처럼 보여야 합니다. 차이는 방향성 - 연출, 프레이밍, 리듬 - 이지 해상도가 아닙니다.
참조 구현체는 reference/ 디렉토리에 있으며, 의사 코드가 아닌 실제 동작하는 ESM 모듈입니다. 프로젝트 내부가 아닌 스크래치 디렉토리에 설정하세요:
cp -r <skill>/reference/* "$SCRATCH/" && cd "$SCRATCH" && npm install
export TEASER_BASE_URL="https://the-app.example.com"
reference/package.json은 "type": "module"과 세 가지 의존성을 선언합니다. 모든 스크립트는 TEASER_BASE_URL을 읽으므로 특정 앱에 하드코딩되지 않습니다.
다른 모든 것보다 먼저: 두 가지 엄격한 규칙
1. 명시적이고 항목별로 동의를 받지 않고 실제 세계 부작용을 절대 트리거하지 마십시오.
실제 앱을 촬영한다는 것은 실제 버튼을 클릭하는 것을 의미합니다. 그 중 일부는 이메일을 보내고, 공개적으로 게시하고, 요금을 청구하거나, 서드파티에 양식을 제출할 수 있습니다. 앱을 조작하기 전에:
- 기계를 떠나는 모든 작업을 스토리보드에 열거하십시오.
- 각 작업이 무엇을 수행하는지, 몇 번 수행하는지 정확히 사용자에게 알리고, 횟수에 대한 동의를 얻으십시오.
- 되돌릴 수 없는 단계 직전에서 멈추는 모드(미리보기, 드라이런, 촬영 후 거절할 수 있는 확인 게이트)를 선호하십시오.
라이브 시스템에 대한 읽기 전용 프로브 같은 것은 없습니다. 이미 실행 중인 세션에 착륙하는 "진단" 클릭은 실제로 실행됩니다. 어떤 동작이 작동하지 않은 이유를 디버깅하는 경우, 다음 클릭이 작동할 것이라고 가정하고 그에 대비하십시오.
의도하지 않은 작업이 실행된 경우: 즉시 해당 소스에서 프로세스를 중단하고(UI 버튼만이 아니라 세션/워커를 종료해야 하며, UI 버튼은 효과가 없을 수 있음), 읽어서 중단 상태를 확인한 후, 최종 메시지에서 사용자에게 횟수를 포함하여 명확히 알리십시오.
2. 모든 프레임이 공개되어 있고 개인정보(PII)가 가득하다고 가정하십시오.
실제 계정에는 이름, 이메일, 주소, 문서가 포함되어 있습니다. 사전에 사용자와 정책을 결정하십시오:
- 프레임으로 감싸기(기본값) - 신원을 배제하도록 샷을 구성하십시오. ffmpeg 단계에서 지속적인 크롬(사이드바, 아바타, 계정 메뉴)을 자르십시오.
- 촬영 전 숨기기 - 카메라가 돌아가기 전에 문제가 되는 카드에 대해
page.evaluate로visibility: hidden을 설정하십시오. 절대 촬영하고 잘라내길 기대하지 마십시오. - 시드된 데모 계정 사용 - 가능할 때 가장 깔끔합니다.
제공하기 전에 최종 편집본의 모든 프레임을 전체 해상도로 검토하십시오. 접촉 시트가 아닌 프레임 자체를 검토하십시오.
워크플로우
1. 정찰 및 스토리보드 작성
먼저 모든 후보 화면의 인증된 스크린샷을 캡처하십시오(reference/scout.js). 그것들을 살펴보십시오. 그런 다음 스토리보드 표를 작성하십시오: 비트, 샷, 시청자가 느껴야 하는 감정, 길이. 할당된 작업이 없는 샷은 촬영 전에 잘라냅니다.
작동하는 아크: 긴장(문제) → 공개(제품) → 증명(실제로 그 일을 함) → 규모(결과) → 신뢰(실행되는 곳) → 마무리.
스토리보드에 어떤 화면이 PII를 포함하는지, 어떤 것이 안전한지 기록하십시오.
2. 세트 준비
촬영 후가 아닌 촬영 전에 큐레이션하십시오:
- 데이터가 가장 잘 보이는 뷰를 선택하십시오 - 가득 찬 차트, 활성 목록, 인식 가능한 이름, 0이 아닌 카운트. 절대 스피너, 빈 상태 또는 반쯤 렌더링된 차트를 촬영하지 마십시오.
- UI 상태를 의도적으로 설정하십시오(패널 너비, 접힘/펼침, 필터, 스크롤 위치) - init 스크립트 또는 사전 롤
page.evaluate의localStorage를 통해. - 토스트, 배너, 쿠키 바를 카메라 밖에서 해제하십시오.
- 데이터가 안정화되도록 하십시오:
networkidle및 몇 초 대기.
3. 촬영
화면 녹화가 아닌 CDP 스크린캐스트(Page.startScreencast)를 사용하십시오. 페이지를 오프스크린에서 ~100fps로 캡처하므로 사용자가 하는 일이 프레임에 나타나지 않고 기계를 계속 사용할 수 있습니다. Playwright가 구동하고 CDP가 촬영합니다. reference/rig.js가 이를 구현합니다.
- 샷당 하나의 주제. "전체 앱"이 아닌 그 대상을 프레이밍하십시오.
- 카메라 움직임은 페이지 내부의 스크립트된 이지드 스크롤(
cameraScroll)에서 비롯되며, 필터에서 비롯되지 않습니다. 아래 zoompan 경고를 참조하십시오. - 커서는 배우입니다: 이징으로 미끄러지고 누르면 딥하는 주입된 SVG 커서(
cursorClick)를 사용하거나 숨기십시오. 유휴 드리프트는 금지. - 각 테이크를 리허설하고, 프레임을 추출하고, 살펴보고, 조정한 후 실제로 촬영하십시오.
외부 창 촬영(앱 자체가 여는 브라우저, 데스크톱 앱)은 OS 캡처가 필요합니다 - gdigrab/x11grab/avfoundation (리그의 recordDesktop). 이는 화면의 모든 것을 캡처하며, 사용자의 작업도 포함합니다. 사용자에게 경고하고, 자리 비우도록 요청한 후, 결과를 프레임별로 검토하십시오. 개인적인 것을 캡처한 경우 삭제하십시오.
4. 타이틀 카드
정적 이미지가 아닌 브라우저 내에서 촬영된 애니메이션 HTML/CSS입니다. 앱 자체 오리진의 빈 페이지에 카드 마크업을 주입하여 웹 폰트와 팔레트가 적용되도록 한 후 스크린캐스트하십시오. 라이브 페이지에서 실제 디스플레이 폰트를 가져와(getComputedStyle) 알려진 좋은 모노 스택을 고정하십시오. 폰트를 추측하지 마십시오.
앱의 모션 언어(자체 이징 곡선 및 지속 시간)와 일치시킵니다. 프로젝트에 설정된 카드 스타일이 없는 경우, 디자인 전에 frontend-design 스킬을 로드하십시오.
5. 편집
reference/build.js는 각 세그먼트를 공통 크기/fps로 정규화한 후 체인을 크로스페이드합니다. 약 2.5~4초마다 컷을 유지하십시오. 주변 일상적인 부분을 압축하면서 정점 순간에는 일반 속도로 여유를 주십시오.
6. 검토 후 제공
- 접촉 시트 및 초당 전체 해상도 프레임을 생성하십시오.
- PII, 잘린 패널, 읽을 수 없는 텍스트가 있는지 프레임을 읽으십시오.
- 프로브로 지속 시간과 치수를 확인하십시오.
- MP4 및 README용 팔레트 최적화된 GIF를 제공하십시오(GitHub는 커밋된 MP4를 인라인 재생하지 않습니다). GIF는 ~10MB 미만으로 유지하십시오.
- 요청하지 않으면 무음으로 남겨 두십시오. 음악을 라이선스할 수 없습니다. 그렇게 말하십시오.
어렵게 얻은 세부 사항
절대 zoompan을 푸시인에 사용하지 마십시오. 프레임당 줌을 다시 계산하고 자르기 창을 전체 픽셀로 반올림하므로 이미지가 앞뒤로 튑니다 - 지진처럼 읽힙니다. 록오프 샷과 실제 페이지 내 스크롤을 사용하십시오. 푸시인이 반드시 필요하면, 먼저 소스를 4배로 사전 확장하고 프레임 델타 측정(reference/jitter.js)으로 확인하십시오: 록오프된 정적 샷은 평균 델타가 1.0 미만이어야 하며, 눈에 띄는 떨림은 3+로 측정됩니다.
애니메이션이 안정되면 스크린캐스트가 프레임 방출을 중단합니다. 1.2초 후에 끝나는 애니메이션이 있는 카드는 1.2초 클립을 생성합니다. tpad=stop_mode=clone:stop_duration=N으로 패딩하고 -t로 원하는 길이로 자릅니다.
고정 속도가 아닌 타임스탬프가 있는 프레임을 조립하십시오. 스크린캐스트 프레임은 metadata.timestamp와 함께 도착합니다. 실제 프레임별 지속 시간으로 ffmpeg concat 목록을 작성한 다음 상수 60fps로 리샘플링하십시오. 고정 간격을 가정하면 저더가 발생합니다.
ffmpeg-static을 dev 의존성으로, 모듈 경로로 해석하십시오. 절대 ffmpeg가 PATH에 있다고 가정하지 마십시오. (ffprobe는 해당 패키지에 없습니다 - 대신 ffmpeg -i stderr를 파싱하십시오.)
인증된 캡처: 한 번 헤드풀로 로그인하고, storageState를 저장한 후, 모든 테이크에서 재사용하십시오(reference/login.js). 세션은 만료됩니다 - 같은 날 촬영을 끝내거나 다시 실행하십시오. 또한 거기서 UI 환경 설정에 대한 localStorage도 시드하십시오.
배포된 오리진의 로컬호스트는 Chrome의 로컬 네트워크 액세스 정책에 의해 차단됩니다. 페이지가 로컬 서비스에 도달해야 하는 경우, --disable-features=LocalNetworkAccessChecks,PrivateNetworkAccessChecks,BlockInsecurePrivateNetworkRequests로 시작하십시오.
고정 오프셋에서 지속적인 크롬을 자르십시오. 뷰포트 너비 1920 + railWidth로 촬영한 다음, crop=1920:1080:railWidth:0로 사이드바를 제거하고 정확히 1080p에 맞춥니다.
결과물
경로, 지속 시간, 치수를 보고하고, 사용자에게 여전히 필요한 것(음악, GitHub 네이티브 비디오 업로드)을 명시하며, 촬영 중에 사용자가 알아야 할 사항이 발생했으면 공개하십시오.