Communitygithub.com

skeletorflet/opencode-supreme-setup

HyperFrames HTML을 사용하여 비디오 합성, 애니메이션, 타이틀 카드, 오버레이, 자막, 음성 해설, 오디오 반응형 비주얼 및 장면 전환을 생성합니다. HTML 기반 비디오 콘텐츠 제작, 오디오와 동기화된 자막 추가, TTS 내레이션, 오디오 반응형 애니메이션(비트 싱크, 글로우, 펄스), 애니메이션 텍스트 강조(마커 스윕, 손그림 원, 버스트 라인, 스크리블, 스케치아웃), 장면 전환(크로스페이드, 와이프, 리빌, 셰이더 전환)이 필요할 때 사용합니다. 합성 제작, 타이밍, 미디어 및 전체 비디오 제작 워크플로우를 다룹니다. CLI 명령어(init, lint, preview, render, transcribe, tts)는 hyperframes-cli 스킬을 참조하세요.

opencode-supreme-setup란 무엇인가요?

이 스킬은 HTML을 비디오 제작의 진실 공급원(source of truth)으로 활용하는 HyperFrames 프레임워크를 기반으로, 완전한 비디오 합성 및 애니메이션 워크플로우를 제공합니다. Claude Code, Cursor, Codex와 같은 AI 에이전트 환경에서 실행되도록 설계되었으며, 사용자가 비디오 콘텐츠, 자막, 음성 해설, 오디오 반응형 비주얼, 장면 전환 등을 HTML로 제작할 수 있게 합니다. 특히 Open Design(OD) 프로젝트 내에서의 효율적인 렌더링을 지원하여, 숨겨진 캐시 디렉토리를 통해 소스 파일의 혼란을 방지하고 npx 스캐폴드 + 신속한 편집 워크플로우를 통해 제작 시간을 단축합니다. SKILL.md 문서는 스캐폴드 기반의 빠른 경로, 레이아웃 우선 애니메이션 접근법, 시각적 아이덴티티 게이트, 데이터 속성, 합성 구조 및 다양한 템플릿(타이틀 카드, 오버레이, 자막, 오디오 반응형, 장면 전환)을 상세히 설명하여, AI 에이전트가 일관되고 효율적으로 고품질 비디오를 제작할 수 있도록 안내합니다.

지원 대상✓Claude Code~Codex CLI~Cursor✓OpenCode
npx skills add https://github.com/skeletorflet/opencode-supreme-setup/tree/HEAD/.claude/skills/hyperframes

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

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

문서

HyperFrames

HTML이 비디오의 진실 공급원(source of truth)입니다. 합성(composition)은 타이밍을 위한 data-* 속성, 애니메이션을 위한 GSAP 타임라인, 그리고 모양을 위한 CSS가 포함된 HTML 파일입니다. 프레임워크는 클립 가시성, 미디어 재생 및 타임라인 동기화를 처리합니다.

Open Design 통합 (이 표면의 핵심)

이 스킬이 Open Design 내에서 실행될 때(즉, $OD_PROJECT_DIR이 설정된 경우), 출력 흐름은 고정됩니다: 렌더링된 .mp4 파일만 프로젝트 루트에 위치해야 합니다. 합성 소스 파일(hyperframes.json, meta.json, index.html, assets)은 사용자의 FileViewer 또는 채팅의 "생성된 파일" 칩을 어지럽히지 않도록 숨겨진 캐시 디렉토리 안에 있어야 합니다.

OD 내부의 렌더링 워크플로우 — 빠른 경로:

대부분의 OD 요청("테스트 비디오", "5초 제품 소개", "데모 클립")에 대해 합성 HTML을 처음부터 작성하지 마십시오. HyperFrames의 내장 스캐폴드를 사용하고 프롬프트가 실제로 변경하는 내용만 편집하십시오. "처음부터 작성" 경로는 수 분의 모델 출력과 조용한 채팅 도구 시간을 소비합니다. 스캐폴드 경로는 단 몇 초면 됩니다.

# 1. 숨겨진 캐시 슬롯 선택. 점(dotfile) 접두사 → OD의 프로젝트 파일
#    목록에서 제외되므로 소스 파일이 채팅을 어지럽히지 않습니다.
COMP_REL=".hyperframes-cache/$(date +%s)-$(openssl rand -hex 2)"
COMP="$OD_PROJECT_DIR/$COMP_REL"

