FrameVOX: 에이전트가 만든 소셜 비디오용 영상 제작 CLI

발행: (2026년 6월 10일 AM 05:22 GMT+9)
10 분 소요
원문: Dev.to

출처: Dev.to

FrameVOX: 에이전트가 만든 소셜 비디오용 비디오 제작 CLI

FrameVOX는 제가 새로 만든 비디오 제작 프로젝트입니다.

레포지토리:

https://github.com/tecnomanu/framevox

짧게 말하면: FrameVOX는 HTML 구성, 음성 생성, 템플릿, 렌더링을 활용해 바로 배포 가능한 비디오를 만들 수 있는 CLI입니다.

보다 정확히 말하면: FrameVOX는 HyperFrames와 TTS 제공자를 감싸는 얇은 실용 레이어입니다. HyperFrames 자체를 대체하는 것이 아니라, 에이전트와 사람이 비디오 아이디어를 실제 MP4 파일로 바꿀 때 흔히 겪는 여러 번거로운 과정을 한데 묶어줍니다.


문제점

HTML‑to‑video 도구는 강력하지만, 제작 워크플로에는 작은 실패 지점이 많이 존재합니다.

수작업으로 진행한다면 전형적인 흐름은 다음과 같습니다:

mkdir my-promo
cd my-promo

# index.html, style.css, assets, timing, scenes, voice script 만들기
# data‑attribute를 올바르게 연결하기
# 음성 생성 또는 녹음하기
# 제공자가 raw audio를 반환하면 PCM을 MP3로 변환하기
# 음성 파일이 정상인지 확인하기
# lint 실행하기
# headless Chrome으로 렌더링하기
# 타이밍 수정하기
# 다시 렌더링하기

이 단계들이 불가능한 것은 아니지만, 모두 합쳐지면 워크플로에 마찰이 생겨 특히 AI 에이전트가 작업을 수행할 때 흐트러지기 쉽습니다.

에이전트는 파일을 만드는 데는 능숙하지만, 숨겨진 설정이 필요하거나 키가 누락되었거나 템플릿이 불분명하거나, 음성 변환을 수동으로 해야 하거나, 렌더링이 늦게 실패하는 상황에서는 약합니다.

FrameVOX는 이 과정을 명시적으로 만들어 줍니다:

npx framevox init my-promo --template minimal-mobile
npx framevox add-key gemini YOUR_GEMINI_KEY
npx framevox voice
npx framevox render

이렇게 하면 하나의 프로젝트 폴더, 하나의 음성 파일, 하나의 렌더링된 MP4가 생성됩니다.


FrameVOX가 감싸는 것

FrameVOX는 HTML‑to‑video 레이어로 HyperFrames를 사용합니다.

HyperFrames는 여전히 렌더링 엔진이며, 구성 모델, 프리뷰, lint, 검사, 렌더링 파이프라인을 제공합니다. FrameVOX는 그 위에 다음과 같은 제작용 래퍼를 추가합니다:

  • 템플릿 기반 프로젝트 스캐폴딩
  • TTS 키 저장
  • Gemini, Piper, ElevenLabs 음성 생성
  • 생성된 오디오에 대한 MD5 무결성 검사
  • 렌더링 전 lint 기본값
  • 템플릿 탐색
  • 자동 생성 레시피와 프로젝트 문서
  • 에이전트 스킬 설정
  • 업데이트 및 상태 명령

이 구분은 중요합니다. FrameVOX는 전체 디자인 앱이 되려는 것이 아니라, 실제 렌더러를 중심으로 반복 가능한 프로젝트 워크플로를 만들고자 합니다.


요구 사항

현재 FrameVOX가 필요로 하는 환경은 다음과 같습니다:

Node.js >= 22
ffmpeg
Chrome 또는 Chromium
piper 바이너리 (Piper를 사용할 경우에만)

패키지는 다음과 같이 노출됩니다:

{
  "name": "framevox",
  "version": "0.2.0",
  "bin": {
    "framevox": "bin/framevox.js"
  }
}

HyperFrames는 의존성으로 번들되어 있기 때문에, 일반적인 렌더 경로에서는 별도로 설치할 필요가 없습니다.


프로젝트 구조

init 명령을 실행하면 프로젝트는 다음과 같은 형태가 됩니다:

my-promo/
├── index.html
├── voice.json
├── DESIGN.md
├── assets/
├── voice.mp3
├── output.mp4
├── RECIPE.md
└── .framevox/
    └── config.json

각 파일의 역할은 다음과 같습니다:

  • index.html – 실제 비디오 구성 파일
  • voice.json – 음성 스크립트
  • DESIGN.md – 제품, 브랜드, 색상, 카피 등을 편집 전에 정리하는 곳
  • assets/ – 로고 및 기타 미디어 파일
  • .framevox/config.json – 제공자와 렌더 메타데이터 저장
  • RECIPE.md – 프로젝트 제작 과정을 문서화

