제품 비디오 (그리고 그 주변의 에셋들), 엔드투엔드
당신은 라이브 웹 페이지에서 vos CLI를 사용하여 출시 가능한 제품 에셋(세련된 비디오, 정확한 크기의 스틸 이미지, 또는 둘 다)을 제작하고 있습니다. 모든 것은 데이터입니다. 당신은 플로우 스크립트를 작성하고, CLI가 녹화 및 계획을 수행하며, JSON을 튜닝하고, 다시 렌더링합니다. 페이싱이나 줌을 수정하기 위해 절대 다시 녹화하지 마세요. doc.json을 편집하고 다시 렌더링하세요. 품질 기준: references/taste.md — 그 품질 루프를 따르고 스틸 이미지를 멀티모달 방식으로 판단하세요.
설정
npm i -D @vosjs/cli
하나의 명령어, 하나의 패키지: @vosjs/cli는 오픈 소스(MIT) vos 바이너리로, 엔진 동사, 여기서 사용되는 테이크 파이프라인(recond / plan / frames / render on screen recordings) 및 vos.so 플랫폼 동사를 포함합니다. (버전 0.9까지는 테이크 파이프라인이 @vosso/vos-plugin으로 별도 제공되었습니다. 여전히 이를 나열하는 프로젝트는 제거할 수 있습니다.) 요구 사항:
- Chromium 브라우저: 시스템 Chrome이 자동으로 발견됩니다. 그렇지 않으면
npx playwright install chromium을 실행하거나VOS_BROWSER_PATH를 지정하세요. 종료 코드 3은 브라우저를 찾을 수 없음을 의미합니다. - 렌더링 시 네트워크 연결: 렌더 페이지는 esm.sh에서 three/mediabunny를 로드합니다. 녹화는 또한 대상 URL에 도달해야 합니다. 완전히 오프라인인 샌드박스는 렌더링할 수 없습니다. 아무것도 배송하지 말고 그렇게 말하세요.
규칙: 로그 → stderr, 결과 → stdout; --json은 {"event":"done",…}으로 끝나는 NDJSON 스트림을 출력합니다. 종료 코드: 0 정상 / 1 오류 / 2 사용법 또는 엄격한 실패 / 3 브라우저 없음 / 4 리코더가 페이지 대신 로그인 화면을 만남 (SESSION이 누락되었거나 만료됨, 스크립트 버그 아님: references/sessions.md). vos <동사> --help는 해당 동사의 플래그를 출력합니다 (@vosjs/cli 0.41.1 이상).
단계 0 — 대상을 선택하세요 (모든 것을 결정합니다)
| 대상 | 뷰포트 | 출력 | 추가 사항 |
|---|---|---|---|
| 랜딩 페이지 클립 (히어로/섹션 임베드) | 2560×1440 (푸티지 기본 2K) | webm → VP9 재인코딩 + 포스터 | 무음 루프; references/destinations.md 참조 |
| 런칭 비디오 (PH, 소셜, 스토어 프로모션) | 2560×1440 또는 1280×720 | mp4 (--format mp4, 시스템 Chrome 필요) | doc.audio를 통한 배경 음악 |
| 런칭 킷 스틸 이미지 (스토어 스크린샷, 타일, OG) | 에셋에 맞게 크기 조정 | 동일한 테이크에서 frames --frame <t> --size WxH PNG | 하나의 테이크 → 모든 에셋 |
| 빠른 데모 (이슈, PR, 채팅) | 1280×720 | webm, 기본값 | 속도가 세련미보다 우선; 여기서만 초안 허용 |
채널별 치수 및 바이트 예산: references/destinations.md.
핵심 루프 (모든 대상)
-
자신의 도구(fetch HTML / Playwright)로 대상 페이지를 탐색하세요. 하나의 이야기를 전달하는 3~6개의 순간을 식별하세요. 안정적인 선택자(
a[href='…'], id, 역할 — nth-child 체인이 아님)를 수집하세요. 세트처럼 콘텐츠를 준비하세요: 스크립트는 자랑스러운 스크린샷이 보여줄 상태로 제품을 남겨야 합니다 — 레이블이 입력되고, 실제처럼 보이는 데이터, 이야기 중인 기능. 빈 캔버스는 빠르게 녹화되지만 아무것도 데모하지 않으며, 다운스트림 구성이 이를 구제할 수 없습니다.로그인 뒤에 있나요? 스크립트 전에 세션을 확보하세요. 세션이 없는 리코더는 벽(로그인 페이지 또는 사이트가 낯선 사람에게 보내는 공개 페이지)을 녹화하고, 유일한 증상은 선택자를 건너뛰는 것입니다.
references/sessions.md의 사다리를 위에서 아래로 따라가며 유효한 첫 번째 단계에서 멈추세요: 벽 없음 (데모 모드, 인증이 꺼진 로컬 서버) → 프로젝트가 이미 가지고 있는 테스트 인증에서 세션 MINT (playwright/.auth,auth.setup.ts, 시드 스크립트: 누구에게도 묻기 전에 먼저 찾아보세요) →actions.json의setup을 사용하여 오프 카메라로 로그인 ({ "env": "NAME" }의 비밀번호, 절대 리터럴 아님) → 사람이 한 번 로그인 (vos session open <url> --name <app>, 그런 다음 record에--session <app>) → 사람이 vos extension을 사용하여 숏 리스트에서 녹화하고 vos actions script actions.json이 출력하면, 당신이 편집합니다. 모든 단계는setup,--storage-state용 상태 파일 또는--session용 명명된 세션으로 끝납니다. 프로덕션 비밀번호를 입력하거나 수락하지 말고, 상태 파일을 테이크 디렉토리와 git 외부에 보관하며, 데모 계정에서 녹화하세요: 계정이 보여주는 것이 비디오에 표시됩니다.이미 agent-browser로 기능을 검증했나요? 그 워크를 유지하고 두 번째 스크립트를 건너뛰세요. agent-browser의
--json결과는 무엇이 실행되었는지 말하지 않으므로(scroll은{scrolled:true}를 반환), 각 호출을 감싸 명령이 결과 옆에 같이 있게 한 다음 변환하세요:ab() { agent-browser "$@" --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const r=JSON.parse(s);process.stdout.write(JSON.stringify({command:process.argv.slice(1),...r})+"\n")})' -- "$@" >> steps.jsonl; } ab open https://target.example; ab snapshot -i -u; ab click @e27 ab wait 800; ab snapshot -i # 페이지 변경: 참조 번호 재지정 ab fill @e2 query; ab press Enter vos actions from-agent-browser steps.jsonl --out actions.json(하나의
agent-browser batch … --json > steps.jsonl로 실행된 전체 경로는 이미 그 모양을 가지고 있습니다). 로그는 현재 디렉토리의steps.jsonl이므로 하나의 디렉토리에서 작업하세요. 참조는 그들 앞에 있는 마지막snapshot -i를 통해 해결되며, 탐색 후 그리고 대화 상자 내에서 다시 번호가 RE-RENUMBERED됩니다: 페이지를 변경하는 모든 작업 후에 다시 스냅샷을 찍고, 참조를 지정하기 전에 참조를 읽으세요 (-u는 링크에 href를 제공합니다). 컨트롤을 클릭하고, 단축키를 누르지 마세요: ⌘K는 인간을 위해 대화 상자를 열지만, 키 입력은 리코더가 재생할 수 없는 한 단계입니다. 리코더가 따라올 수 없는 것(단축키, 드래그, 두 번째open)은 출력에 NAME이 지정되며, 절대 삭제되지 않습니다: 노트를 읽고, 해당 단계를 수동으로 작성한 다음 녹화하세요. -
actions.json작성:{ "url": "https://target.example", "viewport": { "width": 1280, "height": 720 }, "steps": [ { "do": "wait", "ms": 800 }, { "do": "hover", "selector": "a[href='/pricing']", "ms": 700 }, { "do": "click", "selector": "#cta" }, { "do": "wait", "ms": 1500 }, { "do": "scroll", "dy": 400 }, { "do": "move", "x": 640, "y": 320 }, { "do": "wait", "ms": 900 } ] }동사:
waithoverclicktypescrollmovedrag(type={do:'type', selector, text, delayMs?, ms?, focus?}: 필드를 클릭한 다음text를 입력합니다;focus:false는 이미 포커스된 곳에 입력하여 Enter를 제출합니다) (drag = 실제 편집:{do:'drag', selector|x,y, tx, ty, ms}— 범위 입력 슬라이드, 캔버스 요소 드래그, 타임라인 클립 이동). 페이싱은 줌 계획입니다: 열기wait ≥700ms; 중요한 것에 700–900ms 동안 호버 (체류는 줌이 됨); 클릭의ms는 READING 시간이며, 페이지의 마지막 변경 이후 유지됩니다 (@vosjs/cli0.47 이상; 리코더가 자체적으로 정착 시간을 지불), 따라서 비트로 크기를 조정하세요: 탐색 후 약 1000ms, 컨트롤 후 600ms, 느린 페이지를 위해 패딩하지 마세요; 정착된 상태로 끝나세요. 호버 트리거 메뉴에서 커서를 멀리 이동시키세요 (taste.md, 흐름 규칙).vos validate actions.json으로 확인하세요.그런 다음 리허설하세요 (
@vosjs/cli0.39 이상):vos record --actions actions.json --out take --dry-run. 모든 단계가 실제 페이지에 대해 순서대로 실행됩니다(나중 선택자는 일반적으로 이전 클릭 후에만 존재하기 때문), 그러나 아무것도 캡처되지 않고 아무것도 기록되지 않습니다: 놓친 선택자는 실시간 테이크 및 인코딩 후가 아니라 초 단위로 명명되며(exit 2),--out에 이미 있는 테이크는 푸티지와 컷을 유지합니다. 각 단계의 rect를 캡처 픽셀로 출력하며, 이것이 고정된 레이어가 읽는 것입니다. 모든 스크립트 편집 후에 다시 리허설하고, 통과하는 스크립트만 녹화하세요. 로그인된 제품도 같은 방식으로 리허설합니다:--storage-state와--browser-arg=도 적용되며, 리허설은 프레임이 노출하는 것(주소, 키, 카드)을 나열하여 끝납니다. 녹화하기 전에mask로 그것들을 가리세요:references/sessions.md. -
녹화:
vos record --actions actions.json --out take --strict --json--strict항상 사용: 선택기 건너뛰기 / 네트워크 유휴 시간 초과 → 완료 이벤트에skipped[]와 함께 exit 2. 건너뛰기는 흐름이 깨졌음을 의미합니다 — 수정하고, 절대 우회하여 배송하지 마세요. 테이크는 자동으로 인코딩 및 계획을 수립합니다. (vos create --actions actions.json out.webm --strict는 단일 샷 녹화+렌더링 동사입니다 — 빠른 첫 번째 패스에는 좋지만, 이 스킬의 루프는 렌더링 전에 프레임을 검토하므로 여기서는 별도 동사를 선호하세요.) -
doc.json튜닝 (JSON Schema는@vosjs/clinpm 패키지와 함께 제공됩니다:schema/doc.schema.json):zoom:[{in, out, level, cx, cy, source}], SOURCE 초; 레벨 1.4–2.8;cx/cyNORMALIZED [0..1] (0.5,0.5 = 중앙) — 픽셀이 아님; 당신이 건드린 범위에"source": "manual"설정 (재계획에서 유지됨).segments(트림) ·speed(rate0.1–16) ·frame.*·cursor.tilt:[{in, out, rx, ry, source}], SOURCE 초 — 3D 카드가 활성화된 동안 포즈로 기울어지고, 그 사이에 휴식 위치로 돌아옵니다. DEGREES (±5..18은 프리미엄으로 보임): +rx = 위쪽 가장자리가 가까워짐, +ry = 왼쪽 가장자리가 가까워짐 (오른쪽 초점을 향해 기울이기 = 음수ry). 범위 ≥ 0.8초; 줌 순간과 쌍을 이루고(동일한 in/out은 움직임을 연결), 약 5초 비트당 하나의 포즈 변경. 당신이 건드린 범위에"source": "manual";tiltStyle: "subtle"|"medium"|"strong"은 자동 지팡이를 기록합니다.frame.backgroundMedia: 카드 뒤의 비디오 루프/이미지 —{"kind":"video","key":"/bg.webm","duration":10,"dim":0.2}.key= 테이크 디렉토리("/bg.webm")에 드롭된 파일 또는 미디어 URL; 비디오는duration이 필요함 (OUTPUT 앵커, modulo 루프);dim0..1 스크림. 분위기, 주제가 아님 — 밀집된 UI 뒤에서 흐리게 처리.audio: OUTPUT 앵커 클립;key는 테이크 디렉토리("/music.mp3")에 드롭된 파일일 수 있음; gain/fades/loop. 전체 렌더링에서 먹싱됨 (Opus/AAC);--range는 무음 유지; 단일 비행을 강제합니다.- 내보내기:
{"resolution": "720p|1080p|2k|4k", "fps": 30}— 푸티지를 초과하지 마십시오 (validate가 경고합니다). 그런 다음vos validate take --json— 린트를 통과해야 합니다.
-
렌더링하기 전에 확인하세요 (taste.md 품질 루프):
vos frames take --at-zooms --times 0,25%,50%,75%,100% --json→ taste.md에 대해 모든 스틸 이미지 판단, 줌 정점에서 가장 엄격하게.- 반복: doc.json 편집 →
vos render take check.webm --range a..b --draft(초, 절반 해상도 — 절대 초안을 배송하지 마세요) → 변경된 영역을 다시 프레임. - 프레젠테이션을 시도 중이신가요? 스크래치 스크립트 대신 플래그를 사용하세요.
render/frames는 doc 오버라이드 —--set <path>=<value>(반복 가능; JSON 또는 문자열),--frame <macos|windows|minimal|none>(렌더),--background <url>— 메모리의 doc을 패치하고(doc.json은 건드리지 않음) 린트로 게이트됩니다. 따라서vos frames take --frame 2.0 --set frame.browserBar.kind=mac-light --set tilt[0].rx=8은 파일을 건드리지 않고 프레임이 있고 기울어진 카드를 미리 봅니다.
-
최종 렌더링:
vos render take out.webm --json(또는--format mp4). 완료를 선언하기 전에 taste.md에 대해 최종 프레임(frames --at-zooms)을 다시 확인하세요. 렌더링은 결정론적입니다 — 당신의 편집만이 출력을 변경합니다.
6b. 인간 검토 라운드 (요청에 포함된 경우): vos open take는 테이크를 스튜디오로 제공합니다 — 당신의 doc.json 편집이 그대로 도착하고