
6시간에서 10분으로: 0.02달러짜리 AI 영화 학교를 구축한 방법
요약
Qwen 모델을 활용하여 한 문장의 텍스트를 음성과 자막이 포함된 세로형 단편 영화로 변환하는 AI 파이프라인 'drama916' 구축 사례를 소개합니다. 반복적인 수정 작업을 비용이 저렴한 텍스트 단계로 집중하여 전체 제작 비용을 획기적으로 절감한 아키텍처 설계 노하우를 다룹니다.
핵심 포인트
- 텍스트 기반 반복 작업을 통해 시나리오 및 비평 단계 비용을 $0.02 수준으로 절감
- Qwen 모델과 Alibaba Cloud Function Compute를 활용한 서버리스 아키텍처 구축
- 시리즈 바이블(Series bible) 도입을 통한 캐릭터 드리프트(Character drift) 현상 방지
- 상태 유지형(Stateful) 비디오 제작 파이프라인 구축 시의 기술적 도전과 해결책
Qwen Cloud Global AI Hackathon를 위해 drama916을 구축하는 과정 — 한 문장을 음성이 포함된 세로형 단편 영화로 변환하는 파이프라인과, 전체 아키텍처(Architecture)를 형성한 비용에 관한 교훈.
라이브 데모 (Live demo): https://drama916.coralglove.com
소스 코드 (Source code): https://github.com/itsbigdill/drama916
한 문장을 입력하세요:
“아보카도와 배가 휴가를 떠나고, 배는 건포도가 될 때까지 일광욕을 합니다.”
약 10분 후, 여러분은 음성과 자막이 포함된 9:16 비율의 단편 영화와 바로 복사해서 사용할 수 있는 소셜 미디어 캡션(Caption)을 시청하게 됩니다.
이것이 바로 AI Showrunner 트랙을 위한 저희의 출전작, drama916입니다. 이 시스템은 Qwen 모델을 기반으로 하며, Alibaba Cloud Function Compute에 배포되었고, 하나의 단순한 아이디어를 중심으로 설계되었습니다:
수정 비용이 저렴할 때 창의적인 실수를 저질러라.
완성된 쇼케이스 영화를 제작하는 데는 7.16달러가 들었습니다. 하지만 시나리오(Screenplay), 촬영 계획(Shot planning), 그리고 세 차례의 감독 비평(Director critique)에는 단 약 0.02달러만이 소요되었습니다.
그 격차가 저희가 내린 거의 모든 기술적 결정을 결정지었습니다.
이것은 솔직한 구축 이야기입니다. 왜 저희가 반복 작업(Iteration)을 텍스트 단계로 옮겼는지, 시리즈 바이블(Series bible)을 통해 캐릭터 드리프트(Character drift)를 어떻게 줄였는지, 그리고 상태 유지형(Stateful) 비디오 제작 파이프라인을 Function Compute에 배포했을 때 무엇이 고장 났는지에 대한 이야기입니다.
아키텍처를 설명하는 영수증
모든 drama916 실행은 다음 경로에 비용 보고서를 생성합니다:
runs/<id>/run_report.json
이 보고서에는 모델 호출(Model calls), 토큰 사용량(Token usage), 생성된 이미지, 비디오 재생 시간, 그리고 해당 특정 영화에 대해 계산된 비용이 기록됩니다.
다음은 저희 쇼케이스 영화 중 하나인 **“Gods of the Pitch”**의 장부입니다. 8개의 샷(Shot), 41초 분량, 전체 음성 포함.
| 단계 (Stage) | 모델 (Model) | 비용 (Cost) |
|---|---|---|
| 시나리오 (Screenplay) | qwen3.7-max | $0.0122 |
| ... |
이 장부의 형태를 살펴보십시오.
모든 텍스트 기반 추론 단계 — 시나리오 (Screenplay), 샷 계획 (Shot planning), 그리고 세 차례의 비평 (Critique) — 는 약 $0.021, 즉 전체 실행 비용의 약 0.3% 정도의 비용이 들었습니다.
비디오 생성 (Video generation)이 92% 이상을 차지했습니다.
따라서 설계 원칙은 자연스럽게 도출되었습니다:
비용이 저렴한 곳에서 반복 (Iterate)하라. 결정이 승인된 후에만 렌더링 (Render)하라.
대부분의 생성형 비디오 (Generative-video) 워크플로우는 이와 반대로 동작합니다. 클립을 생성하고, 문제를 발견하면, 프롬프트 (Prompt)를 수정하고, 다시 생성합니다.
모든 창의적인 반복 과정이 가장 비용이 많이 드는 단계를 거치게 됩니다.
drama916은 그 루프 (Loop)의 대부분을 텍스트 단계로 옮겼습니다.
쇼러너 (Showrunner)에게 먼저 생각하는 법을 가르치기
파이프라인 (Pipeline)은 로그라인 (Logline)에서 시작됩니다.
1. 시나리오 (Screenplay)
qwen3.7-max는 아이디어를 시작, 고조, 결말이 있는 짧은 시나리오로 확장합니다.
이 단계에서는 더 깊은 추론 (Reasoning) 기능을 활성화된 상태로 유지합니다. 스토리 구조 (Story structure)는 더 많은 토큰 (Tokens)을 소비함으로써 결과물을 직접적으로 개선할 수 있는 몇 안 되는 영역 중 하나입니다.
2. 샷 계획 (Shot plan)
qwen3.7-plus는 시나리오를 개별 샷 (Shot)으로 나눕니다.
모든 샷에 대해 다음 사항을 정의합니다:
- 누가 등장하는지;
- 어떤 일이 일어나는지;
- 카메라 프레이밍 (Camera framing);
- 감정적 비트 (Emotional beat);
- 대사 (Spoken line);
- 누가 말하는지.
이 단계에서 모든 것은 여전히 텍스트입니다. 단 하나의 이미지나 비디오 클립을 다시 생성하지 않고도 구조를 변경할 수 있습니다.
3. 감독-비평 루프 (Director-critic loop)
두 번째 qwen3.7-plus 역할이 감독 (Director)이자 비평가 (Critic) 역할을 수행합니다.
이 모델은 계획된 스토리보드 (Storyboard)를 여러 차원에 걸쳐 1점에서 10점 사이로 점수를 매깁니다:
- 서사적 연속성 (Narrative continuity);
- 시각적 명확성 (Visual clarity);
- 페이싱 (Pacing);
- 캐릭터 일관성 (Character consistency);
- AI 렌더링 가능성 (AI renderability).
마지막 카테고리가 특히 중요해졌습니다.
한 장면(shot)이 시나리오상으로는 괜찮게 들릴 수 있지만, 이미지나 비디오 모델에게는 여전히 어려울 수 있습니다. 흔한 문제로는 한 프레임에 너무 많은 캐릭터가 등장하거나, 복잡한 손 상호작용, 불분명한 해부학적 구조, 또는 검열(moderation)을 유발할 가능성이 있는 문구 등이 있습니다.
점수가 8점 미만일 경우, 비평가(critic)는 위험한 장면을 식별하여 이를 다시 작성하고 계획을 다시 평가합니다. 이 루프는 최대 3회까지 실행될 수 있습니다.
각 비평 라운드에는 약 0.002달러가 소요됩니다.
이는 쇼케이스 실행(showcase run)에서 평균적인 비디오 클립을 재생성하는 것보다 수백 배 저렴하며, 비디오 단계 전체를 다시 렌더링하는 것보다 수천 배 저렴합니다.
이것이 실제 적용된 우리의 토큰 예산 최적화(token-budget optimization) 전략입니다. 단순히 더 적은 토큰을 사용하는 것이 아니라, 값비싼 생성 오류를 피하기 위해 저렴한 추론(reasoning) 토큰을 사용하는 것입니다.
인간의 승인 게이트 (The human approval gate)
AI 비평가가 최종 권한을 가진 것은 아닙니다.
비디오 생성이 시작되기 전, drama916은 qwen-image-2.0-pro를 사용하여 전체 스토리보드(storyboard)를 생성하고 이를 사용자에게 제시합니다.
사용자는 다음을 수행할 수 있습니다:
- 감독의 노트(director’s note)와 함께 프레임 다시 그리기;
- 장면 순서 변경;
- 불필요한 장면 제거;
- 대사 검토;
- 최종 스토리보드 승인.
예를 들어, 사용자는 다음과 같이 작성할 수 있습니다:
“그가 벤치에 혼자 앉아 있게 해줘.”
시스템은 단순히 이미지를 다시 그리는 것 이상의 일을 수행합니다. 작은 qwen3.6-flash 호출이 장면의 동작을 업데이트하며, 필요한 경우 프레임, 스크립트, 대사 및 자막이 동기화된 상태를 유지하도록 대사를 조정합니다.
스토리보드가 승인된 후에야 drama916은 비디오 크레딧을 사용합니다.
사용자가 Film it을 클릭하면, 승인된 각 스토리보드 프레임은 happyhorse-1.1-i2v 클립의 실제 첫 번째 프레임이 됩니다.
제작의 값비싼 단계는 AI 비평가와 인간 감독이 모두 계획을 승인한 후에야 시작됩니다.
시리즈 바이블을 통한 캐릭터 일관성 유지 (Keeping characters consistent with a series bible)
캐릭터 드리프트(Character drift)는 다중 장면 생성(multi-shot generation)에서 발생하는 가장 큰 문제 중 하나입니다.
캐릭터는 연속된 두 장면 사이에서 얼굴, 옷, 비율, 또는 심지어 종(species)까지 변할 수 있습니다.
우리는 처음에 점점 더 상세한 프롬프트 (prompts)를 사용하여 이 문제를 해결하려고 시도했습니다. 하지만 모든 에이전트 (agent)가 캐릭터를 조금씩 다르게 묘사했기 때문에 신뢰할 수 있는 결과를 얻지 못했습니다.
해결책은 더 나은 형용사를 찾는 것이 아니었습니다. 그것은 소유권 규칙 (ownership rule)이었습니다:
백엔드 (backend)가 모든 캐릭터의 외형을 소유합니다. 모델 (models)은 샷 (shot)마다 외형을 다시 설계하지 않습니다.
시나리오 에이전트 (screenplay agent)는 각 캐릭터의 표준 시각적 묘사 (canonical visual description)를 한 번 정의합니다.
그러면 샷 플래너 (shot planner)는 새로운 외형 세부 사항을 만들어내는 것이 금지됩니다. 그것은 오직 구조만을 반환합니다:
- 어떤 캐릭터가 존재하는지;
- 그들이 무엇을 하고 있는지;
- 그들이 어디에 있는지;
- 카메라가 그들을 어떻게 보는지.
백엔드는 다음 요소들로부터 기계적으로 각 이미지 프롬프트 (image prompt)를 구성합니다:
- 선택된 시각적 스타일 (visual style);
- 표준 캐릭터 묘사 (canonical character descriptions);
- 출연진 참조 이미지 (cast reference images);
- 장소 (location);
- 샷 액션 (shot action);
- 카메라 프레이밍 (camera framing).
동일한 캐릭터 묘사가 해당 캐릭터가 등장할 때마다 토씨 하나 틀리지 않고 그대로 삽입됩니다.
우리는 또한 최종 스토리보드 (storyboard)와 동일한 시각적 스타일을 사용하여 출연진의 각 멤버에 대해 하나의 참조 초상화 (reference portrait)를 생성합니다. 이러한 참조 이미지들은 프레임 생성 (frame generation) 단계로 다시 전달됩니다.
이 방법이 모든 일관성 문제를 제거하지는 못하지만, 샷 간의 드리프트 (drift)를 실질적으로 줄여줍니다.
우리는 또한 중요한 한계점도 배웠습니다. 시각적으로 모호한 캐릭터는 여전히 어렵다는 점입니다.
"상체가 불분명한 인간형 거미"와 같은 묘사는 모델에게 여러 가지 유효한 해석을 제공합니다. 모델은 각 프레임마다 서로 다른 해석을 선택할 수 있습니다.
명확한 실루엣, 의상, 색상 및 해부학적 구조를 가진 캐릭터는 훨씬 더 일관되게 유지됩니다.
조용한 폴백 (silent fallbacks) 없음
이미지 검열 (image moderation)이 가끔 무해해 보이는 장면을 차단하기도 합니다.
"포옹 (embrace)"과 같은 단어는 프롬프트의 나머지 내용에 따라 예상보다 더 공격적으로 해석될 수 있습니다.
우리의 초기 프로토타입 (prototype)은 차단된 이미지를 근처의 프레임으로 조용히 대체했습니다. 이는 파이프라인 (pipeline)을 계속 작동하게 만들었지만, 부정직한 결과를 초래했습니다. 시스템이 생성한 적도 없는 샷을 완료한 것처럼 보였기 때문입니다.
우리는 그러한 동작을 제거했습니다.
이제 차단된 프레임은 스토리보드에 차단됨(blocked) 상태로 표시되며, 그 이유와 함께 재생성 (Regenerate) 버튼이 나타납니다. 모든 필수 프레임이 실제로 존재할 때까지 영화는 진행될 수 없습니다.
우리는 모호한 연출(staging)을 더 명확하고 G-rated(전체 관람가) 수준의 시각적 언어로 다시 쓰는 프롬프트 정화기 (prompt sanitizer)를 추가했습니다.
예를 들어:
“그들은 감정적으로 포옹한다.”
는 다음과 같이 바뀔 수 있습니다:
“그들은 머리를 서로 맞대고 있으며, 그들 위로 작은 하트 기호들이 떠다닌다.”
이는 장면의 감정적 목적을 변경하지 않으면서도 많은 검열 (moderation) 문제를 해결합니다.
동일한 원칙이 비디오 출력에도 적용됩니다.
비디오 API 요청이 가끔 성공적으로 반환되면서도 정작 결과물은 전체가 검은색인 클립을 생성할 때가 있습니다. 우리는 거의 검은색에 가까운 출력을 감지하는 ffmpeg 루마 체크 (luma check)를 추가하여, 정화된 프롬프트로 한 번 재시도하고, 재시도 후에도 여전히 유효하지 않으면 실패를 보고하도록 했습니다.
재시도는 존재하지만, 조용히 가짜로 대체되는 일은 없습니다.
대사를 장면에 맞추기
음성 생성 (Voice generation)은 또 다른 문제를 야기했습니다.
비디오 클립은 5.2초 동안 지속되는데, 생성된 대사는 6.3초 동안 지속될 수 있습니다. 첫 번째 버전에서는 남은 음성이 다음 장면으로 이어졌습니다.
그 결과 기술적으로는 완결되었으나 내용을 따라가기 어려웠습니다.
이제 편집기 (editor)는 음성에 맞춰 시각적 지속 시간 (visual duration)을 조정합니다.
먼저 클립을 의도된 것처럼 보일 수 있는 안전한 한도 내에서 약간 느리게 만듭니다. 만약 대사가 더 길다면, 문장이 끝날 때까지 마지막 프레임을 유지합니다.
그 후 새로운 장면 지속 시간을 기준으로 크로스페이드 (Crossfade) 타이밍을 다시 계산합니다.
영화는 약간 더 길어졌지만, 대사는 극적으로 이해하기 쉬워졌습니다.
또한 이를 통해 생성된 음성이 관련 없는 클립 위에 얹혀진 오디오 레이어처럼 느껴지지 않고, 실제 편집의 일부처럼 느껴지게 되었습니다.
Function Compute에 상태 유지 비디오 파이프라인 (stateful video pipeline) 배포하기
백엔드는 의도적으로 작게 구성되었습니다.
다음과 같은 하나의 Python 서비스로 이루어져 있습니다:
- 표준 라이브러리 HTTP 서버 (standard-library HTTP server);
- 프론트엔드에서 폴링(polled)하는 인메모리 실행 상태 (in-memory run state);
- 편집을 위한 ffmpeg;
- 모델 호출을 위한 DashScope API.
이 상태 유지 파이프라인 (stateful pipeline)을 Alibaba Cloud Function Compute에 배포하면서 몇 가지 실질적인 교훈을 얻었습니다.
프로토타입에는 ZIP 웹 함수 (ZIP Web Function)가 더 간단했습니다
Function Compute는 커스텀 컨테이너를 지원하지만, 이번 해커톤 빌드에서는 ZIP 웹 함수를 선택했습니다.
패키지 구성 요소는 다음과 같습니다:
- Python 애플리케이션;
- 벤더링된 (vendored)
manylinux2014_x86_64의존성 파일들; - 정적 ffmpeg 바이너리;
bootstrap스크립트;- 시연용 에셋 (showcase assets).
최종 패키지 크기는 약 130MB였기 때문에, 직접 업로드 대신 OSS를 통해 업로드했습니다.
교차 버전 의존성 벤더링 (Cross-version dependency vendoring)은 조용히 실패할 수 있습니다
우리는 Python 3.10 런타임을 위해 Python 3.14 개발 머신에서 의존성을 준비했습니다.
pip는 빌드 인터프리터에 대해 환경 마커 (environment markers)를 평가했습니다. 그 결과, Python 3.11 미만에서만 필요한 호환성 의존성이 패키징 과정에서 누락되었습니다.
이로 인해 프로덕션 런타임에서 임포트 (import) 중에 함수가 충돌했습니다.
문제를 발견한 후 해결 방법은 간단했습니다. 빌드 머신이 타겟 런타임에 맞춰 의존성을 올바르게 해결할 것이라고 가정하는 대신, 필요한 백포트 (backports)를 명시적으로 고정 (pin)하는 것이었습니다.
애플리케이션 디렉토리는 읽기 전용입니다
배포된 코드 디렉토리는 런타임 출력용으로 사용할 수 없습니다.
따라서 생성된 실행 결과는 다음 경로에 저장됩니다:
RUNS_DIR=/tmp/runs
부트스트랩 (bootstrap) 프로세스는 애플리케이션에 포함된 시연용 영화들을 런타임 디렉토리로 복사하기도 합니다.
이는 프로토타입에는 작동하지만, /tmp는 영구적인 저장소가 아닙니다. 생성된 영화와 보고서를 OSS에 보관하는 것은 우리가 가장 먼저 수행할 프로덕션 개선 사항 중 하나입니다.
기본 Function Compute 도메인은 공개 UI에 적합하지 않았습니다
기본 *.fcapp.run 응답은 보안 동작 특성상 우리의 설정에서 HTML 다운로드를 강제했습니다.
대신 Cloudflare를 통해 커스텀 도메인을 연결했습니다.
기본적인 흐름은 다음과 같습니다:
- CNAME을 생성합니다;
- Cloudflare 프록시 (proxy)를 일시적으로 비활성화하여 이를 검증합니다;
- 프록시를 다시 활성화합니다;
- HTTPS를 위해 Full SSL 모드를 사용합니다.
하나의 Warm 인스턴스가 활성 실행을 보호합니다
현재 프로토타입은 활성 실행 상태 (active run state)를 메모리에 유지합니다.
비디오 생성 중에 스케일 투 제로 (scale-to-zero) 재순환이 발생하면, 이미 수 달러의 모델 호출 비용이 지출된 후 실행 상태가 파괴될 수 있습니다.
해커톤 배포를 위해, 우리는 최소 인스턴스 수를 1로 설정했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기