# 2. 즉시 렌더링 가능한 스캐폴드 가져오기 (hyperframes.json,
#    meta.json, GSAP CDN + 등록된 window.__timelines.main이 있는
#    index.html). 이 작업은 쉘에서 실행됩니다 — 순수 파일 복사,
#    Chrome 불필요, npx 캐시 외 네트워크 불필요.
npx hyperframes init "$COMP" --example blank --skip-skills --non-interactive

# 3. $COMP/index.html 만 편집 — 루트의 `data-duration` 변경
#    (기본 길이가 아닌 경우), <style>의 플레이스홀더 팔레트 교체,
#    텍스트/이미지를 위한 1~3개의 클립 <div> 추가, 기존
#    `window.__timelines["main"] = gsap.timeline({paused:true})` 블록 내에
#    일치하는 GSAP 트윈 추가. 편집을 최소화하십시오. 스캐폴드는 이미
#    유효한 HF입니다.

# 4. OD 데몬을 통해 렌더링 디스패치. 이 쉘에서 `npx hyperframes
#    render`를 실행하지 마십시오 — 데몬이 샌드박스 없는 프로세스에서
#    대신 실행합니다. (많은 에이전트 CLI, 특히 Claude Code는 Bash를
#    macOS sandbox-exec으로 감싸는데, 이 아래에서 puppeteer의 Chrome
#    하위 프로세스가 프레임 캡처 도중 부분적으로 멈춥니다. 데몬
#    프로세스는 샌드박스가 없으므로 렌더링이 안정적으로 완료됩니다.)
#
#    디스패처는 ~1초 내에 {taskId}를 반환합니다. 렌더링이 완료될
#    때까지 "$OD_NODE_BIN" "$OD_BIN" media wait <taskId> 호출을
#    반복합니다. 각 호출은 최대 25초 동안 롱 폴링하며(쉘 도구의
#    기본 30초 제한 미만), 종료 코드 0/2/5로 완료/실행 중/실패를
#    알립니다.
out=$("$OD_NODE_BIN" "$OD_BIN" media generate \
  --project "$OD_PROJECT_ID" \
  --surface video \
  --model hyperframes-html \
  --output "<descriptive-name>.mp4" \
  --composition-dir "$COMP_REL")
ec=$?
task_id=$(printf '%s\n' "$out" | tail -1 | jq -r '.taskId // empty')
since=$(printf '%s\n' "$out" | tail -1 | jq -r '.nextSince // 0')
while [ "$ec" -eq 2 ] && [ -n "$task_id" ]; do
  out=$("$OD_NODE_BIN" "$OD_BIN" media wait "$task_id" --since "$since")
  ec=$?
  since=$(printf '%s\n' "$out" | tail -1 | jq -r '.nextSince // '"$since")
done
[ "$ec" -ne 0 ] && { echo "$out" >&2; exit "$ec"; }

각 generate 및 각 wait 호출은 최대 약 25초 동안 지속되므로 에이전트 쉘 도구의 기본 ~30초 제한이 절대 발생하지 않습니다. HF의 진행 라인(프레임 N/M 캡처 중)은 루프 전체에 걸쳐 stderr로 실시간 스트리밍됩니다. 렌더링이 완료되면 마지막 stdout 라인은 {"file": { "name": "<output>", "size": …, "kind": "video", … }}입니다 — 응답에서 file.name을 인용하여 사용자에게 무엇이 생성되었는지 알려주십시오.

