튜토리얼
hiapi API에서 minimax-h3-max로 멀티 앵글 이미지-투-비디오 프롬프트 작성하기
카메라 앵글 파라미터는 없습니다—아래 프롬프트 작성 방식으로 한 장의 사진을 멀티 샷 클립으로 바꿀 수 있습니다.
minimax-h3-max 는 한 장의 사진을 5–15초 비디오로 만들 수 있지만, 해당 엔드포인트에는 '카메라 앵글', '멀티 뷰', '샷 수' 파라미터가 전혀 없습니다—파라미터 참조에 나열된 지원 입력 필드는 prompt, first_frame_image, last_frame_image, duration, resolution, aspect_ratio입니다. 카메라 지시는 prompt 에 작성하며, 이 필드는 최대 7,000자를 받습니다.
따라서 '멀티 앵글' 클립—와이드 설정 샷에서 클로즈업으로, 다시 트래킹 샷으로 전환—은 설정하는 파라미터가 아니라 작성하는 프롬프트입니다. 이 튜토리얼은 요청 구조, 하나의 생성 클립 안에서 여러 카메라 앵글을 요구하는 프롬프트 패턴, 그리고 이를 둘러싼 프로덕션급 워크플로를 다룹니다.
이 프롬프트로 생성하기 → 10초와 768P를 선택하세요. 이미지-투-비디오로 할 경우 프레임 이미지를 추가하고 aspect_ratio 를 생략하세요.
사전 준비
hiapi 콘솔에서 API 키를 발급받으세요. 아래 모든 호출은 Authorization: Bearer YOUR_API_KEY 로 공유 비동기 작업 엔드포인트 POST https://api.hiapi.ai/v1/tasks 에 인증합니다.
최소 예제: 사진 한 장, 세 가지 카메라 앵글
first_frame_image 는 피사체와 장면을 고정하여, 모델이 구체적으로 전환했다가 돌아올 콘텐츠를 갖게 합니다. 프롬프트는 각 샷을 명시적인 번호 전환으로 설명합니다. 이 모터사이클 프롬프트는 코드 예제이며 렌더링 샘플은 포함되지 않습니다.
黄昏时分潮湿的城市街道上停着一辆红色复古摩托车,霓虹灯招牌映在路面上。镜头 1 - 低角度广角:摄像机保持静止广角镜头,拍摄整辆摩托车,细雨轻轻落下。切到镜头 2 - 特写:摄像机向镀铬前灯和前轮紧密推进,缓慢向右跟拍。切到镜头 3 - 俯视顶拍:摄像机从上方垂直向下俯拍摩托车,缓慢旋转。无文字或字幕。
이 프롬프트로 생성하기 → 직접 공개 접근 가능한 모터사이클 이미지를 추가하고 10초와 768P를 선택한 뒤 aspect_ratio 를 생략하세요.
import os
import requests
import time
API_KEY = os.environ["HIAPI_API_KEY"]
BASE = "https://api.hiapi.ai/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
payload = {
"model": "minimax-h3-max",
"input": {
"prompt": (
"A red vintage motorcycle parked on a wet city street at dusk, neon signs reflecting on the pavement. "
"Shot 1 - low wide angle: the camera holds a static wide shot of the full motorcycle, rain lightly falling. "
"Cut to Shot 2 - close-up: the camera pushes in tight on the chrome headlight and front wheel, tracking slowly right. "
"Cut to Shot 3 - overhead top-down: the camera looks straight down at the motorcycle from above, slowly rotating. "
"No text or subtitles."
),
"first_frame_image": "https://your-cdn.example.com/motorcycle-source.jpg",
"duration": 10,
"resolution": "768P",
},
}
# Frame images and aspect_ratio are mutually exclusive.
def response_data(response):
response.raise_for_status()
body = response.json()
if not isinstance(body, dict) or body.get("code") != 200:
raise ValueError("Expected a JSON object with code=200")
data = body.get("data")
if not isinstance(data, dict):
raise ValueError("Expected data to be an object")
return data
# Submit once. An uncertain POST response is not a reason to submit again.
try:
resp = requests.post(
f"{BASE}/tasks", headers=HEADERS, json=payload, timeout=(10, 60)
)
created = response_data(resp)
task_id = created.get("taskId")
if not isinstance(task_id, str) or not task_id.strip():
raise ValueError("Missing data.taskId")
except (requests.RequestException, ValueError) as exc:
raise RuntimeError(
"Could not confirm task creation. Check task records before resubmitting."
) from exc
print("taskId:", task_id, flush=True)
deadline = time.monotonic() + 600
while time.monotonic() < deadline:
try:
resp = requests.get(
f"{BASE}/tasks/{task_id}", headers=HEADERS, timeout=(10, 60)
)
task = response_data(resp)
except (requests.RequestException, ValueError) as exc:
raise RuntimeError(
f"Query failed; retain taskId={task_id} and resume GET for this ID."
) from exc
state = task.get("status")
if state == "fail":
raise RuntimeError(f"Task {task_id} failed: {task.get('error')}")
if state == "success":
outputs = task.get("output")
if not isinstance(outputs, list):
raise RuntimeError(f"Task {task_id}: missing output array")
video = next(
(item for item in outputs
if isinstance(item, dict) and item.get("type") == "video"
and isinstance(item.get("url"), str) and item["url"]),
None,
)
if video is None:
raise RuntimeError(f"Task {task_id}: no video URL in output")
print(video["url"])
print("expireAt (Unix seconds):", video.get("expireAt"))
break
if state not in {"queued", "handling", "archiving"}:
raise RuntimeError(f"Task {task_id}: unexpected status {state!r}")
time.sleep(min(3, max(0, deadline - time.monotonic())))
else:
raise TimeoutError(f"Polling timed out; continue GET with taskId={task_id}")
first_frame_image 를 실제 공개 접근 가능한 HTTPS 이미지 URL로 바꾸거나 완전히 제거하고 텍스트만으로 동일한 멀티 앵글 시퀀스를 생성하세요—minimax-h3-max 는 동일한 prompt 필드로 텍스트-투-비디오와 이미지-투-비디오를 모두 처리합니다.
프롬프트 작성: 번호 샷 패턴
세 가지 선택이 목표 샷 시퀀스를 명확하게 만듭니다:
- 장면을 설정하는 한 문장, 그다음 번호 샷. 먼저 피사체와 장면을 한 번 설명한 뒤, 각 카메라 앵글을 각자 라벨이 붙은 비트로 나열하세요:
镜头 1 - [구도]: [동작]. 切到镜头 2 - [구도]: [동작].'镜头 N으로 전환'은 카메라 앵글 변경을 명시적으로 요구합니다. - 표준 영화 촬영 용어를 사용하세요.
低角度广角镜头,俯视顶拍镜头,特写,缓慢推镜,侧向跟拍镜头,手持—이런 단어가 원하는 구도와 움직임을 지정합니다. '또 다른 멋진 앵글' 같은 모호한 표현은 일관성 없는 결과를 낳습니다. - 길이에 맞춰 샷 수를 계획하세요.
duration은 5~15초의 정수입니다. 두세 샷이 현실적입니다. 다섯 가지 다른 앵글을 5초 클립에 밀어 넣으면 각 샷이 1초도 안 되어 컷 전환보다는 결함처럼 보이는 경우가 많습니다.
first_frame_image 와 last_frame_image 는 모두 선택 사항이며 서로 독립적입니다—하나, 둘 다, 혹은 둘 다 설정하지 않을 수 있습니다. 둘 중 하나라도 제공하면 aspect_ratio 를 생략하세요: 이 필드들은 상호 배타적이며, 프레임 이미지가 출력의 종횡비를 결정합니다. 또한 앵글 간에 엄격한 3D/기하학적 일관성은 보장되지 않는다는 점에 유의하세요—이것은 사진측량 파이프라인이 아니라 생성형 비디오 모델이므로, 첫 프레임으로 고정해도 컷 사이에 피사체 세부가 약간 흔들릴 수 있습니다.
프로덕션 환경에 맞게 만들기
- 스크립트 규모를 넘어서면 폴링 대신 콜백을 우선 사용하세요. 요청 본문에
"callback": {"url": "https://your-domain.com/hiapi/callback", "when": "final"}를 추가하면, 루프에서GET /v1/tasks/{taskId}를 폴링하는 대신 작업이 종료 상태에 도달할 때 hiapi가 POST로 알려줍니다. taskId로 중복 제거하세요. 폴링 응답과 콜백 모두 동일한taskId를 키로 사용합니다—같은 ID의 중복 종료 상태 알림은 여러 개의 독립 작업이 아니라 멱등으로 처리하세요.- 출력을 즉시 다운로드하세요. 성공한 작업은 임시 저장소용
data.output[].url을 반환합니다.type이video인 출력 항목을 선택하고, 해당expireAtUnix 타임스탬프(초)를 확인하세요. 종료 상태를 처리하는 같은 핸들러에서 자체 저장소로 재업로드하세요. - 두 가지 실패 형태를 처리하세요. 잘못된 요청 본문(지원되지 않는 필드, 범위를 벗어난
duration, 형식이 잘못된 이미지 URL)은 제출 시400 INVALID_REQUEST로 빠르게 실패합니다. 인증 문제는error.code: "permission_denied"와 함께401을 반환합니다. 생성 도중 실패한 작업은 폴링/콜백 응답에서"status": "fail"로 보고됩니다—output을 신뢰하기 전에status를 먼저 확인하세요.
관련 읽기
- minimax-h3-max 모델 페이지—실시간 가격, 파라미터, 그리고 코드에 연결하기 전에 브라우저에서 프롬프트를 테스트할 수 있는 플레이그라운드.
- minimax-h3-max API 문서—전체 파라미터 참조와 콜백 세부 사항.
- H3 및 H3 Max 가격—해상도 요금과 짧은 영상 예산.
- hiapi 가격—모델별 현재 초당 요금.
자주 묻는 질문
minimax-h3-max에는 전용 멀티 앵글 또는 멀티 카메라 파라미터가 있나요?
없습니다. 문서상 입력 필드는 prompt, first_frame_image, last_frame_image, duration, resolution, aspect_ratio 입니다. 카메라 앵글 필드를 추가하는 대신 prompt 안에 여러 샷을 설명하세요.
aspect_ratio 를 first_frame_image 또는 last_frame_image 와 함께 설정할 수 있나요?
아니요. aspect_ratio 는 어떤 프레임 이미지 필드와도 상호 배타적입니다. 제공된 이미지가 출력 비율을 결정합니다. 프레임 이미지를 하나라도 전달하면 aspect_ratio 를 생략하세요.
멀티 앵글 클립은 얼마나 길게 만들 수 있나요?
duration 은 5~15 정수 초를 받습니다. 두세 가지 다른 카메라 앵글은 이 창 안에 여유 있게 들어갑니다. 그 이상은 각 샷을 몇 분의 1초로 압축하는 경우가 많습니다.
피사체가 앵글 간에 완벽하게 일관성을 유지하나요?
보장되지 않습니다. minimax-h3-max 는 생성형 비디오 모델이므로 first_frame_image 가 오프닝 프레임을 고정해도 세부(정확한 텍스처, 미세한 비율)가 컷 사이에 흔들릴 수 있습니다. 픽셀 단위로 정확한 멀티 뷰 재구성이 아니라 강한 창작적 일관성으로 간주하세요.
소스 이미지 없이 텍스트만으로 멀티 앵글 클립을 생성할 수 있나요?
가능합니다—first_frame_image 와 last_frame_image 를 생략하고 prompt 에 장면과 샷을 설명하세요. 순수 텍스트 생성은 기본 가로 캔버스를 사용합니다. 세로 구도를 원하면 세로 프레임 이미지를 제공하고 aspect_ratio 를 설정하지 않거나, 편집기에서 저장된 비디오를 크롭/패딩하세요.
인증 실패는 어떻게 나타나나요?
HTTP 401 이며, 응답 본문은 {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}} 와 유사합니다. Authorization: Bearer 헤더와 키가 콘솔에서 취소되지 않았는지 꼼꼼히 확인하세요.
모터사이클 샷 시퀀스를 복사하고 이 프롬프트로 생성하기 → 10초와 768P를 선택하고, 오프닝 구도를 유도하려면 프레임 이미지를 추가하세요.
관련 글
모든 아티클 보기 →-
튜토리얼
HiAPI API로 hailuo-2.3-fast/image-to-video 호출하는 방법: curl과 Python 실전
빠르고 저렴한 이미지-투-비디오 등급의 첫 실행 요청 — 모델 ID부터 MP4 다운로드까지
-
튜토리얼
HiAPI API로 hailuo-2.3/text-to-video를 호출하는 방법: curl, Python 및 실행 가능한 요청 예시
-
튜토리얼
HiAPI에서 Kandinsky 6.0 Pro 텍스트-투-비디오 사용하기: curl 및 Python 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드