명확한 제품 이미지 한 장, Claude Code, AIHubMix API가 있으면 Seedream으로 캐릭터 레퍼런스를 생성하고, 이를 가상 인물 에셋으로 등록한 뒤, Seedance로 AI 제품 광고를 만들 수 있습니다.
이 튜토리얼은 실제 알로에 미스트 캠페인을 기반으로 하며, 프로젝트 구조, 설정, 명령어, 완성된 비디오 프롬프트를 포함합니다. 목표 결과물은 AI로 생성한 인물과 배경이 포함된 20초, 720p, 9:16 세로형 광고입니다.
Claude Code와 AIHubMix가 전체 워크플로를 구동합니다. Claude Code는 프로젝트 브리프를 읽고, 프롬프트를 수정하며, 실행을 정리합니다. AIHubMix는 단일 모델 진입점을 제공하여 같은 프로젝트 안에서 이미지와 비디오 생성을 모두 수행할 수 있게 합니다.
모델 ID, 파라미터, 오류 처리 방식은 2026년 9월 16일자 프로젝트 스냅샷을 기준으로 합니다. 재사용하기 전에 현재 API를 확인하세요. 명령어는 포함된 flow.py를 사용하며 반드시 프로젝트 루트 디렉터리에서 실행해야 합니다.스타터 패키지 다운로드
코드, 프롬프트, 설정, 샘플 이미지를 다운로드하세요:
https://drive.google.com/uc?export=download&id=1nXcj26Fq3daHeTd0SynS7_QEXgH8z4u_
압축을 푼 뒤 seedance-starter 디렉터리로 들어가세요. 패키지에는 flow.py, 두 개의 스키마 스냅샷, 다섯 개의 프롬프트 파일, 제품 이미지, 세 장의 레퍼런스 이미지가 포함되어 있습니다. Python 스크립트는 표준 라이브러리만 사용합니다.
- 비디오 단계부터 시작하기: 포함된 레퍼런스 이미지 세 장을 사용하고, 키를 설정한 뒤 4단계부터 시작하세요.
- 자신의 제품으로 시작하기: 제품 이미지와 프롬프트 세부 내용을 바꾸고, 포함된 레퍼런스 이미지를
assets/에서 옮긴 뒤 3단계부터 시작하세요.
.env.example을 .env로 복사하고 본인의 API 키를 추가하세요. 계정에 관련 모델 접근 권한, 필요한 비동기 작업 권한, 충분한 할당량이 있어야 합니다. API 생성에는 사용량에 따른 요금이 부과됩니다.
1. 제품 이미지와 프로젝트 준비하기
예시 제품은 Nature Republic Aloe Vera Mist입니다. 워크플로를 적용할 때는 이미지, 제품 설명, 사용 동작을 함께 업데이트하세요.
| 파일 | 용도 |
|---|---|
assets/product.png | 원본 제품 이미지 |
prompts/prompt-a.txt | 메인 캐릭터 초상 프롬프트 |
prompts/prompt-b.txt | 캐릭터가 제품을 들고 있는 프롬프트 |
prompts/prompt-c.txt | 제품 사용 프롬프트 |
prompts/prompt-video.txt | 비디오 타임라인, 카메라, 오디오 요구사항 |
prompts.json | 해상도, 길이, 레퍼런스 의존성, 프롬프트 경로 |
flow.py | API 요청, 에셋 등록, 폴링, 다운로드 |
seedream.schema.json, seedance.schema.json | 캐시된 API 스키마 스냅샷 |
Claude Code는 프로젝트 브리프를 읽고 설정과 프롬프트를 수정하는 데 도움을 줍니다. flow.py는 AIHubMix를 통해 실제 요청을 보냅니다.
이 워크플로에 AIHubMix가 적합한 이유
AI 제품 광고 워크플로에는 보통 둘 이상의 모델이 필요합니다. 이미지 모델은 인물과 제품 레퍼런스를 만들고, 비디오 모델은 움직임과 카메라 동작을 만듭니다. AIHubMix는 대부분의 주요 모델을 지원하므로, 공급자마다 별도의 계정, 인증, 요청 진입점을 관리하지 않고 하나의 API 서비스에서 작업에 맞는 모델을 선택할 수 있습니다.
AIHubMix는 여러 공급자와 연결되어 있으며, 사용 가능한 저지연 경로를 자동으로 선택합니다. 이는 이미지 생성, 에셋 처리, 비디오 생성을 순서대로 완료해야 하는 워크플로에서 단일 공급자의 불안정성이 미치는 영향을 줄여줄 수 있습니다. 모델 가용성, 라우팅, 응답 시간은 여전히 현재 서비스 상황에 따라 달라집니다.
프로젝트 루트에 .env 파일을 만들거나, 같은 변수를 환경 변수로 설정하세요:
AIHUBMIX_API_KEY=replace_with_your_api_key
프로젝트는 .env를 .gitignore로 제외합니다. 변수 이름과 예시만 공유하고, 실제 키는 절대 공유하지 마세요.

