기본 익스플레이너
차분하고 프리미엄한 제품 데모입니다. 마치 잘 투자받은 스타트업이 홈페이지에 올려놓는 그런 종류의 영상입니다. 모든 비결은 절제에 있습니다: 밝고 가벼운 캔버스, 한 번에 한 줄의 짧은 텍스트, 그리고 제품 자체 인터페이스를 깔끔하게 재구성하여 클로즈업으로 촬영하면서 사용하는 모습을 보여줍니다. 카메라가 스토리텔링을 합니다: 텍스트 라인 안으로 접근하고, 타이핑 동작을 따라가며, 결과를 드러내기 위해 뒤로 물러나고, 다음 기능으로 부드럽게 이동합니다.
하나의 HTML 페이지로 작성하며, 시간 값에 따라 모든 프레임을 렌더링한 후 모션 블러와 사운드트랙을 포함한 MP4로 렌더링합니다.
1단계: 브리핑 받기 (한 번의 메시지로, 그 후 진행)
한 번의 메시지로 모든 것을 질문한 후, 스스로 작업하세요. 제품만 필수이며, 나머지 항목이 비어 있으면 스스로 결정하고 선택한 내용을 말하세요.
- 제품: 이름, 그리고 몇 문장으로 설명하는 기능. 웹사이트 URL이 있다면 더 좋습니다.
- 시청자가 반드시 기억해야 할 한 가지 (예: "아이디어를 입력하면 라이브 앱이 나옵니다").
- 브랜드: 색상, 폰트, 로고 파일, 또는 "웹사이트 사용". 없으면 아래 기본 팔레트를 사용하세요.
- 형식: 16:9 (1920×1080) 또는 9:16 (1080×1920). 기본값 16:9.
- 길이: 이 스타일의 기본 길이는 아래에 나와 있습니다.
- 음악: 자체 트랙(파일 경로) 또는 합성하도록 맡기기. 기본값: 합성.
- 방향 (선택 사항): 원하는 장면, 태그라인, 콜 투 액션, 피해야 할 모든 것.
URL이 제공된 경우, 무엇을 쓰기 전에 제품의 실제 문구, 기능, 색상 및 폰트 이름을 위해 (웹 가져오기) 읽으세요. UI 레이블 및 태그라인에는 실제 문구를 사용하세요.
사실을 절대 지어내지 마세요. 고객 수, 수익, 평점, 사용후기 또는 인용문을 만들어내지 마세요. 사용자나 웹사이트가 명시한 경우에만 숫자를 사용하고, 그 외에는 상대적인 막대, 진행률 및 자리 표시자 스켈레톤 라인을 사용하세요. UI 내부의 예제 콘텐츠(프롬프트, 파일 이름, 프로젝트 이름, 영수증의 가격)는 괜찮으며 신뢰할 수 있어야 합니다. 제품 자체에 대한 주장(통계, 사용자 수, 평점, "무료"와 같은 제안)은 허용되지 않습니다. 콜 투 액션은 사용자나 웹사이트가 제공한 URL 또는 제안만 사용하고, 없으면 이름과 태그라인으로 끝내세요.
로고. 사용자가 파일을 제공하거나 자신의 제품이고 요청한 경우에만 로고를 사용하세요. 그렇지 않으면 브랜드 폰트로 이름을 텍스트로 작성하세요. 서드파티 로고(통합)는 제공된 경우에만 사용하고, 그렇지 않으면 이름이 적힌 중립적인 둥근 타일을 사용하세요.
또한 (선택 사항으로) 보여줄 3~5가지 기능 또는 워크플로 단계와 제품이 연결되는 모든 것(통합)을 요청하세요. URL이 제공된 경우 사이트에서 가져오세요.
이 스타일의 기본 길이: 60초. 범위 45~90초. 길이에 따라 예산을 조정하세요(선택적 섹션을 먼저 제거):
| 길이 | 기능 | 선택적 섹션 |
|---|---|---|
| 45초 | 2~3개, 각 약 9초 | 증명 또는 통합, 둘 다는 안 됨 |
| 60초 | 3~4개, 각 약 10초 | 증명 / 통합 중 하나 |
| 90초 | 4~5개, 각 약 12초 | 둘 다 |
2단계: 스크립트 작성, 그 다음 제작
구조
먼저 스크립트와 비트 시트를 작성하세요: 화면 텍스트의 모든 줄, 그 뒤에 오는 UI 순간 및 해당 시간; 위 예산에 대해 시간을 합산하세요. 화면 텍스트가 유일한 "음성"이므로, 자체적으로 스토리를 전달해야 합니다.
장면과 카메라가 함께 작동하는 방식: 각 장면(제목 줄, UI 순간)은 자체 카메라를 가진 별도의 레이어입니다. 장면 내에서 카메라는 접근하고, 따라가고, 뒤로 물러납니다. 장면 사이에서는 나가는 레이어가 짧은 블러(0.3~0.4초)와 함께 다음 레이어로 용해(dissolve)되며, 다음 레이어는 이미 움직이고 있습니다.
- 오프닝 (0~5초). 평범한 밝은 캔버스. 중앙에 작은 단어가 페이드 업됩니다:
Introducing. 브랜드 순간으로 용해됩니다: 부드러운 브랜드 그라데이션이 (천처럼 부드러운 대각선 빛 띠가 천천히 떠다니며) 로고 또는 중앙에 작게 이름과 함께 휩쓸고 들어옵니다. - 문제 또는 요청 (약 5초). 시청자가 알아차리는 짧은 줄 (
Still building prospect lists by hand?), 또는 제품 입력으로 바로 이동: 크고 둥근 입력 상자, 비어 있고 플레이스홀더 텍스트가 있으며, 아래에 제안 칩이 있습니다. - 기능 챕터 (3
5개, 각 약 815초). 각각은:- 제목 줄: 짧은 문장 하나, 작게 (1080p에서 약 28px), 평범한 캔버스에 중앙 정렬. 단어별로 타이핑되거나 페이드 인됩니다. 그런 다음 카메라가 그 줄 안으로 접근하여 줄이 프레임 너비의 약 75%를 차지할 때까지 가까워지고, 하나의 핵심 단어 또는 짧은 구문이 강조 표시됩니다: 부드러운 브랜드 색상 상자가 그 뒤를 왼쪽에서 오른쪽으로 휩쓸고 지나갑니다 (
Call the decision maker. Directly.). - UI 순간: 제품의 실제 인터페이스를 깔끔한 벡터 UI(스크린샷 아님)로 재구성하고, 중요한 부분만 크롭하여 크게 보여줍니다. 카메라는 요소가 프레임의 대부분을 채울 만큼 가깝고, 동작을 따라갑니다: 입력 상자에 텍스트 타이핑(카메라는 커서를 따라갑니다;
measureText로 텍스트를 측정하여 위치를 파악), 에이전트 단계가 하나씩 체크되는 것(스피너 → 체크,Found 247 matches), 결과 카드가 먼 카드는 흐릿하게(피사계 심도) 쌓이는 것, 테이블이 행별로 채워지는 것, 커서가 셀 버튼을 클릭하고 값이 나타나는 것, 새 열이 추가되고 각 셀이 값이 나타나기 전에 반짝임(shimmer)으로 "생각"하는 것, 추론 및 출처가 있는 팝오버가 열리는 것. - 뒤로 물러나기(pull-back): 동작 후, 카메라는 잠시 전체 화면을 보여주기 위해 부드럽게 밖으로 나와 시청자가 자신의 위치를 이해할 수 있게 한 후, 다음으로 미끄러져 갑니다.
- 제목 줄: 짧은 문장 하나, 작게 (1080p에서 약 28px), 평범한 캔버스에 중앙 정렬. 단어별로 타이핑되거나 페이드 인됩니다. 그런 다음 카메라가 그 줄 안으로 접근하여 줄이 프레임 너비의 약 75%를 차지할 때까지 가까워지고, 하나의 핵심 단어 또는 짧은 구문이 강조 표시됩니다: 부드러운 브랜드 색상 상자가 그 뒤를 왼쪽에서 오른쪽으로 휩쓸고 지나갑니다 (
- 증명 (선택 사항, 실제 숫자만). 숫자가 카운트 업 되는 문장, 숫자가 강조 표시됨 (
Backed by a database of 300M+ profiles), 미묘한 점선 지구본 또는 그리드 위에. - 통합 (선택 사항).
Built for your existing workflow.가 중앙에 있고, 8~12개의 앱 타일(둥근 사각형, 제공된 경우에만 실제 로고; 통합이 적으면 반복)이 가장자리에서 다른 깊이로 떠서 들어옵니다: 가까운 것은 더 크고 약간 흐릿하며, 먼 것은 작고 선명하며, 모두 시차 효과(parallax)로 떠다닙니다. 여기서는 텍스트가 카메라 접근 대신 자체적으로 확대되어 타일이 프레임 안에 유지됩니다. - 클로저. 브랜드 그라데이션 위에: 사용 사례를 순환하는 회전 강조 단어가 있는 하나의 문장 (
Do all your [prospecting / research / outreach] in Product.), 그 다음, 제품에 실제로 있다면, 사용할 수 있는 또 다른 방법 (예: Claude 커넥터가 있는 제품의 경우Or just ask Claude), 그 다음 키 구문이 강조된 태그라인. - 엔드 카드 (3초). 브랜드 그라데이션 위의 로고 또는 이름, 작은 글씨로 URL 또는 콜 투 액션.
프리미엄하게 만드는 규칙
- 한 번에 하나씩. 화면에 한 줄의 텍스트와 하나의 UI 요소만 동시에 표시합니다. 텍스트와 UI는 거의 프레임을 공유하지 않습니다: 텍스트 장면, 그 다음 UI 장면.
- 카메라가 편집자입니다. 하드 컷이 없습니다. 모든 장면 변경은 카메라 이동(접근, 뒤로 물러나기, 미끄러짐) 또는 일반 캔버스 위의 부드러운 블러-용해입니다. 카메라 이동은 부드러운 이징 (
ease, 0.6~1.2초) 또는 강하게 감쇠된 스프링 (z≥ 0.95)입니다; 바운스는 없습니다. - 실제 UI, 깔끔하게 제작. 제품(또는 웹사이트)에 대해 알고 있는 정보에서 인터페이스를 재구성하세요: 실제 레이아웃, 레이블, 색상, 폰트 및 모서리 반경을 장면에 필요한 만큼 단순화합니다. 그 안의 콘텐츠는 제품에 맞는 신뢰할 수 있는 예제 데이터입니다. 부드러운 그림자, 1px 테두리, 넉넉한 여백.
- 커서: 일반 macOS 스타일 화살표, 부드러운 곡선으로 이동, 클릭하기 전에 잠시 도착하며, 작은 누름 딥(dip)과 클릭된 컨트롤에 부드러운 리플(ripple)이 있습니다. 호버 상태는 변경됩니다.
- 타이포그래피: 알려진 경우 브랜드 폰트; 그렇지 않으면 Inter 또는 Geist. 제목 줄에는 작고 일반 무게 (카메라가 확대하므로 폰트 크기가 아닌 카메라로 커집니다). 큰 텍스트는 좁은 자간.
- 기본 팔레트: 캔버스
#F7F7F8, 텍스트#111114, 보조#8A8A94, UI 표면 흰색에#E7E7EC테두리, 브랜드 강조#2E6BFF, 강조 상자 = 강조 색상의 15~20% 불투명도. 브랜드 그라데이션: 흰색 → 옅은 강조 → 강조, 느린 대각선 실크 밴드로 (CSS 블러가 아닌 캔버스에 그리기). 브랜드 색상이 강조를 대체합니다. - 페이싱: 각 제목 줄은 도착 후 약 2초 유지; UI 순간은 실제 속도로 실행 (초당 약 25자 타이핑), 각 결과 후 0.5초 정지하여 시청자가 읽을 수 있도록 함.
- 금지 사항: UI 뒤의 복잡한 배경, 두 가지 이상의 강조 색상, 바운스 이징, 이모지, 큰 드롭 섀도우, 모든 곳에서의 글래스모피즘, 지어낸 지표 또는 사용후기.
사운드
밝고 부드러운 배경 음악, 100~110 BPM (부드러운 피아노 또는 플럭 코드, 오프닝 후 가벼운 퍼커션 진입, 클로저에서 고조), 조용하고 따뜻함. 사운드 효과는 작게: 타이핑 중 키 틱, 부드러운 클릭, 완료된 단계당 가벼운 "틱", 큰 카메라 이동 시 부드러운 우슈(whoosh), 엔드 카드에서 부드러운 차임. 음악은 잘 만들어진 제품 비디오의 배경처럼 자리 잡아야 하며, 주도적이지 않아야 합니다.
페이지 구축 방법
하나의 자체 포함 HTML 파일 (인라인 CSS 및 JS; 사용자가 제공한 경우에만 이미지). DOM + CSS 변환, SVG 또는 전체 화면 캔버스 중 적합한 것으로 그리세요.
페이지 계약
window.VIDEO = {w, h, duration}및window.seek(t), 시간의 순수 함수: 시간t(초)에 대한 모든 요소를 설정합니다. CSS 전환이나 애니메이션,setTimeout, 이전 프레임의 상태를 전달하지 않습니다. 모든 프레임은 자체적으로, 어떤 순서로든 올바르게 렌더링되어야 합니다.seek내에서 레이아웃 측정(예:offsetLeft,measureText)은 괜찮습니다. 결정론적입니다.- 무작위성(그레인, 파티클, 오디오 노이즈)은 시드 생성기에서 비롯되며,
Math.random을 사용하지 않습니다. - 기록이 필요한 모든 것(움직이는 물체를 뒤따르는 카메라, 시뮬레이션)은 로드 시 한 번 구워집니다: 0에서
duration까지 1/240초 간격으로 단계를 밟고 값을 저장한 후,seek이 보간과 함께 값을 다시 읽습니다. 루프의 경우, 루프가 시작되는 상태에서 시뮬레이션을 시작합니다(스타일의 seam 규칙 참조). - 루프:
seek(t)는t % duration을 사용합니다. seam에 걸쳐 있는 효과(착지 시 스쿼시, 사운드 테일)는 양쪽 끝에서 그리거나 혼합합니다. - URL에
?render가 있는 경우: 컨트롤 없음, 미리보기 배율 없음; 스테이지는 정확히w × h로 왼쪽 상단에 있습니다. 없으면: 스테이지는 창에 맞게 CSS로 배율 조정되고 미리보기 컨트롤이 표시됩니다. - 폰트: 포함시키세요. woff2 파일(Google Fonts 또는 브랜드 폰트)을 다운로드하고 base64
@font-face로 인라인하여 렌더링이 자동으로 대체되지 않도록 합니다. 무게 변형의 경우, 범위가 있는 가변 폰트([email protected])를 사용하세요. - 레이어: 장면 레이어에 투명한 배경을 제공하고 그 뒤에 하나의 스테이지 배경이 기본 색상을 제공하도록 하여, 이후 레이어가 이전 레이어를 실수로 가리지 않도록 합니다. 절대 위치 지정 텍스트는
white-space: nowrap을 얻습니다. - 속도: 큰 CSS
filter: blur()및 큰 흐릿한 그라데이션은 스크린샷을 찍는 데 매우 느립니다. 그라데이션과 글로우는 로드 시 한 번 캔버스에 그리거나(또는 이미지로) 이동시킵니다.
도우미: 이것들을 붙여넣고 모든 것을 기반으로 구축하세요
// 감쇠된 스프링 단계 응답 0 -> 1. w = 속도 (8 느림, 14 보통, 22 빠름), z = 감쇠 (1 = 오버슈트 없음)
function spring(t, w = 14, z = 0.82) {
if (t <= 0) return 0;
if (z >= 1) return 1 - Math.exp(-w * t) * (1 + w * t);
const wd = w * Math.sqrt(1 - z * z);
return 1 - Math.exp(-z * w * t) * (Math.cos(wd * t) + (z * w / wd) * Math.sin(wd * t));
}
// 대상을 여러 번 변경하는 값, 각각으로 스프링: track(start, [[time, value, w?, z?], ...]) -> f(t)
const track = (v0, keys) => t => { let v = v0, p = v0; for (const [tk, val, w, z] of keys) { v += (val - p) * spring(t - tk, w, z); p = val; } return v; };
// 정밀한 이징 키프레임 (카메라 이동에 가장 좋음): kf([[t0, v0], [t1, v1, easeFn?], ...]) -> f(t)
const kf = keys => t => { if (t <= keys[0][0]) return keys[0][1]; for (let i = 1; i < keys.length; i++) { const [a, va] = keys[i - 1], [b, vb, e = ease] = keys[i]; if (t <= b) return lerp(va, vb, e((t - a) / (b - a))); } return keys[keys.length - 1][1]; };
const clamp = (x, a = 0, b = 1) => Math.min(b, Math.max(a, x));
const ease = x => (x = clamp(x), x < .5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2); // easeInOutCubic
const lerp = (a, b, k) => a + (b - a) * k;
const seg = (t, a, b) => clamp((t - a) / (b - a)); // [a, b] 구간에서 t의 0..1 진행도
const rng = s => () => (s = (s + 0x6D2B79F5) | 0, s = Math.imul(s ^ (s >>> 15), 1 | s), s ^= s + Math.imul(s ^ (s >>> 7), 61 | s), ((s ^ (s >>> 14)) >>> 0) / 4294967296);
- 타이핑: 표시 문자열은
full.slice(0, n(t))이며t에서 깜빡이는 커서가 있습니다. 숫자 카운트 업:lerp(a, b, ease(seg(t, …)))형식을 지정합니다. - 카메라는
kf또는track에 의해 구동되는transform: translate() scale() rotate()를 가진 래퍼 요소입니다.
사운드
window.buildAudio(ctx)는 주어진AudioContext또는OfflineAudioContext에서 시간 0부터 전체 사운드트랙(음악 + 효과)을 예약하고, 시각 자료와 동일한 타임라인 숫자를 사용합니다. 오실레이터, 필터링된 노이즈(시드 버퍼에서) 및 엔벨로프로 합성합니다. 사용자가 음악 파일을 제공한 경우fetch+decodeAudioData로 로드하고, 비트 그리드를 템포에 설정하고(측정), 그 위에 효과만 추가합니다.- 미리보기 재생: 첫 번째 재생 시, 사운드트랙을 버퍼로 한 번 렌더링한 다음, 스크러빙된 위치에서 재생합니다. 클록이
seek을 구동합니다:
let buf, ac, src, startAt = 0, offset = 0, playing = false;
async function play() {
ac ??= new AudioContext();
if (!buf) { const off = new OfflineAudioContext(2, Math.ceil(48000 * VIDEO.duration), 48000); await buildAudio(off); buf = await off.startRendering(); }
src = ac.createBufferSource(); src.buffer = buf; src.connect(ac.destination);
src.start(0, offset % VIDEO.duration); startAt = ac.currentTime; playing = true;
}
function pause() { if (!playing) return; offset += ac.currentTime - startAt; src.stop(); playing = false; }
function now() { return playing ? (offset + ac.currentTime - startAt) % VIDEO.duration : offset; }
(function loop() { seek(now()); requestAnimationFrame(loop); })(); // 스크러버가 오프셋을 설정합니다 (일시 정지, 설정, 재생)
- 비트 시트를 스크립트 상단에 주석으로 넣으세요: 순간당 한 행, 시간, 발생하는 일 및 사운드.
3단계: 확인, 렌더링, 전달
작업 폴더에서 한 번 설정
…
[번역을 위해 잘림]