OD 내부의 시각적 아이덴티티 게이트 건너뛰기. 아래 "접근 방식" 섹션의 HARD-GATE 섹션은 모든 합성을 작성하기 전에 DESIGN.md / visual-style.md를 읽거나 중단하고 3가지 분위기 질문을 하라고 지시합니다. 해당 게이트는 독립형 HF 프로젝트를 위한 것입니다. OD 프로젝트에는 이미 자체 디자인 시스템 레이어가 있습니다 — 사용자는 프로젝트 생성 시 시각적 방향을 선택했습니다. OD 테스트 렌더링의 경우 기본값: 어두운 캔버스(#0b0b0f), 따뜻한 악센트 하나(#ffb76b), 차가운 악센트 하나(#7da4ff), 절제된 움직임. 사용자의 프롬프트가 주제조차 선택하기에 너무 모호한 경우에만(매우 드물게) 스타일 입력을 요청하십시오.

스캐폴드를 건너뛰고 처음부터 작성해야 하는 경우: 사용자가 빈 템플릿이 분명히 제공할 수 없는 것을 명시적으로 요청하는 경우에만 해당합니다(예: 다중 합성 타임라인, 오디오 반응형 오버레이, 이미 생성한 TTS 트랙과 동기화된 자막). 그 외 모든 경우에는 init + 편집이 기본 경로입니다.

자체 쉘에서 여전히 실행할 수 있는 더 가벼운 HF 하위 명령(Chrome을 실행할 필요 없음):

  • npx hyperframes lint "$COMP" — 디스패치 전 합성 검증
  • npx hyperframes transcribe <audio> — 자막 생성
  • npx hyperframes tts <text> — 내레이션 생성

데몬 디스패치는 render/inspect/preview(Chrome이 필요한 모든 것)로 예약하십시오.

"$OD_NODE_BIN" "$OD_BIN" media generate --model hyperframes-html를 호출하지 마십시오 — 해당 디스패처 경로는 의도적으로 400(AGENT_RENDERED)을 반환합니다. HyperFrames는 npx를 통해 사용자가 직접 렌더링합니다.

프로젝트 루트에 hyperframes.json / meta.json / index.html을 드롭하지 마십시오. OD의 파일 목록은 재귀적으로 스캔하므로 사용자는 채팅에 세 개의 관련 없는 파일이 나타나는 것을 보게 됩니다.

render 이외의 CLI 옵션(lint, preview, transcribe, tts, inspect, benchmark)의 경우, 작업이 필요할 때 쉘 도구에서 직접 호출하십시오(예: 합성에서 참조하기 전에 캐시에 TTS 오디오 생성).

접근 방식

HTML을 작성하기 전에 높은 수준에서 생각하십시오:

  1. 무엇 — 시청자는 무엇을 경험해야 합니까? 내러티브 아크, 핵심 순간 및 감정적 비트를 식별하십시오.
  2. 구조 — 몇 개의 합성, 어떤 것이 하위 합성인지 vs 인라인인지, 어떤 트랙이 무엇을 전달하는지(비디오, 오디오, 오버레이, 자막).
  3. 타이밍 — 어떤 클립이 지속 시간을 결정하는지, 전환이 어디에 위치하는지, 페이싱은 어떠한지.
  4. 레이아웃 — 먼저 최종 상태를 구축하십시오. 아래 "애니메이션 전 레이아웃"을 참조하십시오.
  5. 애니메이트 — 그런 다음 아래 규칙을 사용하여 모션을 추가하십시오.

작은 편집(색상 수정, 타이밍 조정, 한 요소 추가)의 경우 바로 규칙으로 건너뛰십시오.

시각적 아이덴티티 게이트

다음 순서로 확인하십시오:

  1. 프로젝트에 DESIGN.md가 있습니까? → 읽으십시오. 정확한 색상, 글꼴, 모션 규칙 및 "하지 말아야 할 것" 제약 조건을 사용하십시오.
  2. visual-style.md가 있습니까? → 읽으십시오. style_prompt_full 및 구조화된 필드를 적용하십시오. (참고: visual-style.md는 프로젝트별 파일입니다. visual-styles.md는 8개의 명명된 프리셋이 있는 스타일 라이브러리입니다 — 다른 파일입니다.)
  3. 사용자가 스타일을 지정했습니까? (예: "Swiss Pulse", "어둡고 기술적인", "럭셔리 브랜드") → 8개의 명명된 프리셋에 대해 visual-styles.md를 읽으십시오. 다음을 포함하는 최소한의 DESIGN.md를 생성하십시오: ## Style Prompt (한 문단), ## Colors (역할이 포함된 3-5개의 16진수 값), ## Typography (1-2개의 글꼴 패밀리), ## What NOT to Do (3-5개의 안티 패턴).
  4. 위 중 어느 것도 해당 없습니까? → HTML을 작성하기 전에 3가지 질문을 하십시오:
    • 분위기는 무엇입니까? (폭발적 / 영화적 / 유동적 / 기술적 / 혼란스러운 / 따뜻함)
    • 밝은 캔버스인가요 어두운 캔버스인가요?
    • 특정 브랜드 색상, 글꼴 또는 시각적 참조가 있습니까? 그런 다음 답변에서 최소한의 DESIGN.md를 생성하십시오.

모든 합성은 팔레트와 타이포그래피를 DESIGN.md, visual-style.md 또는 명시적인 사용자 지시로 추적해야 합니다. #333, #3b82f6 또는 Roboto에 손을 대고 있다면 — 이 단계를 건너뛴 것입니다.

모션 기본값, 크기 조정, 진입 패턴 및 이징에 대해서는 house-style.md를 따르십시오. 하우스 스타일은 사물이 HOW 움직이는지 처리합니다. DESIGN.md는 사물이 WHAT처럼 보이는지 처리합니다.

애니메이션 전 레이아웃

모든 요소를 가장 잘 보이는 순간 — 완전히 진입하고, 올바르게 배치되고, 아직 종료되지 않은 프레임 — 에 위치시켜야 할 위치에 배치하십시오. 이것을 정적 HTML+CSS로 먼저 작성하십시오. 아직 GSAP는 사용하지 마십시오.

이것이 중요한 이유: 애니메이션 시작 상태(화면 밖, 0으로 축소, 불투명도 0)에서 요소를 배치하고 도착해야 할 위치로 트윈하면 최종 레이아웃을 추측하는 것입니다. 겹침은 비디오가 렌더링될 때까지 보이지 않습니다. 먼저 최종 상태를 구축하면 모션을 추가하기 전에 레이아웃 문제를 보고 수정할 수 있습니다.

프로세스

  1. 각 장면의 히어로 프레임을 식별하십시오 — 가장 많은 요소가 동시에 보이는 순간. 이것이 구축할 레이아웃입니다.
  2. 해당 프레임에 대한 정적 CSS를 작성하십시오. .scene-content 컨테이너는 width: 100%; height: 100%; padding: Npx; 및 display: flex; flex-direction: column; gap: Npx; box-sizing: border-box를 사용하여 전체 장면을 채워야 합니다. 패딩을 사용하여 콘텐츠를 안쪽으로 밀어 넣으십시오 — 콘텐츠 컨테이너에 position: absolute; top: Npx를 절대 사용하지 마십시오. 절대 위치 콘텐츠 컨테이너는 콘텐츠가 남은 공간보다 높을 때 넘칩니다. position: absolute는 장식용으로만 예약하십시오.
  3. gsap.from()으로 진입 추가 — 화면 밖/보이지 않음에서 CSS 위치로 애니메이트하십시오. CSS 위치가 기본 진실입니다. 트윈은 그곳에 도달하는 여정을 설명합니다.
  4. gsap.to()로 종료 추가 — CSS 위치에서 화면 밖/보이지 않음으로 애니메이트하십시오.

예시

/* scene-content가 장면을 채우고, 패딩이 콘텐츠를 배치합니다 */
.scene-content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 120px 160px;
  gap: 24px;
  box-sizing: border-box;
}
.title {
  font-size: 120px;
}
.subtitle {
  font-size: 42px;
}
/* 컨테이너는 모든 장면 크기(1920x1080, 1080x1920 등)를 채웁니다.
   패딩이 콘텐츠를 배치합니다. Flex + gap이 간격을 처리합니다. */

