튜토리얼
hailuo 2.3 이미지-투-비디오 API 사용법: curl, Python 및 실행 가능한 요청 예시
요약
- 이것은 무엇인가: hiapi에서 hailuo-2.3/image-to-video API를 사용하는 실행 가능한 레시피입니다—정적 이미지를 짧은 동영상으로 변환합니다: 작업 생성, 작업 폴링,
.mp4다운로드. - 엔드포인트:
POST https://api.hiapi.ai/v1/tasks, 요청 본문에"model": "hailuo-2.3/image-to-video"를 작성한 다음GET /v1/tasks/<taskId>로 폴링하여 작업이 종료 상태에 도달할 때까지 기다립니다. - 두 개의 필수 입력 필드:
prompt와image_url—첫 프레임을 가리키는 단일 공개 URL(배열이 아님). duration은 문자열이며, 숫자가 아닙니다:"6"또는"10". 정수6을 전달하면 400으로 거부됩니다.- 스키마는 엄격합니다.
motion_strength,camera_movement또는resolution매개변수가 없습니다—전달하면 400으로 거부됩니다. 움직임은 전적으로 prompt를 통해 제어됩니다.
무엇을 구축하며, 무엇이 필요한가
정적 이미지—제품 사진, 캐릭터 렌더링, 사진—가 있고, hailuo-2.3이 이를 움직이게 하여 정확히 이 프레임에서 시작하는 동영상 클립을 생성하려 합니다. hailuo-2.3은 물리적으로 그럴듯한 움직임(천, 머리카락, 신체 역학)으로 유명하여 정적 이미지를 생동감 있게 만드는 데 매우 적합합니다.
두 가지가 필요합니다:
- hiapi API 키. dashboard에서 생성하세요. 키는
sk-...형태이며Authorization: Bearer헤더에 넣습니다. - 공개적으로 접근 가능한 첫 프레임 이미지 URL. API가
image_url에서 이미지를 가져오므로 인증 없이 접근 가능해야 합니다—S3/R2/CDN 링크는 가능하고,localhost경로나 만료된 서명 URL은 불가능합니다.
hiapi의 모든 생성 모델과 마찬가지로 이 모델도 비동기 작업 인터페이스를 사용합니다: POST로 작업을 생성하면 즉시 taskId를 받고, 이후 폴링 또는 콜백으로 결과를 수신합니다. 동영상에는 동기 엔드포인트가 없습니다—클립 렌더링에는 시간이 걸리며 일반적인 HTTP 타임아웃을 초과합니다.
요청 스키마
hailuo-2.3/image-to-video의 전체 입력 스키마—실제 API로 검증됨:
| 필드 | 유형 | 필수 | 설명 |
|---|---|---|---|
prompt |
string | ✅ | 장면이 아니라 움직임을 설명—장면은 이미지에서 옵니다. |
image_url |
string | ✅ | 공개 URL, 즉 첫 프레임. 단수형—image_urls가 아닙니다. |
duration |
string | 선택 | "6" 또는 "10"(초). 반드시 문자열이어야 합니다. |
prompt_optimizer |
boolean | 선택 | 플랫폼이 생성 전에 prompt를 확장하도록 합니다. |
스키마는 엄격합니다: 이 표에 없는 것은 모두 거부됩니다. motion_strength, camera_movement 또는 resolution을 보내면 다음을 그대로 받게 됩니다:
{
"code": 400,
"error_code": "INVALID_REQUEST",
"message": "invalid input: <root>: additional properties 'resolution', 'camera_movement', 'motion_strength' not allowed"
}
기억해야 할 두 가지 결과:
- 움직임 조정 손잡이가 없습니다. hailuo-2.3의 움직임 물리는 prompt로만 안내됩니다—아래 프롬프트 작성 섹션을 참조하세요.
- 이 엔드포인트에는 해상도나 종횡비 제어가 없습니다. API가 400을 반환할 매개변수에 대한 UI를 구축하지 마세요.
최소 실행 예시: curl
작업 생성:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "hailuo-2.3/image-to-video",
"input": {
"prompt": "The woman turns toward the camera and smiles; wind gently moves her hair; slow cinematic push-in",
"image_url": "https://your-cdn.example.com/first-frame.jpg",
"duration": "6",
"prompt_optimizer": true
}
}'
응답(발췌)에는 data.taskId 아래에 작업 ID가 포함됩니다:
{ "data": { "taskId": "..." } }
폴링:
curl -s https://api.hiapi.ai/v1/tasks/<taskId> \
-H "Authorization: Bearer sk-<your-key>"
클립이 렌더링되는 동안 data.status는 비종료 상태를 보고합니다. "success"로 바뀌면 동영상 URL은 data.output[0].url에 있습니다; "fail"이면 data.error.code와 data.error.message가 이유를 설명합니다.
작업이 성공하면 즉시 파일을 다운로드하세요. 출력 URL은 서명되었으며 만료 시간(expireAt)이 있습니다—바이트를 자체 저장소에 저장하고 작업 URL을 절대 핫링크하지 마세요.
최소 실행 예시: Python
동일한 흐름의 전체 스크립트—생성, 폴링, 다운로드:
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
def create_task() -> str:
payload = {
"model": "hailuo-2.3/image-to-video",
"input": {
"prompt": (
"The cat stretches, hops off the windowsill, and walks toward "
"the camera; soft afternoon light, subtle handheld camera sway"
),
"image_url": "https://your-cdn.example.com/first-frame.jpg",
"duration": "6", # string, not int: "6" or "10"
"prompt_optimizer": True,
},
}
r = requests.post(API_BASE, json=payload, headers=HEADERS, timeout=30)
task_id = (r.json().get("data") or {}).get("taskId")
if not task_id:
raise RuntimeError(f"create failed ({r.status_code}): {r.text[:300]}")
return task_id
def wait_task(task_id: str, timeout_s: int = 900, poll_s: int = 10) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
task = r.json().get("data") or {}
status = task.get("status")
if status == "success":
return task
if status == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')}: {err.get('message')}")
time.sleep(poll_s)
raise TimeoutError(f"task {task_id} not finished after {timeout_s}s")
def main() -> None:
task_id = create_task()
print("task created:", task_id)
task = wait_task(task_id)
url = task["output"][0]["url"]
# The URL is signed and expires -- download immediately, store the bytes yourself.
video = requests.get(url, timeout=120).content
with open("hailuo-output.mp4", "wb") as f:
f.write(video)
print("saved hailuo-output.mp4")
if __name__ == "__main__":
main()
동영상 작업은 이미지 작업보다 눈에 띄게 오래 실행되므로 스크립트는 10초마다 폴링하고 15분의 넉넉한 상한을 설정합니다. ~5초마다보다 더 공격적으로 폴링하지 마세요—렌더링이 더 빨라지지 않습니다.
움직임을 제어하는 prompt 작성
움직임 매개변수가 없으므로 prompt가 유일한 방향타입니다—hailuo-2.3에서는 이것으로 충분합니다. 세 가지 경험 법칙:
- 외형이 아니라 움직임을 설명하세요. 모델은 이미 이미지를 보았습니다.
"a beautiful woman in a red dress"는 prompt를 낭비합니다;"she turns her head slowly to the left as the camera pushes in"가 이를 잘 활용합니다. - 카메라 움직임을 평이한 언어로 설명하세요.
"slow push-in","orbit right","handheld sway","static camera"—이것들은 (존재하지 않는)camera_movement필드가 아니라 prompt 텍스트에 작성해야 합니다. - 확신이 없으면
prompt_optimizer의 도움을 받으세요."prompt_optimizer": true로 설정하면 플랫폼이 생성 전에 짧은 prompt를 확장합니다—짧은 입력에 좋은 기본값입니다. 정교하게 작성한 표현을 엄격히 따르고 싶다면 끄세요.
프로덕션 고려사항
폴링보다 콜백을 우선하세요. 작업 생성 시 콜백을 첨부하면 hiapi가 종료 상태 결과를 엔드포인트로 POST하므로 열린 루프를 유지할 필요가 없습니다:
{
"model": "hailuo-2.3/image-to-video",
"input": { "...": "..." },
"callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
"when": "final"은 종료 상태에서 한 번만 트리거됩니다. 폴링은 스크립트와 노트북에 적합합니다; 콜백이 서버의 올바른 형태입니다—동영상 렌더링이 충분히 길어 폴링에 블로킹된 worker는 실질적인 비용입니다.
다음 오류를 명시적으로 처리하세요:
401및"code": "permission_denied"—키에 문제가 있거나 해당 키에 이 모델을 사용할 권한이 없습니다. 메시지에 지원팀에 보낼 수 있는request_id가 포함됩니다.400 INVALID_REQUEST—스키마 위반. 메시지는 정확합니다, 예:duration: got number, want string또는image_url: missing required field "image_url". 그대로 기록하세요.- 작업 생성 시
402—잔액 부족. 동영상은 작업당 이미지보다 높게 과금되므로 이미지 작업이 여전히 정상적으로 실행되는 키가 동영상 생성에서 먼저 실패할 수 있습니다. 충전하거나 dashboard에서 사용량을 확인하세요. - 작업이
"fail"로 전환됨—생성 측 실패;data.error를 확인하세요. 특히 이미지-투-비디오의 흔한 원인:image_url을 가져올 수 없음(비공개 버킷, 만료된 서명 URL).
재시도에 대해 멱등성을 확보하세요. 프로세스가 생성과 다운로드 사이에 죽으면 순진한 재시작은 두 번째 렌더링을 생성(및 과금)합니다. create_task가 반환된 직후 taskId를 영속화하고, 재시작 시 다시 생성하지 않고 폴링을 계속하세요.
관련 읽기
- hailuo-2.3/image-to-video 모델 페이지—playground, 초당 과금 및 실시간 스키마.
- hailuo-2.3-fast/image-to-video—저지연 등급, 동일한 작업 워크플로우.
- hailuo-2.3/text-to-video—소스 이미지 없이 prompt만으로 생성.
- hiapi 문서—콜백을 포함한 전체 작업 인터페이스 설명.
- 가격—모든 모델의 현재 초당 동영상 요금.
자주 묻는 질문
hailuo-2.3 이미지-투-비디오는 어떤 길이를 지원하나요?
두 가지: "6" 및 "10"초, 문자열로 전달. 다른 값—또는 동일 값을 숫자로 작성—은 400 INVALID_REQUEST를 반환합니다.
왜 "duration": 6은 실패하고 "duration": "6"은 작동하나요?
스키마는 duration을 문자열 열거형으로 정의합니다. API는 명확히 알려줍니다: duration: got number, want string. 이는 이 엔드포인트에서 가장 흔한 400입니다.
출력 해상도나 종횡비를 설정할 수 있나요?
아니요. 엔드포인트는 resolution 또는 aspect_ratio 필드를 노출하지 않으며, 둘 중 하나를 보내면 400입니다—스키마는 알 수 없는 속성을 무시하지 않고 거부합니다.
카메라 움직임이나 움직임 강도를 어떻게 제어하나요?
prompt를 통해. camera_movement나 motion_strength 매개변수가 없습니다—카메라와 움직임 지시를 평이한 언어로 작성하세요("slow push-in", "she walks toward the camera").
여러 참조 이미지를 전달할 수 있나요?
아니요—image_url은 단일 문자열, 즉 첫 프레임입니다. 이는 image_urls 배열을 받는 hiapi의 다른 일부 모델과 다릅니다; 스키마는 모델별로 정의되므로 반드시 모델 페이지를 확인하세요.
첫 프레임에 어떤 이미지 형식이 지원되나요? 표준 웹 형식(JPEG/PNG), 공개적으로 접근 가능한 URL에서 제공. 플랫폼이 해당 URL을 가져올 수 없으면 작업은 생성 후 실패합니다—따라서 제출 전에 링크가 공개적으로 접근 가능한지 확인하세요.
hailuo-2.3/text-to-video와 무엇이 다른가요?
텍스트-투-비디오는 prompt만으로 장면을 발명합니다; 이미지-투-비디오는 첫 프레임을 이미지에 고정하고 그로부터 애니메이션합니다. 작업 수명 주기는 완전히 동일합니다—입력 스키마만 다릅니다(여기서는 image_url이 필수이고, 텍스트-투-비디오에는 이미지 필드가 전혀 없습니다).
비용은 얼마인가요? 동영상은 출력 초 단위로 과금되며 요금은 변동합니다—현재 수치는 hailuo-2.3/image-to-video 모델 페이지와 가격 페이지를 확인하세요.
관련 글
모든 아티클 보기 →-
튜토리얼
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 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드