HiAPI
블로그

튜토리얼

hiapi API에서 minimax-h3-max로 멀티 앵글 이미지-투-비디오 프롬프트 작성하기

카메라 앵글 파라미터는 없습니다—아래 프롬프트 작성 방식으로 한 장의 사진을 멀티 샷 클립으로 바꿀 수 있습니다.

Sep 12, 2026
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. 장면을 설정하는 한 문장, 그다음 번호 샷. 먼저 피사체와 장면을 한 번 설명한 뒤, 각 카메라 앵글을 각자 라벨이 붙은 비트로 나열하세요: 镜头 1 - [구도]: [동작]. 切到镜头 2 - [구도]: [동작]. '镜头 N으로 전환'은 카메라 앵글 변경을 명시적으로 요구합니다.
  2. 표준 영화 촬영 용어를 사용하세요. 低角度广角镜头, 俯视顶拍镜头, 特写, 缓慢推镜, 侧向跟拍镜头, 手持—이런 단어가 원하는 구도와 움직임을 지정합니다. '또 다른 멋진 앵글' 같은 모호한 표현은 일관성 없는 결과를 낳습니다.
  3. 길이에 맞춰 샷 수를 계획하세요. 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 인 출력 항목을 선택하고, 해당 expireAt Unix 타임스탬프(초)를 확인하세요. 종료 상태를 처리하는 같은 핸들러에서 자체 저장소로 재업로드하세요.
  • 두 가지 실패 형태를 처리하세요. 잘못된 요청 본문(지원되지 않는 필드, 범위를 벗어난 duration, 형식이 잘못된 이미지 URL)은 제출 시 400 INVALID_REQUEST 로 빠르게 실패합니다. 인증 문제는 error.code: "permission_denied" 와 함께 401 을 반환합니다. 생성 도중 실패한 작업은 폴링/콜백 응답에서 "status": "fail" 로 보고됩니다—output 을 신뢰하기 전에 status 를 먼저 확인하세요.

관련 읽기

자주 묻는 질문

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를 선택하고, 오프닝 구도를 유도하려면 프레임 이미지를 추가하세요.

영구 AI 아티팩트로 빌드 시작하기

API 키를 받아 태스크 기반의 하나의 API로 이미지, 비디오, 오디오 모델을 호출하세요.

API 문서 보기