전체 워크플로는 명확한 제품 이미지 한 장에서 시작합니다.
2. 출력 목표 설정하기 및 이미지와 비디오 파라미터 분리하기
실제 파일을 편집할 때는 prompts.json 의 관련 부분이 아래와 같습니다. 기존 stills 배열과 다른 필드는 그대로 유지하세요.
{
"size": "1080x1920",
"aspect_ratio": "9:16",
"duration": 20,
"resolution": "720p",
"generate_audio": true,
"video_prompt_file": "prompts/prompt-video.txt"
}
size는 이미지 생성에 속합니다. aspect_ratio, duration, resolution, generate_audio는 비디오 생성에 속합니다. 스크립트는 전체 설정 객체를 두 엔드포인트에 모두 보내지 않고, 각각 별도의 요청을 구성합니다.
프로젝트는 다음 모델 ID를 사용합니다:
- Seedream:
doubao-seedream-5-0-pro-260628 - Seedance:
doubao-seedance-2-5-260628
포함된 스키마 스냅샷에 따르면 이미지 엔드포인트는 size를 받고, 비디오 엔드포인트는 aspect_ratio를 받습니다. 두 가지를 섞어 쓰면 요청이 거부됩니다. flow.py는 요청을 보내기 전에 캐시된 스키마 속성을 확인하지만, 이것이 완전한 파라미터 검증은 아닙니다.
3. 캐릭터 레퍼런스 세 장을 순서대로 생성하기
각 이미지는 역할이 다르며, 뒤의 이미지는 앞의 이미지에 의존합니다:
| 레퍼런스 | 내용 | 입력 |
|---|---|---|
| A: 캐릭터 초상 | 얼굴, 헤어, 의상, 공간, 조명을 확정 | 이 예시에서는 텍스트 프롬프트만 사용 |
| B: 제품을 들고 있는 모습 | 같은 인물이 라벨이 카메라를 향한 채 병을 들고 있음 | 제품 이미지 + A |
| C: 제품을 사용하는 모습 | 같은 인물이 스프레이 펌프를 누르고 있음 | 제품 이미지 + B |
프롬프트에는 캐릭터의 세부 특징이 반복적으로 포함되며, 제품의 형태, 색상, 라벨 배치, 자연스러운 손 동작을 묘사합니다.
실행:
python3 flow.py stills
결과는 assets/frame-01.jpg, frame-02.jpg, frame-03.jpg로 저장됩니다. 캐릭터 일관성, 패키지 재현도, 사용 동작의 사실감을 검토하세요.
스크립트는 이미 존재하는 파일을 건너뜁니다. 프롬프트를 변경했다면, 해당 출력물을 백업하고 옮긴 뒤 다시 실행하세요. A를 변경하면 B와 C도 다시 생성해야 할 수 있습니다.

레퍼런스는 캐릭터 정체성, 제품 표현, 제품 사용 방식을 확립합니다.
4. 이미지 호스팅하고 가상 인물 에셋 등록하기
스타터에는 작성자 계정의 에셋 ID가 포함되어 있지 않습니다. 레퍼런스는 본인 계정에 직접 등록하세요.
이 프로젝트는 등록에 공개 이미지 URL을 사용합니다. 원본 워크플로는 커밋 SHA에 고정된 GitHub raw URL을 사용했지만, 인증 없이 이미지를 직접 반환하는 호스팅이라면 어디든 사용할 수 있습니다.
GitHub /blob/ URL은 HTML 페이지를 반환하므로 이미지 URL로 사용할 수 없습니다.
이 임시 호스트를 업로드한 파일의 실제 위치로 바꾸세요:
IMAGE_BASE='https://your-public-image-host.example/campaign'
python3 flow.py check "$IMAGE_BASE/frame-01.jpg" "$IMAGE_BASE/frame-02.jpg" "$IMAGE_BASE/frame-03.jpg"
python3 flow.py assets "$IMAGE_BASE/frame-01.jpg" "$IMAGE_BASE/frame-02.jpg" "$IMAGE_BASE/frame-03.jpg"
check는 HTTP 200과 이미지 Content-Type을 확인합니다. assets는 virtual_portrait 에셋 그룹을 만들거나 재사용하고, 각 이미지를 등록한 뒤 active 상태가 될 때까지 기다리고, 에셋 ID를 state.json에 기록합니다.
이 단계는 프로젝트에서 실제로 발생한 실패에서 비롯되었습니다. 사실적인 캐릭터 URL을 비디오 엔드포인트에 직접 전달했더니 doubao_real_person_required 오류가 반환되었습니다. 이 캠페인의 인물은 AI로 생성되었으므로 virtual_portrait 분류가 올바랐습니다. 실제 인물 사진은 해당 검증 절차를 따라야 하며, 가상 인물로 표시해서는 안 됩니다.
하나의 비디오 요청에 사용되는 모든 에셋은 같은 그룹에 속해야 합니다.