잘못된 예 — 하드코딩된 치수와 절대 위치 지정:

.scene-content {
  position: absolute;
  top: 200px;
  left: 160px;
  width: 1920px;
  height: 1080px;
  display: flex; /* ... */
}
// 3단계: 해당 위치로 애니메이션 진입
tl.from(".title", { y: 60, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
tl.from(".subtitle", { y: 40, opacity: 0, duration: 0.5, ease: "power3.out" }, 0.2);
tl.from(".logo", { scale: 0.8, opacity: 0, duration: 0.4, ease: "power2.out" }, 0.3);

// 4단계: 해당 위치에서 애니메이션 종료
tl.to(".title", { y: -40, opacity: 0, duration: 0.4, ease: "power2.in" }, 3);
tl.to(".subtitle", { y: -30, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.1);
tl.to(".logo", { scale: 0.9, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.2);

요소가 시간에 따라 공간을 공유할 때

요소 A가 동일한 영역에서 요소 B가 진입하기 전에 종료되면, 둘 다 각각의 히어로 프레임에 대해 올바른 CSS 위치를 가져야 합니다. 타임라인 순서는 시각적으로 공존하지 않음을 보장합니다 — 그러나 레이아웃 단계를 건너뛰면 타이밍 오류로 인해 실수로 겹치는 경우를 발견하지 못할 수 있습니다.

의도적인 겹침으로 간주되는 것

계층화된 효과(텍스트 뒤의 글로우, 그림자 요소, 배경 패턴) 및 z-스택 디자인(카드 스택, 깊이 레이어)은 의도적입니다. 레이아웃 단계는 의도하지 않은 겹침(두 개의 제목이 서로 위에 겹쳐짐, 통계가 레이블을 덮음, 콘텐츠가 프레임 밖으로 나감)을 잡기 위한 것입니다.

데이터 속성

모든 클립

속성필수값
id예고유 식별자
data-start예초 또는 클립 ID 참조 ("el-1", "intro + 2")
data-durationimg/div/합성에 필수초. 비디오/오디오는 미디어 지속 시간을 기본값으로 사용합니다.
data-track-index예정수. 동일한 트랙의 클립은 겹칠 수 없습니다.
data-media-start아니요소스로의 트림 오프셋 (초)
data-volume아니요0-1 (기본값 1)

data-track-index는 시각적 계층에 영향을 주지 않습니다 — CSS z-index를 사용하십시오.

합성 클립

속성필수값
data-composition-id예고유 합성 ID
data-start예시작 시간 (루트 합성: "0" 사용)
data-duration예GSAP 타임라인 지속 시간보다 우선합니다
data-width / data-height예픽셀 치수 (1920x1080 또는 1080x1920)
data-composition-src아니요외부 HTML 파일 경로

합성 구조

data-composition-src를 통해 로드된 하위 합성은 <template> 래퍼를 사용합니다. 독립형 합성(메인 index.html)은 <template>을 사용하지 않습니다 — data-composition-id div를 <body>에 직접 배치합니다. 독립형 파일에서 <template>을 사용하면 브라우저에서 모든 콘텐츠가 숨겨지고 렌더링이 중단됩니다.

하위 합성 구조:

<template id="my-comp-template">
  <div data-composition-id="my-comp" data-width="1920" data-height="1080">
    <!-- content -->
    <style>
      [data-composition-id="my-comp"] {
        /* 범위가 지정된 스타일 */
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
    <script>
      window.__timelines = window.__timelines || {};
      const tl = gsap.timeline({ paused: true });
      // 트윈...
      window.__timelines["my-comp"] = tl;
    </script>
  </div>
</template>

루트에서 로드: <div id="el-1" data-composition-id="my-comp" data-composition-src="compositions/my-comp.html" data-start="0" data-duration="5"></div>

루트 합성 구조 (메인 index.html)

<!-- 템플릿 없음! data-composition-id가 body의 직접 자식입니다 -->
<div data-composition-id="root" data-width="1920" data-height="1080" data-duration="10">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
  <style>
    /* 글로벌 스타일 */
    body { margin: 0; overflow: hidden; background: #0b0b0f; width: 100%; height: 100%; }
    [data-composition-id="root"] {
      position: relative;
      width: 1920px; height: 1080px; overflow: hidden;
    }
    .scene { position: absolute; inset: 0; }
  </style>
  <div class="scene">
    <div class="scene-content">
      <h1 class="title">안녕하세요</h1>
      <p class="subtitle">HyperFrames 세계에 오신 것을 환영합니다</p>
    </div>
  </div>
  <script>
    window.__timelines = window.__timelines || {};
    const tl = gsap.timeline({ paused: true });
    tl.from(".title", { y: 60, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
    tl.from(".subtitle", { y: 40, opacity: 0, duration: 0.5, ease: "power3.out" }, 0.2);
    tl.to(".scene", { opacity: 0, duration: 0.5, ease: "power2.in" }, 9.5);
    window.__timelines["root"] = tl;
  </script>
</div>

자주 사용되는 합성 패턴에 대해서는 아래 템플릿을 참조하십시오.

합성 템플릿

이 템플릿은 일반적인 요청을 충족합니다. 필요에 따라 복사, 수정 및 조합하십시오. 더 복잡한 효과의 경우 여러 템플릿을 쌓거나 하위 합성을 사용하십시오.

1. 정적 타이틀 카드

정적 텍스트(애니메이션 없음)가 있는 단일 타이틀 카드. 가장 간단한 템플릿입니다.

<div data-composition-id="title-card" data-width="1920" data-height="1080" data-duration="5">
  <style>
    [data-composition-id="title-card"] .scene-content {
      display: flex; flex-direction: column; justify-content: center; align-items: center;
      width: 100%; height: 100%; padding: 120px 160px; gap: 24px; box-sizing: border-box;
      background: linear-gradient(135deg, #0b0b0f 0%, #1a1a2e 100%);
    }
    [data-composition-id="title-card"] .title { font-size: 120px; color: #ffffff; text-align: center; margin: 0; }
    [data-composition-id="title-card"] .subtitle { font-size: 42px; color: #ffb76b; text-align: center; margin: 0; }
  </style>
  <div class="scene-content">
    <h1 class="title">HyperFrames</h1>
    <p class="subtitle">HTML로 구동되는 비디오</p>
  </div>
</div>

2. 베이직 텍스트 애니메이션

텍스트가 위로 올라오면서 페이드 인되는 애니메이션이 있는 타이틀 카드.

<div data-composition-id="anim-title" data-width="1920" data-height="1080" data-duration="5">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
  <style>
    [data-composition-id="anim-title"] .scene-content {
      display: flex; flex-direction: column; justify-content: center;
      width: 100%; height: 100%; padding: 120px 160px; gap: 24px; box-sizing: border-box;
      background: radial-gradient(circle at 50% 50%, #1a1a2e, #0b0b0f);
    }
    [data-composition-id="anim-title"] .title { font-size: 120px; color: #ffffff; text-align: center; margin: 0; }
    [data-composition-id="anim-title"] .subtitle { font-size: 42px; color: #7da4ff; text-align: center; margin: 0; }
  </style>
  <div class="scene-content">
    <h1 class="title">오디오 반응형</h1>
    <p class="subtitle">비트에 맞춰 움직이는 비주얼</p>
  </div>
  <script>
    window.__timelines = window.__timelines || {};
    const tl = gsap.timeline({ paused: true });
    tl.from(".title", { y: 80, opacity: 0, duration: 1, ease: "power4.out" }, 0);
    tl.from(".subtitle", { y: 50, opacity: 0, duration: 0.8, ease: "power3.out" }, 0.5);
    window.__timelines["anim-title"] = tl;
  </script>
</div>

3. 오디오 반응형 배경

오디오 데이터(주파수 대역)에 반응하여 배경 요소가 확장/수축됩니다. 실제로는 외부 오디오 분석이 필요하지만 이 템플릿은 애니메이션을 보여줍니다.

<div data-composition-id="audio-bg" data-width="1920" data-height="1080" data-duration="10">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
  <style>
    [data-composition-id="audio-bg"] .scene { position: relative; width: 100%; height: 100%; overflow: hidden; background: #0b0b0f; }
    [data-composition-id="audio-bg"] .bar { position: absolute; bottom: 0; width: 20px; background: #ffb76b; border-radius: 10px 10px 0 0; }
    [data-composition-id="audio-bg"] .content {
      position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; align-items: center;
    }
    [data-composition-id="audio-bg"] .title { font-size: 80px; color: #ffffff; margin: 0; z-index: 1; }
  </style>
  <div class="scene">
    <div id="bars-container" style="position: absolute; bottom: 0; left: 0; right: 0; height: 300px; display: flex; gap: 10px; justify-content: center;">
      <div class="bar" style="height: 50px; left: 100px;"></div>
      <div class="bar" style="height: 100px;"></div>
      <div class="bar" style="height: 150px;"></div>
      <div class="bar" style="height: 200px;"></div>
      <div class="bar" style="height: 120px;"></div>
      <div class="bar" style="height: 180px;"></div>
      <div class="bar" style="height: 80px;"></div>
      <div class="bar" style="height: 220px;"></div>
    </div>
    <div class="content">
      <h1 class="title">비트에 맞춰</h1>
    </div>
  </div>
  <script>
    window.__timelines = window.__timelines || {};
    const tl = gsap.timeline({ paused: true, repeat: -1, yoyo: true });
    tl.to(".bar", { height: "+=50", duration: 0.5, ease: "power1.inOut", stagger: 0.1 });
    window.__timelines["audio-bg"] = tl;
  </script>
</div>

4. 텍스트 오버레이

이미지/비디오 위에 반투명 배경이 있는 텍스트.

<div data-composition-id="overlay-text" data-width="1920" data-height="1080" data-duration="5">
  <style>
    [data-composition-id="overlay-text"] {
      position: relative; width: 100%; height: 100%; overflow: hidden;
    }
    /* 배경 (비디오/이미지로 대체) */
    [data-composition-id="overlay-text"] .bg { position: absolute; inset: 0; background: linear-gradient(45deg, #2d1b4e, #1a1a2e); }
    /* 오버레이 */
    [data-composition-id="overlay-text"] .overlay {
      position: absolute; inset: 0;
      background: linear-gradient(to top, rgba(0,0,0,0.8) 0%, transparent 50%);
      display: flex; flex-direction: column; justify-content: flex-end;
      padding: 80px; box-sizing: border-box;
    }
    [data-composition-id="overlay-text"] .title { font-size: 72px; color: #ffffff; margin: 0; }
    [data-composition-id="overlay-text"] .subtitle { font-size: 32px; color: #cccccc; margin: 0; }
  </style>
  <div class="bg"></div>
  <div class="overlay">
    <h1 class="title">장면 제목</h1>
    <p class="subtitle">더 많은 정보를 위한 부제목</p>
  </div>
</div>

5. 크로스페이드 전환

오디오 트랙이 없는 두 장면 간의 기본 페이드.

<div data-composition-id="crossfade" data-width="1920" data-height="1080" data-duration="5">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
  <style>
    [data-composition-id="crossfade"] .scene { position: absolute; inset: 0; width: 100%; height: 100%; }
    [data-composition-id="crossfade"] .scene-a { background: #1a1a2e; display: flex; justify-content: center; align-items: center; }
    [data-composition-id="crossfade"] .scene-b { background: #2d1b4e; display: flex; justify-content: center; align-items: center; opacity: 0; }
    [data-composition-id="crossfade"] .label { font-size: 60px; color: #ffffff; }
  </style>
  <div class="scene scene-a"><span class="label">장면 A</span></div>
  <div class="scene scene-b"><span class="label">장면 B</span></div>
  <script>
    window.__timelines = window.__timelines || {};
    const tl = gsap.timeline({ paused: true });
    // 2초 후 장면 B가 페이드 인
    tl.to(".scene-b", { opacity: 1, duration: 1, ease: "power2.inOut" }, 2);
    window.__timelines["crossfade"] = tl;
  </script>
</div>

6. 와이프 전환

장면이 오른쪽에서 왼쪽으로 슬라이드되어 이전 장면을 덮습니다.

<div data-composition-id="wipe" data-width="1920" data-height="1080" data-duration="5">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
  <style>
    [data-composition-id="wipe"] .scene { position: absolute; inset: 0; width: 100%; height: 100%; }
    [data-composition-id="wipe"] .scene-a { background: #1a1a2e; display: flex; justify-content: center; align-items: center; z-index: 1; }
    [data-composition-id="wipe"] .scene-b { background: #2d1b4e; display: flex; justify-content: center; align-items: center; z-index: 2; left: 100%; }
    [data-composition-id="wipe"] .label { font-size: 60px; color: #ffffff; }
  </style>
  <div class="scene scene-a"><span class="label">장면 A</span></div>
  <div class="scene scene-b"><span class="label">장면 B</span></div>
  <script>
    window.__timelines = window.__timelines || {};
    const tl = gsap.timeline({ paused: true });
    tl.to(".scene-b", { left: "0%", duration: 1, ease: "power3.inOut" }, 2);
    window.__timelines["wipe"] = tl;
  </script>
</div>

7. 캡션 (자막)

단순한 하단 타사(third) 텍스트. 일반적으로 오디오/비디오와 함께 사용됩니다.

<div data-composition-id="captions" data-width="1920" data-height="1080" data-duration="10">
  <style>
    [data-composition-id="captions"] {
      position: relative; width: 100%; height: 100%; overflow: hidden;
      background: transparent; /* 비디오 위에 오버레이 */
    }
    [data-composition-id="captions"] .caption {
      position: absolute; bottom: 120px; left: 50%; transform: translateX(-50%);
      background: rgba(0,0,0,0.7); color: #ffffff; font-size: 36px;
      padding: 16px 32px; border-radius: 8px; text-align: center;
      white-space: nowrap;
    }
    [data-composition-id="captions"] .caption-2 { bottom: 60px; font-size: 28px; padding: 12px 24px; }
  </style>
  <div class="caption">안녕하세요, HyperFrames에 오신 것을 환영합니다!</div>
</div>

8. 오디오 반응형 글로우

속성에 반응하는 맥동하는 글로우 효과(예: 오디오 주파수 범위).

<div data-composition-id="pulse-glow" data-width="1920" data-height="1080" data-duration="10">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
  <style>
    [data-composition-id="pulse-glow"] {
      position: relative; width: 100%; height: 100%; overflow: hidden;
      background: #0b0b0f; display: flex; justify-content: center; align-items: center;
    }
    [data-composition-id="pulse-glow"] .glow {
      width: 600px; height: 600px; border-radius: 50%;
      background: radial-gradient(circle, #ffb76b, transparent 70%);
      opacity: 0.5; filter: blur(80px);
    }
    [data-composition-id="pulse-glow"] .title { font-size: 80px; color: #ffffff; position: absolute; margin: 0; text-shadow: 0 0 40px #ffb76b; }
  </style>
  <div class="glow"></div>
  <h1 class="title">비트에 맞춰</h1>
  <script>
    window.__timelines = window.__timelines || {};
    const tl = gsap.timeline({ paused: true, repeat: -1, yoyo: true });
    tl.to(".glow", { scale: 1.5, opacity: 0.8, duration: 0.6, ease: "sine.inOut" });
    window.__timelines["pulse-glow"] = tl;
  </script>
</div>

CLI 명령어

HyperFrames는 합성 생성 및 관리를 위한 CLI를 제공합니다. 일반적인 명령어는 다음과 같습니다:

  • npx hyperframes init <path> — 새 합성을 초기화합니다.
  • npx hyperframes lint <path> — 합성을 검증합니다.
  • npx hyperframes preview <path> — 미리보기 서버를 시작합니다.
  • npx hyperframes render <path> — 합성을 비디오로 렌더링합니다.
  • npx hyperframes transcribe <audio> — 오디오에서 자막을 생성합니다.
  • npx hyperframes tts <text> — 텍스트 음성 변환을 생성합니다.
  • npx hyperframes inspect <path> — 합성 세부 정보를 표시합니다.
  • npx hyperframes benchmark <path> — 성능을 벤치마킹합니다.

전체 문서는 HyperFrames CLI 스킬을 참조하십시오.

문제 해결

  • 렌더링이 멈춥니다: 특히 macOS에서 샌드박스 제한을 확인하십시오. 마지막 수단으로 OD 데몬 경로를 사용하십시오.
  • 자막이 표시되지 않습니다: data-start 및 data-duration이 올바르게 설정되었는지 확인하십시오.
  • 오디오가 재생되지 않습니다: data-volume이 0으로 설정되지 않았고 오디오 파일 경로가 올바른지 확인하십시오.
  • 레이아웃이 어긋납니다: 하드코딩된 절대 위치 대신 패딩이 있는 Flexbox 레이아웃을 사용했는지 확인하십시오.
  • 스타일이 적용되지 않습니다: 합성의 data-composition-id로 범위가 지정된 CSS 선택기를 사용하고 있는지 확인하십시오.

모범 사례

  1. 스캐폴드 사용: 가능하면 항상 처음부터 작성하는 대신 npx hyperframes init로 시작하십시오.
  2. 레이아웃 우선: 모션을 추가하기 전에 항상 최종 상태의 HTML+CSS를 먼저 구축하십시오.
  3. 설계 시스템 존중: 색상, 글꼴 및 모션에 대해 DESIGN.md를 따르십시오.
  4. 트랙 인덱스 사용: 동일한 트랙에서 클립이 겹치지 않도록 하여 예기치 않은 동작을 방지하십시오.
  5. 테스트 자주: 긴 작성 세션보다 작은 변경 사항을 자주 렌더링하여 문제를 조기에 발견하십시오.

그 외의 경우, house-style.md에서 세부 사항을 확인하십시오.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

관련 스킬