개요
이 스킬은 제품 런칭 비디오(히어로 샷, 기능 콜아웃, 타이밍)를 HyperFrames 구성으로 조립합니다. 새 릴리스에 대해 간결하고 브랜드화할 수 있는 발표 클립이 필요할 때 사용하세요. 제공된 제품 자산에서 최종 MP4를 렌더링합니다.
HyperFrames — 제품 런칭 비디오
LLM이 HTML(그들의 첫 번째 언어)을 작성하고 HyperFrames가 결정론적 MP4로 렌더링하는 HTML 구성을 통해 제품 런칭 비디오를 만듭니다. 에이전트 네이티브 비디오 파이프라인: LLM이 HTML을 작성하고, HyperFrames가 headless Chrome + FFmpeg를 통해 프레임 정확한 비디오를 렌더링합니다.
사용 시기
- 사용자가 URL, 브리프 또는 스크립트에서 제품 런칭 비디오를 원하는 경우
- 사용자가 제품의 자체 비주얼을 활용한 사이트 투어/쇼케이스를 원하는 경우
- 사용자가 키네틱 캡션과 브랜딩이 있는 소셜 클립(TikTok/Reels/Shorts)을 원하는 경우
- 사용자가 애니메이션 오버레이와 음악이 있는 마케팅/프로모션 비디오를 원하는 경우
- 사용자가 제품 URL이나 설명과 함께 "나를 위한 비디오를 만들어줘"라고 말하는 경우
사용하지 말아야 할 경우
- 사용자가 실제 인물 / UGC / 스튜디오 콘텐츠를 원하는 경우 (카메라 필요, HTML 아님)
- 사용자가 라이브 스트리밍 / 라이브 커머스를 원하는 경우 (RTMP 수집 필요)
- 사용자가 토크쇼 스타일 인터뷰를 원하는 경우 (
hyperframes-embedded-captions또는hyperframes-talking-head-recut사용) - 사용자가 제품/URL 없이 순수 설명형 비디오를 원하는 경우 (
hyperframes-faceless-explainer사용) - 사용자가 프레젠테이션/슬라이드를 원하는 경우 (
hyperframes-slideshow사용)
워크플로우
0 · 프로젝트 부트스트래핑
npx hyperframes init my-launch-video
cd my-launch-video
이 명령어는 index.html, package.json 및 HyperFrames CLI가 구성된 프로젝트 스캐폴드를 생성합니다.
1 · 비디오 계획
- 입력: 제품 URL, 브리프 또는 스크립트
- 출력: 타이밍이 포함된 3-6개 장면 스토리보드 (총 30-90초 최적)
- 예산: 제목 ≤2초, 아웃트로 ≤3초, 중간 장면 각각 ≈8-12초
- 디자인 언어 선택:
hyperframes.heygen.com/design에서 frame.md 템플릿 탐색
2 · 구성 HTML 작성
구성 계약:
<!doctype html>
<html lang="en">
<body>
<div
id="main"
data-composition-id="intro"
data-start="0"
data-duration="15"
data-width="1080"
data-height="1920"
data-fps="30"
>
<div
class="clip"
data-start="0"
data-duration="5"
data-track-index="0"
>
<!-- 장면 콘텐츠 -->
</div>
</div>
</body>
</html>
주요 속성:
data-composition-id: 구성의 고유 IDdata-start/data-duration: 초 단위 타이밍data-width/data-height: 뷰포트 크기 (9:16의 경우 1080×1920)data-fps: 프레임 레이트 (표준 30)class="clip": 시간이 지정된 요소 표시data-track-index: 레이어 순서 (높을수록 위에 위치)
3 · seekable 애니메이션 연결
GSAP(권장), CSS 키프레임 또는 WAAPI를 사용하세요. 모든 애니메이션은 seekable(결정론적 — 동일한 시간에 동일한 프레임, 모든 렌더링에서 동일)해야 합니다.
GSAP 패턴 (권장):
const tl = gsap.timeline({ paused: true });
tl.to("#title", { opacity: 1, y: 0, duration: 0.8, ease: "power4.out" }, 0.5);
tl.to("#image", { scale: 1, opacity: 1, duration: 1.2, ease: "power3.out" }, 1.0);
window.__timelines = { main: tl };
CSS 키프레임 패턴:
@keyframes fadeInUp {
from { transform: translateY(40px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.animate-in {
animation: fadeInUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
4 · 미디어 추가
- 이미지:
public/디렉토리에 다운로드하고staticFile()또는 상대 경로로 참조 - 비디오 배경:
assets/에 배치하고data-loop로 반복 - 오디오/BGM:
<audio data-start="0" data-duration="15" src="./bgm.mp3">태그로 추가 - 내레이션: TTS로 생성하고 캡션을 단어 타임스탬프에 정렬
5 · 린트 및 확인
npx hyperframes check # 구성 계약 검증
npx hyperframes lint # 일반적인 오류 확인
계속 진행하기 전에 모든 오류를 수정하세요. 경고는 허용되지만 검토해야 합니다.
6 · 미리보기
npx hyperframes preview # HMR로 Hyperframes Studio 열기
원시 구성 페이지에서 __player.seek(time)를 사용하여 3-4개 지점을 샘플 점검하세요. 확인할 사항:
- 애니메이션이 올바른 시간에 트리거되는지
- 컷에서 흰색 플래시가 없는지 (불투명 스테이지 바탕)
- 캡션이 보이고 읽을 수 있는지
- 오디오 레벨이 균형 잡혀 있는지
7 · 렌더링
npx hyperframes render --output launch-video.mp4
출력 확인:
ffmpeg -ss 3 -i launch-video.mp4 -frames:v 1 frame-3s.png # 캡션 확인
ffmpeg -ss 15 -i launch-video.mp4 -frames:v 1 frame-15s.png # 장면 확인
반합리화 표
| 합리화 | 현실 |
|---|---|
| "그냥 비디오 편집기를 사용할게요" | GUI 편집기는 에이전트에 적합하지 않습니다. HTML은 LLM이 가장 잘 작성하는 것입니다. |
| "린트 단계는 건너뛸게요" | 린트는 렌더링을 망가뜨리는 구성 계약 오류를 잡아냅니다. |
| "Remotion을 사용할게요" | Remotion은 React 이해가 필요합니다. HTML이 에이전트에게 더 간단합니다. |
| "시간을 채우기 위해 유휴 애니메이션을 추가할게요" | 유휴 움직임은 금지됩니다 — 모든 단계는 기능을 수행해야 합니다 (hyperframes-cut-the-curve 참조) |
| "캡션을 위해 콘텐츠를 42%에 중앙 정렬할게요" | 캡션은 오버레이입니다 — 진정한 중앙에 정렬하세요 (y = H/2) |
| "장면 사이에 크로스페이드를 사용할게요" | 크로스페이드는 캐리어가 없습니다 — 기본 경계에는 cut-the-curve를 사용하세요 |
| "장면 없이 하나의 큰 HTML 파일을 작성할게요" | 장면은 구성의 단위입니다 — 각 장면은 자체 clip 래퍼를 가져야 합니다 |
| "미리보기를 건너뛰고 바로 렌더링할게요" | 미리보기는 렌더링 시간을 낭비하는 타이밍 오류를 잡아냅니다 |
코드 예제
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #0a0a0a; }
#main {
position: relative;
width: 1080px;
height: 1920px;
overflow: hidden;
}
.scene {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.5s ease;
}
.scene.active { opacity: 1; }
.hook-bg {
background: linear-gradient(135deg, #ff6b35 0%, #f7931e 100%);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 80px;
text-align: center;
color: white;
font-family: system-ui, sans-serif;
}
.hook-text {
font-size: 72px;
font-weight: 800;
line-height: 1.1;
transform: translateY(40px);
opacity: 0;
}
.animate-in {
animation: fadeInUp 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes fadeInUp {
from { transform: translateY(40px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
</style>
</head>
<body>
<div
id="main"
data-composition-id="product-ad"
data-start="0"
data-duration="15"
data-width="1080"
data-height="1920"
data-fps="30"
>
<div class="scene hook-bg" data-start="0" data-duration="5" data-track-index="0">
<h1 class="hook-text animate-in" data-start="0.5" data-duration="4">
Product Name
</h1>
</div>
</div>
<script>
// IntersectionObserver 또는 수동 타이밍을 통한 장면 활성화
const scenes = document.querySelectorAll('.scene');
scenes.forEach(scene => {
const start = parseFloat(scene.dataset.start);
const duration = parseFloat(scene.dataset.duration);
setTimeout(() => scene.classList.add('active'), start * 1000);
setTimeout(() => scene.classList.remove('active'), (start + duration) * 1000);
});
</script>
</body>
</html>
검증 항목
- 구성이
npx hyperframes check를 0개의 오류로 통과함 - 모든 장면에
data-start,data-duration,data-track-index가 있음 - 애니메이션이 seekable함 (결정론적이며, 벽시계에 의존하지 않음)
- 미리보기가 3개 이상의 샘플 점검 지점에서 올바른 타이밍을 보여줌
- 렌더링된 MP4에 흰색 플래시, 정지 프레임 또는 누락된 캡션이 없음
- 오디오 레벨이 균형 잡혀 있음 (필요 시 내레이션 carve 적용)
- 출력 해상도가 대상과 일치함 (9:16의 경우 1080×1920, 16:9의 경우 1920×1080)