Communitygithub.com

suxrobGM/logistics-app

Playwright와 ffmpeg를 사용하여 앱의 짧은 티저/데모 비디오를 촬영, 편집, 제작합니다. 스토리보드, 인증된 캡처, PII 검토, 애니메이션 타이틀 카드, MP4 + GIF. '티저 만들기', '데모 비디오 녹화', '제품 출시 비디오', 'README용 화면 녹화'에 사용하세요.

logistics-app란 무엇인가요?

이 스킬은 Playwright를 사용해 실제 UI를 구동하고 ffmpeg로 편집하여 런칭 수준의 티저 비디오(~30~45초)를 제작하는 전문 도구입니다. 단순한 화면 녹화가 아닌, 연출, 프레이밍, 리듬감을 갖춘 제품 비디오를 목표로 합니다. CDP 스크린캐스트(Page.startScreencast)를 사용해 사용자 작업에 영향을 주지 않고 오프스크린에서 고프레임으로 캡처하며, 스토리보드 작성부터 인증된 캡처, PII 검토, 애니메이션 HTML/CSS 타이틀 카드 제작, 최종 MP4 및 GIF 출력까지 전 과정을 지원합니다. 실제 사이드 이펙트(이메일 발송, 결제 등)에 대한 명시적 동의, 모든 프레임의 개인정보(PII) 검토 등 강력한 안전 규칙을 적용합니다. reference/ 디렉토리에 실제 동작하는 ESM 모듈이 포함되어 있어 즉시 사용 가능합니다.

지원 대상✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/suxrobGM/logistics-app/tree/main/.claude/skills/teaser-video

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

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

문서

티저 비디오

실행 중인 앱의 런칭 수준 티저(3045초)를 제작합니다: 스토리보드 작성, 실제 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 버튼만 중지하는 것이 아니라, 효과가 없을 수 있음), 읽어서 중지된 상태를 확인한 다음, 최종 메시지에서 사용자에게 횟수를 포함하여 명확히 알리십시오.

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 경고를 참조하십시오.
  • 커서는 배우입니다: 이징과 함께 미끄러지고 누를 때 딥(dip)하는 주입된 SVG 커서(cursorClick)를 사용하거나 숨기십시오. 유휴 드리프트는 없습니다.
  • 각 테이크를 리허설하고, 프레임을 추출하고, 살펴보고, 조정한 다음 실제로 촬영하십시오.

외부 창 촬영(앱 자체가 여는 브라우저, 데스크톱 앱)은 OS 캡처가 필요합니다 - gdigrab/x11grab/avfoundation(rig의 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 네이티브 비디오 업로드)을 명확히 진술하며, 촬영 중에 사용자가 알아야 할 일이 발생했으면 공개하십시오.

관련 스킬