에이전트 기반 워크플로에서는 이러한 구조가 중요합니다. 에이전트는 DESIGN.md를 검토하고, 구성 파일을 수정하고, voice.json을 조정하고, 오디오를 재생성한 뒤, 어디에 무엇이 있는지 추측하지 않고 다시 렌더링할 수 있습니다.


템플릿

FrameVOX는 패밀리별로 묶인 템플릿을 제공합니다. 현재 내장된 패밀리는 다음과 같습니다:

minimal
promo
studio
immersive

각 패밀리는 모바일과 데스크톱 변형을 가질 수 있습니다. 예시:

templates/promo/
├── style.css
├── family.json
├── mobile/
└── desktop/

이를 통해 하나의 패밀리가 시각적 아이덴티티를 공유하면서도 여러 출력 포맷을 지원할 수 있습니다.

유용한 명령들:

framevox templates
framevox templates --json
framevox templates add promo
framevox templates install promo
framevox init my-reel --template promo-mobile

템플릿 검색 순서는 다음과 같습니다:

project .framevox/templates/
user ~/.framevox/templates/
builtin templates

즉, 실험 단계에서 재사용 가능한 브랜드 템플릿까지 깔끔한 경로를 제공합니다. 기본 패밀리로 시작하고, 프로젝트에 복사한 뒤 브랜드에 맞게 커스터마이징하고, 재사용 가능해지면 전역에 설치하면 됩니다.


음성 생성

FrameVOX는 여러 TTS 경로를 지원합니다:

framevox add-key gemini YOUR_GEMINI_KEY
framevox add-key elevenlabs YOUR_ELEVENLABS_KEY
framevox add-key piper-voice en_US-lessac-medium
framevox keys

키는 ~/.framevox/.env에 저장되며 절대 커밋해서는 안 됩니다.

음성 파일은 간단합니다:

{
  "prompt": "따뜻하고 대화체 톤으로 읽어 주세요:",
  "text": "Meet Crewdesk... 현장 팀을 정렬해 주는 스케줄링 툴입니다."
}

긴 영상의 경우 씬을 활용할 수 있습니다:

{
  "prompt": "에너지 넘치는 제품 출시 톤으로 읽어 주세요:",
  "gap": 0.3,
  "scenes": [
    { "id": "hook", "text": "팀 일정이 또 바뀌었어요." },
    { "id": "problem", "text": "이제 세 명이 서로 다른 플랜을 보고 있습니다." },
    { "id": "solution", "text": "Crewdesk는 모든 교대, 경로, 업데이트를 한 곳에 모아 줍니다." },
    { "id": "cta", "text": "오늘 첫 스케줄을 시작해 보세요." }
  ]
}

특정 파트를 재생성할 수도 있습니다:

framevox voice --scene hook
framevox voice --scene 2

생성 후 FrameVOX는 음성 타임라인을 기록합니다. 이는 비디오 타이밍을 텍스트 길이 추측이 아니라 실제 오디오 길이에 기반해 맞출 수 있게 해 주기 때문에 중요합니다.


Gemini용 감정 태그

Gemini TTS는 인라인 태그를 통해 전달 방식을 바꿀 수 있습니다:

{
  "prompt": "스페인어 리오플라텐세, 따뜻하고 대화체로 읽어 주세요:",
  "text": "Bueno che, mirá esto... [excited]Esto acelera todo.[/excited] ... [whisper]Y no tenés que tocar ffmpeg a mano.[/whisper]"
}

태그는 말해야 할 단어가 아니라 전달 지시입니다.

예시:

  • [eloquent]...[/eloquent] – 연극적인 강조 강화
  • [sad]...[/sad] – 차분한 전달
  • [whisper]...[/whisper] – 낮은 목소리
  • [excited]...[/excited] – 높은 에너지

짧은 프로모션에서는 여러 API 호출보다 text 필드 하나에 일시정지를 넣는 것이 더 효율적일 수 있습니다. 긴 스크립트에서는 씬을 활용하면 제어가 쉬워지고 재생성도 간편합니다.


렌더 워크플로

주된 렌더 경로는 의도적으로 단순합니다:

framevox lint
framevox preview
framevox render

렌더 명령은 옵션을 받을 수 있습니다:

framevox render --out
0 조회
Back to Blog

관련 글

더 보기 »

Eidentic 소개

Today we're releasing Eidentic, an open-source TypeScript SDK for building AI agents with self-improving memory and the production fundamentals built in — not b...

Typescript의 타입

Introdução Tipos são uma forma de definir a “forma” ou o contrato dos dados que estamos usando no código. Pensando em Javascript puro, ele é dinâmico: você pode...