감독·각본가·프로듀서·영상 생성기 모두를 13개 AI 에이전트로 — 멀티 에이전트 영상 생성 프레임워크.
왜 모델 하나로는 안 되는가.
2024~2026년 사이 OpenAI Sora, Google Veo, Kling, Runway, Pika 같은 텍스트-투-비디오 모델이 폭발적으로 등장했다. 그런데 결과물은 모두 비슷한 한계를 가진다 — 5~10초짜리 단편 클립, 컷이 바뀌면 캐릭터 얼굴이 바뀌는 일관성 붕괴, 그리고 각본·내레이션 같은 스토리텔링 부재.
ViMax는 "모델을 더 크게 만들자"가 아니라 "여러 모델을 영화 제작 워크플로처럼 오케스트레이션하자"라는 완전히 다른 접근으로 이 문제를 푼다. 사람 영화 제작팀이 작가-감독-스토리보드 아티스트-촬영기사로 분업하듯, ViMax는 13개의 단일 책임 AI 에이전트로 분업시킨다.
한 문장으로 줄이면.
ViMax는 단일 영상 생성 모델이 아니라 오케스트레이션 프레임워크다. 외부 영상·이미지 모델(Veo, Nanobanana, Doubao Seedance)을 YAML 한 줄로 갈아끼울 수 있어, "내 모델을 결합하면 즉시 영상 제작 시스템이 된다"는 매력이 있다.
"하나의 거대한 모델로 영화를 만든다"가 아니라 "각자 한 가지만 잘하는 작은 에이전트들이 협력해서 영화를 만든다"는 비전을 가장 구체적으로 구현한 첫 사례다.
현재 영상 생성의 한계 + ViMax의 차별점.
Sora·Veo·Kling 모두가 동시에 가진 문제 — 그리고 "모델을 더 키워서" 푸는 것이 비싸고 비효율적이라는 점이 ViMax 등장의 배경이다.
Sora, Veo, Kling 모두 한 번에 5~10초 정도밖에 만들지 못한다. 1분짜리 영상이 필요하면 모델 자체를 다시 학습시켜야 한다는 통념이 깨지지 않는다.
같은 캐릭터를 그렸는데 컷이 바뀔 때마다 얼굴·옷·배경이 달라진다. 5초짜리 클립을 여러 개 이어 붙이는 단순한 방법으로는 "한 사람"으로 보이지 않는다.
시각만 있고 각본·내레이션·기·승·전·결 구조가 없다. 모델은 "고양이가 도서관에서 책을 읽는다"는 묘사만 받아들이지, "왜?", "그래서?"는 모른다.
세 가지 문제를 "모델을 더 키운다"가 아니라 "파이프라인을 더 똑똑하게 짠다"로 푸는 것이 핵심 인사이트다.
Sora는 "천재 1명에게 영화 한 편 통째로 맡기는 것"이다 — 그 천재가 아무리 뛰어나도 5분짜리 영화의 모든 컷·캐릭터·각본을 한 번에 만들 수는 없다.
ViMax는 "작가·감독·스토리보드 아티스트·촬영기사·편집감독을 따로 두고 협업시키는 것"이다. 각자는 한 가지만 잘하면 되고, 결과물은 "전체로서 일관된 영화"가 된다.
| 비교 항목 | 단일 모델 (Sora·Veo) | ViMax (오케스트레이션) |
|---|---|---|
| 영상 길이 | 5~10초 한계 | 컷 N개 이어 붙여 무제한 |
| 캐릭터 일관성 | 매 컷마다 달라짐 | FAISS RAG로 참조 강제 |
| 각본 생성 | 없음 (사용자가 직접) | screenwriter 에이전트 자동 |
| 모델 교체 | 불가 (단일 종속) | YAML 한 줄로 교체 |
| 워크플로 | 블랙박스 | 13개 에이전트 단계 가시화 |
| 비용 조절 | 고정 | 저렴한 모델 조합 선택 가능 |
유사 프로젝트(Pika, Runway, Sora)는 모델 자체를 잘 만드는 데 집중한다. ViMax는 거꾸로 "여러 모델을 어떻게 오케스트레이션하면 영화를 만들 수 있는가"라는 시스템적 질문에 답한다. 모델은 외부 API(Google Veo, Doubao Seedance, MiniMax 등)를 갈아끼울 수 있어 "내가 만든 모델을 결합하면 즉시 영상 제작 시스템이 된다"는 매력이 있다.
핵심 의존성 · 외부 모델 · 패키징.
| 패키지 | 역할 | 왜 썼나 |
|---|---|---|
langchain + langchain-openai | LLM 호출 추상화 | 여러 모델 프로바이더(OpenAI, Google, MiniMax)를 동일 인터페이스로 사용 |
openai | OpenAI 호환 API 클라이언트 | OpenRouter, MiniMax, 자체 호스팅 LLM 모두 같은 클라이언트로 처리 |
google-genai | Gemini / Veo / Nanobanana | 구글의 영상·이미지 생성 API 직결 |
faiss-cpu | 벡터 유사도 검색 | 참조 이미지 RAG — "지금 컷에 가장 닮은 캐릭터 사진 찾아줘" |
moviepy | 비디오 편집 | 여러 영상 클립을 이어 붙이고 음성 트랙 합성 |
opencv-python + scenedetect | 영상 분석/장면 감지 | 생성된 영상에서 장면 전환점 자동 추출 |
chardet | 인코딩 감지 | 업로드된 소설/대본 파일 자동 디코딩 |
uv sync 한 줄이면 uv.lock 기준으로 환경 전체가 재구성됨[tool.uv.sources] 섹션에서 PyTorch CUDA 빌드를 플랫폼별로 분기 가능| 레이어 | 지원 모델 | 역할 |
|---|---|---|
| Chat (대본·기획) | Gemini 2.5 Flash, MiniMax-M3 (최신 권장), MiniMax-M2.7 (이전 세대), OpenAI 호환 모델 전반 | 각본 작성, 장면 분할, 스토리보드 설명문 생성 |
| Image | Google Nanobanana (Gemini 2.5 Flash Image), Doubao Seedream, Yunwu 프록시 | 캐릭터 초상화, 첫 프레임 이미지 생성 |
| Video | Google Veo, Doubao Seedance, Yunwu 프록시 | "첫 프레임 → 5초 영상" 생성 |
| Reranker | BGE Reranker (Silicon Flow API) | 여러 후보 이미지 중 캐릭터/배경 일관성이 가장 좋은 것 선택 |
ViMax 기본 설정은 OpenRouter를 통해 Gemini Flash Lite를 호출한다. OpenRouter는 "LLM의 메타 게이트웨이" — 하나의 API 키와 OpenAI 호환 인터페이스로 100+ 모델(GPT, Claude, Gemini, Llama, MiniMax 등)을 호출할 수 있다. 모델 종속을 피하는 모범 패턴이다.
전체 흐름 → 핵심 패턴 하나하나.
┌────────────────────────────────────────────────────────────┐
│ INPUT LAYER │
│ 아이디어 / 대본 / 소설 + 스타일 / 캐릭터 / 사용자 사진 │
└─────────────────────────────┬──────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────┐
│ CENTRAL ORCHESTRATION │
│ pipelines/{idea2video, novel2movie, script2video}.py │
│ 에이전트 스케줄링 · 단계 전환 · 재시도 / 폴백 로직 │
└──────────────┬────────────────────────┬────────────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌──────────────────────┐
│ SCRIPT 이해 │ │ SCENE / SHOT 계획 │
│ character_extractor │ │ scene_extractor │
│ event_extractor │ │ script_planner │
│ screenwriter │ │ storyboard_artist │
│ novel_compressor │ │ global_info_planner │
└──────────┬──────────┘ └──────────┬───────────┘
│ │
└────────────┬─────────────┘
▼
┌────────────────────────────────────────────┐
│ VISUAL ASSET PLANNING │
│ character_portraits_generator │
│ reference_image_selector (FAISS + RAG) │
│ camera_image_generator │
└─────────────────────┬──────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ CONSISTENCY & CONTINUITY │
│ best_image_selector (MLLM/VLM 판정) │
│ BGE Reranker (유사도 재순위) │
└─────────────────────┬──────────────────────┘
│
▼
┌────────────────────────────────────────────┐
│ VISUAL SYNTHESIS & ASSEMBLY │
│ tools/image_generator_* (Nanobanana 등) │
│ tools/video_generator_* (Veo, Seedance) │
│ moviepy 로 컷 합치고 음성 합성 │
└─────────────────────┬──────────────────────┘
│
▼
최종 영상 파일 (.mp4)
13개 에이전트가 각각 하나의 일만 한다. 예: character_extractor는 대본에서 등장인물만 뽑고, scene_extractor는 장면만 나누고, storyboard_artist는 스토리보드만 그린다. 덕분에 디버깅과 모델 교체가 쉬워진다.
실제 영화 제작에서 작가가 카메라까지 잡지 않는 이유와 같다. 역할이 명확히 분리되어 있을 때만 각자가 자기 일에 집중할 수 있고, 한 단계에서 실패해도 다른 단계가 영향받지 않는다.
매 컷을 생성할 때마다 "지금까지 생성된 모든 이미지 + 캐릭터 초상화"를 FAISS 벡터 DB에 인덱싱해 두고, 새 컷이 필요할 때 가장 유사한 참조 이미지를 검색해서 영상 모델에 함께 넣어준다. 이것이 "5번째 컷에서도 캐릭터의 얼굴이 동일"한 비결이다.
이미지 한 장만 생성하지 않고, 병렬로 N장을 생성한 뒤 best_image_selector가 MLLM(멀티모달 LLM)을 호출해서 캐릭터·배경 일관성 점수를 매기고 가장 좋은 것을 고른다. 인간 작가가 컷을 여러 번 그려보고 고르는 워크플로와 동일.
모델이 한 번에 완벽한 결과를 만들 수 없다면, 여러 번 만들고 가장 좋은 것을 고르는 메커니즘을 시스템에 내장해야 한다. ViMax의 best_image_selector는 이 철학을 코드로 구현한 좋은 예시다.
tools/protocols.py에 이미지·영상 생성기의 추상 인터페이스를 정의해두고, image_generator_nanobanana_google_api.py, image_generator_doubao_seedream_yunwu_api.py 같은 구체 구현체를 갈아끼울 수 있다. YAML 한 줄 수정으로 "구글 Veo → 바이트댄스 Seedance"로 전환 가능.
USB 포트가 있으면 어느 회사 마우스든 꽂힌다. protocols.py가 USB 표준이고, image_generator_*.py가 각각의 마우스다. 인터페이스만 표준화하면 구현체는 무한히 늘릴 수 있다는 Python Protocol 패턴의 모범 사례.
어디에 뭐가 있는지.
ViMax/ ├── agents/ # 13개 단일 책임 AI 에이전트 │ ├── character_extractor.py 등장인물 정보 추출 │ ├── scene_extractor.py 장면 분할 │ ├── event_extractor.py 장면 내 이벤트(액션) 추출 │ ├── screenwriter.py 각본 작성 (아이디어→대본) │ ├── novel_compressor.py 긴 소설 → 영상용 압축본 │ ├── script_planner.py 전체 영상 흐름 계획 (★ 25KB, 가장 큰 파일) │ ├── script_enhancer.py 대본 묘사 강화 │ ├── storyboard_artist.py 컷별 스토리보드 텍스트 생성 │ ├── global_information_planner.py 전역 설정 일관성 관리 (★ 18KB) │ ├── character_portraits_generator.py 캐릭터 초상화 생성 │ ├── reference_image_selector.py 참조 이미지 RAG 검색 (★ 15KB) │ ├── camera_image_generator.py 카메라 앵글별 이미지 생성 │ └── best_image_selector.py 생성된 후보 중 최적 선택 │ ├── pipelines/ # 3가지 사용 모드별 오케스트레이터 │ ├── idea2video_pipeline.py 한 줄 아이디어 → 짧은 영상 (10KB) │ ├── novel2movie_pipeline.py 소설 한 권 → 에피소드 영상 (28KB) │ └── script2video_pipeline.py 대본 → 영상 (30KB, 가장 큰 파이프라인) │ ├── tools/ # 외부 API 어댑터 │ ├── protocols.py 공통 인터페이스 정의 │ ├── image_generator_nanobanana_google_api.py │ ├── image_generator_doubao_seedream_yunwu_api.py │ ├── video_generator_veo_google_api.py │ ├── video_generator_doubao_seedance_yunwu_api.py │ ├── reranker_bge_silicon_api.py │ └── render_backend.py │ ├── configs/ # YAML 설정 (모델 갈아끼우는 곳) │ ├── idea2video.yaml │ ├── idea2video_minimax.yaml │ ├── script2video.yaml │ └── script2video_minimax.yaml │ ├── interfaces/ # 데이터 모델(Pydantic 추정) ├── utils/ # 유틸리티 ├── tests/ # 테스트 ├── agent_runtime/ # TUI 관련 런타임 ├── prompts/ # 프롬프트 템플릿 ├── ui/ # 사용자 인터페이스 ├── vimax_benchmark/ # 벤치마크 ├── assets/ # 정적 리소스 │ ├── main_idea2video.py # 진입점: 아이디어 → 영상 ├── main_script2video.py # 진입점: 대본 → 영상 ├── main_agent.py # 진입점: Agent TUI 모드 └── pyproject.toml # uv 의존성 정의
1) main_idea2video.py — 가장 간단한 사용 예시. 약 30줄. 2) pipelines/idea2video_pipeline.py — 전체 흐름을 한눈에. 약 10KB. 3) agents/character_extractor.py — 가장 작고 단순한 에이전트(4KB). 4) 그 다음 script_planner.py로 가장 복잡한 에이전트 도전.
기술 영역마다 무엇을 가져갈지.
pipelines/ 폴더가 LangGraph나 CrewAI의 자리를 직접 구현한 셈. 어떻게 상태를 넘기고 재시도를 처리하는지 살펴볼 것실습: 13개 중 3~4개만 골라서 "단편 영상 자동 생성" 미니 버전을 만들어 보기
실습: 자신이 그린 그림 100장을 CLIP 임베딩으로 FAISS에 넣고, "이 그림과 비슷한 분위기의 그림 5장" 검색기를 만들기
tools/protocols.py의 Protocol(또는 ABC) 패턴 — Python의 duck typing을 안전하게 쓰는 모범 사례실습: ViMax에 새로운 영상 생성 API(예: Runway)를 어댑터로 추가. video_generator_runway_api.py 한 파일만 작성하면 됨
실습: 영상 5개를 받아서 페이드 인/아웃 + 배경음악 합성 + 자막 오버레이를 자동화하는 스크립트 작성
pyproject.toml의 [tool.uv.sources] 섹션 — PyTorch CUDA 빌드를 플랫폼별로 분기하는 모범 예시uv.lock으로 의존성 고정 → 어디서든 동일한 환경 재현실습: 자기 프로젝트를 uv init으로 시작해서 uv add, uv sync, uv run 익히기
로컬은 가볍게, 비용은 API가 부담.
| 항목 | 요구사항 | 비고 |
|---|---|---|
| OS | Linux 또는 Windows | macOS 미지원 (CUDA 의존성) |
| Python | 3.12 이상 | uv가 자동으로 설치 |
| GPU | 필수 아님 | 이미지/영상 생성은 외부 API가 처리 → 로컬은 CPU만 있어도 됨 |
| CUDA | cu128 (PyTorch가 명시) | 로컬에서 임베딩·rerank를 GPU로 돌리고 싶을 때만 |
| 디스크 | 10~50GB | 생성된 컷별 이미지/영상이 누적 |
| API 키 | 최소 3개 | Chat LLM, Image Generator, Video Generator 각각 |
10초짜리 영상 1편(컷 약 3~5개) API 비용은 대략 $1~$5 수준 (Veo 영상 1초당 $0.35 + Nanobanana 이미지당 $0.04 + Gemini Flash 텍스트 비용). 1분 영상이면 $10~$30 가량 예상. MiniMax + Yunwu 프록시 조합으로 더 저렴하게 가능.
현재 macOS는 공식 미지원이다. PyTorch CUDA 빌드가 핵심 의존성에 들어가 있기 때문. 외부 API만 쓰더라도 uv sync 단계에서 의존성 해결이 실패한다. Mac에서 돌리고 싶으면 Docker로 Linux 컨테이너를 띄우거나, 의존성에서 CUDA 빌드를 빼고 CPU 빌드로 fork해야 한다.
난이도별 실습 — Easy → Hard.
1) README의 Quick Start를 그대로 따라하기 2) idea = "고양이가 도서관에서 책을 읽는다"로 시도 3) 가장 저렴한 조합인 Gemini Flash Lite + Nanobanana + Veo 조합 사용 4) 생성된 mp4를 열어 확인
배우는 것: ViMax 진입점 구조, API 키 설정, 한 번의 호출이 13개 에이전트를 순차 호출하는 흐름
1) configs/idea2video.yaml의 chat_model을 MiniMax-M2.7로 변경 2) 같은 아이디어로 다시 생성 3) 생성된 대본/스토리보드 텍스트의 차이를 비교 4) 결과 영상의 분위기 차이를 메모
배우는 것: Provider-agnostic 인터페이스의 위력, LLM 선택이 최종 영상에 미치는 영향
1) tools/protocols.py의 인터페이스 정독 2) image_generator_dalle3_openai.py를 새로 작성 3) OpenAI DALL-E 3 API에 직접 붙이기 4) YAML에서 이 어댑터를 호출하도록 변경 5) 결과 비교
배우는 것: Python Protocol 패턴, 새 외부 API를 기존 시스템에 통합하는 어댑터 작성
1) 같은 캐릭터로 컷 5개를 만들고 2) CLIP 임베딩 cosine similarity로 컷 간 캐릭터 일관성을 측정 3) ViMax의 reference_image_selector를 끄고 다시 측정 4) 점수가 얼마나 떨어지는지 비교 분석
배우는 것: RAG 효과 정량 측정, CLIP 임베딩 활용, 일관성 메트릭 설계
1) novel2movie_pipeline.py를 그대로 사용 2) 짧은 한국어 단편(예: 카프카 "변신" 1장) 입력 3) 모든 에이전트 프롬프트에 "한국어로 응답" 추가 4) 캐릭터·배경·자막이 한국어 정서에 맞게 나오는지 검증 5) 각 에이전트별 출력을 한글 노트로 정리
배우는 것: 전체 파이프라인 커스터마이징, 다국어 프롬프트 엔지니어링, 문화 컨텍스트 반영
주차별로 따라가면 멀티 에이전트 영상 시스템 마스터.
OpenAI/Gemini API 직접 호출 → LangChain의 ChatModel 추상화 → 프롬프트 템플릿. 작은 챗봇 1개 완성. ViMax의 screenwriter.py 코드를 한 줄씩 읽기.
CrewAI 또는 LangGraph 튜토리얼. "감독 + 작가 + 비평가" 3-에이전트 시스템을 직접 짜보기. ViMax의 pipelines/ 코드와 비교하며 "프레임워크 없이 어떻게 구현했는지" 학습.
FAISS, Chroma, Pinecone 비교. CLIP 임베딩으로 이미지 RAG 구현. ViMax의 reference_image_selector.py를 한 줄씩 읽고 자기 이미지 컬렉션에 동일 패턴 적용.
Google Veo, Runway, Pika, Sora의 API 차이 비교. moviepy/ffmpeg로 클립 결합. ViMax에 자신만의 어댑터 PR 보내보기 (Runway 등). 캡스톤: 본인 단편 시나리오를 영상으로.
자주 마주칠 단어들.
공식 · 의존성 · 학습 리소스.
uv sync로 환경 구성, OpenRouter 키 하나로 Gemini Flash Lite + Nanobanana + Veo 묶고 main_idea2video.py 실행. 결과 mp4를 눈으로 확인해 "한 줄이 5초 영상이 되는" 충격을 체험.character_extractor가 뽑은 인물, scene_extractor가 나눈 장면, storyboard_artist가 그린 스토리보드를 한 단계씩 읽기. 어디서 어떤 모델이 호출되는지 감 잡기.configs/idea2video.yaml에서 chat_model을 MiniMax-M2.7로 바꾸고 같은 아이디어 재실행. 각본·스토리보드 텍스트가 어떻게 달라지는지 메모 — Provider-agnostic 인터페이스의 위력 체감.tools/protocols.py의 인터페이스를 따라 Runway 또는 DALL-E 3 어댑터를 작성. YAML에 등록 → 동작 확인 → 업스트림에 PR. 오픈소스 기여 + Protocol 패턴 체득.