레퍼런스가 생성되었고 세 에셋 모두 active 상태였습니다. 이 스크린샷을 찍을 때 비디오 작업은 아직 실행 중이었습니다.
5. 카메라 제한을 포함한 타임라인 형식의 비디오 프롬프트 작성하기
최종 프로젝트 프롬프트는 하나의 연속된 20초 샷을 네 단계로 나눕니다:
| 시간 | 캐릭터 동작 | 제품 위치 |
|---|---|---|
| 0–5초 | 카메라를 바라보며 병을 보여줌 | 얼굴 옆에 두고, 라벨이 카메라를 향함 |
| 5–10초 | 병을 들어 올리고 펌프를 누름 | 프레임 안에 머묾 |
| 10–15초 | 눈을 감고 미스트가 내려앉는 느낌을 느낌 | 프레임 하단 3분의 1 영역 |
| 15–20초 | 눈을 뜨고 제품을 다시 보여줌 | 얼굴 옆으로 돌아오고, 라벨이 카메라를 향함 |
이전 결과에서는 카메라가 너무 가까이 다가가 제품이 보이지 않았습니다. 그래서 최종 프롬프트는 카메라 움직임을 미디엄 클로즈업으로 제한하고, 제품이 계속 보이도록 요구하며, 처음 3초와 마지막 3초 동안 라벨이 읽히도록 요청합니다.
완성된 prompts/prompt-video.txt은 다음과 같습니다. 다른 제품에 적용하려면 브랜드, 패키지 설명, 사용 동작을 업데이트하세요. 이 지시문은 생성 목표이며, 결과물은 여전히 직접 검토해야 합니다.
One continuous 20-second vertical beauty commercial take, no cuts, in a sunlit minimalist vanity corner.
0-5s: the same 24-year-old East Asian woman in an oversized sage-green linen shirt over a white ribbed tank top stands at the vanity holding the translucent light-green Nature Republic Aloe Vera 92% Soothing Gel Mist beside her cheek, the label facing camera and fully legible. She looks to camera with a warm, easy smile and turns the bottle slightly so the label catches the morning light.
5-10s: she lifts the bottle just above eye level and presses the fine-mist pump. A soft cone of aloe mist sprays across her face and catches the light as a faint sparkle of micro-droplets.
10-15s: her eyes close and her chin lifts into a small contented smile as the mist settles, tiny droplets resting on her cheekbone and brow. The bottle stays visible in the lower third of the frame throughout this beat.
15-20s: she opens her eyes, brings the bottle back up beside her cheek with the label square to camera, and holds a final calm look at the lens.
Camera: one slow, smooth push-in from a chest-up framing to a mid-close framing ONLY. Do not push past a mid-close shot. The product must stay inside the frame for the entire take, and the label must be clearly legible in both the first three seconds and the last three seconds.
Look: soft diffused morning sunlight from camera left, photorealistic skin texture with real moisture on the skin, mist rendered as genuinely photographed spray rather than digital particles, premium K-beauty advertising. Keep the product packaging, colours, materials, label layout and label text exactly as in the reference images; do not redesign or re-letter the product. No text overlays, no captions, no watermarks.
Audio: a quiet bright room, one soft short pump-spray hiss, a gentle breath. No music, no voiceover.
오디오 생성은 활성화되어 있지만, 프롬프트는 실내 공간음, 스프레이 소리 한 번, 부드러운 숨소리만 요청하며 음악이나 내레이션은 포함하지 않습니다.
6. 비디오 생성 및 저장하기
에셋 등록 후 asset:// 레퍼런스를 제출하세요. 이 명령은 저장된 ID를 읽고, 각 ID를 별도의 인자로 전달합니다:
python3 - <<'PYCODE'
import json
import subprocess
import sys
from pathlib import Path
state = json.loads(Path("state.json").read_text())
refs = ["asset://" + asset_id for asset_id in state["asset_ids"]]
subprocess.run([sys.executable, "flow.py", "video", *refs], check=True)
PYCODE
인자 목록을 사용하면, 원본 프로젝트에서 여러 ID를 하나의 일반 문자열에 저장할 때 zsh에서 발생한 문제, 즉 여러 ID가 하나의 잘못된 인자로 스크립트에 전달되는 문제도 피할 수 있습니다.
스크립트는 비디오 작업 ID를 저장하고, completed 상태가 될 때까지 폴링한 뒤, 결과를 out/video.mp4로 다운로드합니다. 다른 다운로드가 이 경로를 덮어쓸 수 있으므로, 비교하고 싶은 버전은 백업해 두세요.
기존 작업을 재개하거나 결과를 다시 다운로드하려면:
python3 flow.py status
생성 응답이 유실되었다면 최근 작업 목록을 확인하고 해당 ID를 재개하세요:
python3 flow.py tasks
python3 flow.py status VIDEO_TASK_ID
새 작업을 만들기 전에 기존 작업을 먼저 찾으면 실수로 중복 생성하는 것을 방지할 수 있습니다.
7. 결과 검토 및 반복하기
원본 프로젝트에는 video-v1-10s.mp4와 최종 video.mp4가 보관되어 있습니다. 첫 번째 버전은 10초에 불과했고 제품 사용 장면이 충분하지 않아, 두 번째 프롬프트 반복 작업을 거쳤습니다.
모든 결과물을 다음 체크리스트로 검토하세요:
- [ ] 길이, 해상도, 화면 비율이 목표와 일치하는가.
- [ ] 캐릭터의 얼굴, 의상, 배경이 일관되게 유지되는가.
- [ ] 제품이 계속 보이고, 처음과 끝에서 라벨을 읽을 수 있는가.
- [ ] 다루는 동작과 스프레이 동작이 제품의 실제 사용 방식과 일치하는가.
- [ ] 병 모양, 패키지, 텍스트가 눈에 띄게 변하지 않았는가.
- [ ] 카메라가 지나치게 가까이 다가가지 않고, 오디오가 요청 내용과 일치하는가.
지속 시간이 맞지 않으면 설정과 실제 요청을 모두 점검하세요. 제품이 화면 밖으로 벗어난다면 카메라 제한을 더 강하게 설정하세요. 사용 동작이 너무 짧다면 시간과 동작을 더 명확하게 배분하세요. prompts/prompt-video.txt만 수정하는 경우에는 참조 이미지를 다시 생성할 필요가 없으며, 시각적 참조를 바꿔야 할 때만 다시 생성하고 등록하세요.
자주 묻는 질문
모델 이름이 맞아 보이는데 왜 404가 반환되나요?
원본 프로젝트에서는 축약된 Seedream 이름이 model_not_found를 반환했습니다. 마케팅용 표시 이름이 API 식별자와 같다고 가정하지 말고, 현재 엔드포인트가 허용하는 전체 API 모델 ID를 사용하세요.
브라우저에서는 이미지가 열리는데 왜 등록에 실패하나요?
URL이 HTML, 공유 페이지, 로그인 페이지가 아니라 이미지 자체를 반환하는지 확인하세요. 등록하기 전에 python3 flow.py check URL...을 실행하세요.
프롬프트를 바꿨는데 참조 이미지가 바뀌지 않은 이유는 무엇인가요?
stills는 기존 파일을 건너뜁니다. 다시 생성해야 하는 이미지는 백업한 뒤 옮기고, 이후 단계에서 사용하는 참조도 함께 다시 생성해야 하는지 확인하세요.
HTTP 200이면 동영상이 완성된 것인가요?
아닙니다. 스크립트는 작업의 status에 따라 분기하며, 작업이 completed 상태에 도달한 후에만 다운로드합니다.
첫 버전 시작하기
제품 이미지 한 장을 준비하고, AIHubMix 접근을 설정하고, 이미지 모델과 동영상 모델을 선택하세요. 그다음 Claude Code가 제품 설명과 프롬프트를 조정하도록 하세요. 참조 이미지 세 장을 생성하고 검토한 뒤 등록하고, 동영상을 만든 다음 체크리스트를 활용해 다음 반복 작업을 결정하세요.
나중에 다른 모델이 필요한 프로젝트에서도 같은 파일 구조와 워크플로를 유지하고, AIHubMix 모델 선택과 모델별 파라미터만 업데이트하면 됩니다. 이것이 여러 AI 모델을 사용하는 콘텐츠 팀에게 통합 API 서비스가 주는 실질적인 가치입니다. 작업에 따라 모델은 바뀌어도 워크플로는 재사용할 수 있습니다.



