튜토리얼
HiAPI API로 hailuo-2.3/text-to-video를 호출하는 방법: curl, Python 및 실행 가능한 요청 예시
hailuo-2.3/text-to-video 엔드포인트의 역할
텍스트 프롬프트가 있고 이를 바탕으로 짧은 영상 클립을 생성하고 싶다면 hailuo-2.3/text-to-video가 바로 찾던 엔드포인트입니다. 장면, 주체 그리고 원하는 움직임을 설명하는 자연어 프롬프트를 받아 생성된 영상 클립을 반환합니다. 이 모델은 짧은 출력에 맞춰 튜닝되었으므로, 긴 서사보다는 짧고 자체적으로 완결되는 순간을 요청할 때 가장 좋은 결과를 냅니다.
HiAPI에서는 다른 비동기 생성 엔드포인트와 동일한 패턴을 따릅니다. 요청을 보내면 서비스가 작업을 접수하고, 결과가 준비될 때까지 폴링합니다. 따라서 이 엔드포인트는 백엔드 파이프라인, 콘텐츠 도구, 프로토타입 생성기, 배치 작업, 또는 사람이 영상 편집기 앞에 앉지 않고도 몇 초짜리 영상을 필요할 때 생성해야 하는 모든 상황에 적합합니다.
요청에는 프롬프트와 소수의 생성 제어 파라미터가 담기고, 응답에는 작업 식별자가 담긴 뒤 완성된 영상의 URL이 이어집니다. GPU나 모델 가중치를 관리할 필요가 없습니다. HiAPI가 연산을 처리하고 출력 링크를 반환합니다. 다른 텍스트 투 비디오 API를 사용해 보았다면 전체 형태가 익숙할 것이며, 다만 hailuo-2.3의 프롬프트 스타일은 단순한 시각적 설명보다 물리적 움직임에 대한 사고를 더 보상합니다(자세한 내용은 후반부에서 설명합니다).
사전 조건과 API 자격 증명
첫 호출 전에 다음 세 가지를 준비하세요:
- HiAPI 계정의 API 키. 비밀번호처럼 다루세요. 버전 관리에 넣지 말고 환경 변수에서 불러오며, 유출되면 교체하세요.
- HTTP 클라이언트. 아래 셸 예시는
curl만 필요합니다. Python 예시는 Python 3.8+ 및requests라이브러리(pip install requests)가 필요합니다. - HiAPI API 기본 URL. 모든 요청은 HiAPI API 호스트로 전송되며, 엔드포인트 경로는
hailuo-2.3/text-to-video입니다.Authorization헤더에 bearer 토큰을 담아 인증합니다.
키를 환경 변수에 설정하여 코드에 노출되지 않게 하세요:
export HIAPI_API_KEY="your_api_key_here"
Python에서는 os.environ["HIAPI_API_KEY"]로 읽을 수 있습니다. curl에서는 $HIAPI_API_KEY로 같은 변수를 참조합니다.
미리 정해야 할 것이 하나 더 있습니다. 생성된 영상을 어디에 저장할지입니다. API는 출력 URL을 반환하며, 이 URL은 즉시 가져와 자체 버킷이나 파일 시스템에 저장해야 합니다. 해당 URL이 영구 자산이라고 가정하는 파이프라인을 만들지 마세요.
curl로 실행하는 요청
다음은 텍스트 투 비디오 작업을 제출하는 완전한 curl 호출입니다. 프롬프트를 자신의 장면 설명으로 바꾸세요. 요청 본문은 JSON이며, 핵심 필드는 프롬프트와 길이 및 출력 형태를 제어하는 생성 파라미터입니다.
curl -X POST "https://api.hiapi.ai/v1/hailuo-2.3/text-to-video" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "유리 구슬이 나무 경사를 따라 굴러 내려가다 가속하여 돌바닥에 떨어지고, 두 번 튕긴 뒤 멈춘다",
"duration": 6
}'
성공적으로 제출되면 작업 식별자가 담긴 JSON 객체가 반환됩니다. 대략 다음과 같습니다:
{
"id": "job_abc123",
"status": "queued"
}
핵심은 id입니다. 생성은 동기적으로 완료되지 않습니다. 엔드포인트는 작업을 큐에 넣고 즉시 반환합니다. id를 저장하세요. 이 값을 사용해 상태를 폴링하고 최종적으로 영상 URL을 가져옵니다.
인증 오류가 발생하면 키가 같은 셸 세션에서 내보내졌는지 확인하세요. 검증 오류가 발생하면 JSON 요청 본문 형식이 올바른지, 프롬프트가 존재하는지 확인하세요. 429 응답은 요청을 너무 빠르게 보냈다는 뜻이므로 백오프해야 합니다. 자세한 내용은 프로덕션 환경 부분에서 다룹니다.
Python에서 동일한 호출
Python 버전은 같은 작업을 하지만 파이프라인에 넣기 쉽도록 재사용 가능한 함수로 감쌉니다. 작업을 제출하고 작업 식별자를 반환합니다.
import os
import requests
HIAPI_BASE = "https://api.hiapi.ai/v1"
def submit_text_to_video(prompt: str, duration: int = 6) -> str:
"""hailuo-2.3/text-to-video 작업을 제출하고 작업 id를 반환합니다."""
api_key = os.environ["HIAPI_API_KEY"]
response = requests.post(
f"{HIAPI_BASE}/hailuo-2.3/text-to-video",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json={"prompt": prompt, "duration": duration},
timeout=30,
)
response.raise_for_status()
data = response.json()
return data["id"]
if __name__ == "__main__":
job_id = submit_text_to_video(
"유리 구슬이 나무 경사를 따라 굴러 내려가다 가속하여 돌바닥에 떨어지고, 두 번 튕긴 뒤 멈춘다"
)
print("submitted job:", job_id)
몇 가지 세부 사항은 유지할 가치가 있습니다:
raise_for_status()는 비 2xx 응답을 예외로 전환하며, 이는 파이프라인에서 원하는 동작입니다. 생성되지 않은 작업을 폴링하는 것보다 제출 단계에서 크게 실패하는 편이 낫습니다.- 제출 요청의 timeout은 의도적으로 짧게 설정했습니다. 제출은 빨라야 하며, 긴 대기는 여기가 아니라 폴링 단계에서 발생합니다.
duration파라미터는 별도 파라미터이므로 호출자가 요청 구성 로직을 반복하지 않고도 더 짧거나 긴 클립을 요청할 수 있습니다.
이 함수가 반환되면 상태 폴링을 계속하는 데 필요한 모든 것을 갖춘 것입니다.
6-10초 클립을 위한 운동 물리 프롬프트 작성
짧은 클립은 가차 없습니다. 6~10초 안에 캐릭터를 세우고 세계를 구축하며 줄거리를 마무리할 수는 없습니다. 따라서 가장 효과적인 프롬프트는 명확한 물리적 결과를 수반하는 단일 연속 동작을 설명합니다. 프롬프트를 이야기가 아니라 한순간의 샷 설명으로 생각하세요.
주체와 동작으로 시작하기
무엇이 움직이고 무엇을 하는지부터 시작하세요. "유리 구슬이 나무 경사를 따라 굴러 내려가다"는 모델에게 주체, 재질, 진행 방향을 즉시 제공합니다. "아름다운 장면" 같은 모호한 시작은 애니메이션할 대상에 아무것도 주지 않습니다.
겉모습이 아니라 힘을 설명하기
운동 물리 프롬프트란 작용하는 힘을 말하는 것입니다. 중력, 마찰, 운동량, 무게, 탄성입니다. 구르다, 가속하다, 튕기다, 멈추다, 흔들리다, 쏟아지다, 튀다, 찢어지다 같은 단어는 물리 모델을 암시합니다. 튕기는 물체라면 몇 번 튕기고 어디서 멈추는지 명시하세요. 떨어지는 물체라면 무엇 위에 떨어지는지, 부서지는지, 움푹 들어가는지, 튕겨 오르는지 설명하세요.
카메라를 명확하고 단순하게
고정 카메라나 한 번의 느린 카메라 이동이면 보통 짧은 클립에 충분합니다. 카메라와 주체가 모두 복잡한 일을 하면 클립이 어수선해지고 움직임이 잡음처럼 보입니다. 카메라 유형은 동작에 중요할 때만 지정하세요. 클로즈업, 와이드, 팔로우 샷 등입니다.
사건의 호 구성하기
6–10초 클립에 유용한 템플릿은 준비 → 동작 → 결과입니다. 구슬이 경사 꼭대기에 있고, 굴러 내려가며 가속하고, 떨어져 두 번 튕긴 뒤 멈춥니다. 이 호는 모델에게 시작, 중간, 끝을 제공하며 모두 클립 길이에 맞습니다. 관련 없는 여러 동작을 요구하지 마세요. 잘 설명된 하나의 물리적 사건이 어중간하게 끝나는 세 개의 사건보다 훨씬 잘 읽힙니다.
마지막으로 프롬프트를 구체적으로 유지하세요. 재질, 조명, 표면 질감은 모델이 움직임을 정착시키는 데 도움을 줍니다. 나무 위의 구슬과 얼음 위의 구슬은 다르게 움직이며, 이를 명시하면 결과를 유도합니다.
폴링으로 비동기 작업 처리
생성에는 시간이 걸리므로 이 엔드포인트는 비동기입니다. 작업을 제출하면 id를 받고, 이후 작업이 종료 상태에 도달할 때까지 상태 엔드포인트를 폴링합니다. 견고한 폴링 루프는 세 가지를 처리합니다. 간격, 타임아웃, 오류 노출입니다.
import time
import requests
HIAPI_BASE = "https://api.hiapi.ai/v1"
def wait_for_video(job_id: str, api_key: str, interval: float = 3.0, max_wait: float = 600.0) -> str:
"""작업이 완료될 때까지 폴링하고 출력 영상 URL을 반환합니다."""
deadline = time.time() + max_wait
url = f"{HIAPI_BASE}/hailuo-2.3/text-to-video/{job_id}"
while time.time() < deadline:
response = requests.get(
url,
headers={"Authorization": f"Bearer {api_key}"},
timeout=30,
)
response.raise_for_status()
data = response.json()
status = data.get("status")
if status == "completed":
return data["output"]["video_url"]
if status in ("failed", "cancelled"):
raise RuntimeError(f"작업 {job_id}이(가) 상태 {status}로 종료되었습니다: {data.get('error')}")
time.sleep(interval)
raise TimeoutError(f"작업 {job_id}이(가) {max_wait}초 내에 완료되지 않았습니다")
이 루프에 대한 설명:
- 간격을 두고 폴링하고, 타이트 루프는 피하세요. 검사 사이에 몇 초를 두면 충분하며 API를 과도하게 두드리지 않습니다.
- 항상 총 대기 시간을 제한하세요. 멈춘 작업이 워커를 영원히 붙잡아 두어서는 안 됩니다. 여기서
max_wait값은 보수적입니다. 클립 길이와 큐 상황에 맞게 조정하세요. failed를 실제 분기로 취급하세요. 무작정 재시도하지 말고 오류 페이로드를 노출하세요. 프롬프트나 파라미터 문제는 스스로 해결되지 않습니다.- 원시 응답이 아니라 영상 URL을 반환하세요. 이 함수의 호출자는 응답 구조를 알 필요가 없어야 합니다.
더 무거운 워크로드에서는 제출과 폴링 단계를 서로 다른 워커 프로세스에 두세요. 한 워커는 작업을 큐에 넣고 작업 ID를 저장하며, 다른 워커는 폴링과 다운로드를 담당합니다. 이렇게 하면 요청 지연과 생성 시간이 분리됩니다.
출력 다운로드와 저장
폴링이 영상 URL을 반환하면 바이트를 가져와 영구 위치에 씁니다. 즉시 수행하세요. 반환된 URL은 전달 링크이지 영구 자산 저장소가 아닙니다. 전체 파일을 메모리에 로드하지 말고 스트리밍으로 다운로드하며, 임시 경로에 먼저 쓴 뒤 이름을 바꿔 부분 다운로드가 완료된 파일처럼 보이지 않게 하세요.
import os
import tempfile
import requests
def download_video(video_url: str, dest_path: str) -> None:
"""완성된 영상을 dest_path에 원자적으로 스트리밍합니다."""
os.makedirs(os.path.dirname(dest_path) or ".", exist_ok=True)
with requests.get(video_url, stream=True, timeout=120) as response:
response.raise_for_status()
fd, tmp_path = tempfile.mkstemp(dir=os.path.dirname(dest_path) or ".")
try:
with os.fdopen(fd, "wb") as f:
for chunk in response.iter_content(chunk_size=1 << 16):
f.write(chunk)
os.replace(tmp_path, dest_path)
except Exception:
if os.path.exists(tmp_path):
os.unlink(tmp_path)
raise
api_key = os.environ["HIAPI_API_KEY"]
video_url = wait_for_video("job_abc123", api_key)
download_video(video_url, f"out/{'job_abc123'}.mp4")
몇 가지 실용적 선택:
- 파일 이름을 작업 ID로 지정하세요. 안정적이고 충돌에 강한 키가 생기며, 파일을 생성한 요청과 다시 연결하기가 매우 쉬워집니다.
- 영상과 함께 메타데이터를 저장하세요. 원본 프롬프트, 길이, 타임스탬프를 별도 JSON이나 데이터베이스에 보관하세요. 6개월 뒤에는 어떤 클립이 무엇으로 생성되었는지 알고 싶을 것입니다.
- 프로덕션에서는 객체 스토리지에 업로드하세요. 로컬 디스크 쓰기는 프로토타입에는 괜찮지만, 실제 파이프라인은 파일을 버킷에 푸시하고 객체 키를 기록하여 워커 재시작 후에도 영상이 살아남게 해야 합니다.
프로덕션 환경 팁과 흔한 실패 모드
대부분의 첫 통합은 같은 몇 군데에서 문제가 생깁니다. 다음은 주의할 사항입니다.
올바른 대상에 재시도하기
일시적 장애, 즉 네트워크 오류, 타임아웃, 429, 5xx 응답에는 지수 백오프와 지터를 사용해 재시도하세요. 4xx 검증 오류에는 재시도하지 마세요. 잘못된 프롬프트나 잘못된 파라미터는 매번 같은 방식으로 실패합니다. 생성 작업 자체가 실패하면 오류를 노출하고 재제출 여부를 신중히 결정하세요.
제출과 폴링 분리
프로덕션에서는 제출과 폴링이 서로 다른 단계여야 하며, 보통 서로 다른 프로세스에서 수행됩니다. 제출 성공 직후 작업 ID를 큐나 데이터베이스에 저장하세요. 워커가 충돌하더라도 작업을 잃지 않고 폴링을 재개할 수 있습니다.
모든 곳에 타임아웃 설정
제출 요청, 상태 폴링, 파일 다운로드 모두 각각 타임아웃이 있어야 합니다. 다운로드 단계에 타임아웃이 없는 것은 워커가 멈추는 전형적인 원인입니다.
프롬프트를 모델의 강점 범위 안에 유지
6~10초 범위에서는 단일하고 물리적으로 타당한 동작을 요청하세요. 프롬프트가 너무 많은 것을 요구하면 움직임이 탁한 어수선한 클립을 얻게 됩니다. 출력 품질이 일관되지 않으면 파라미터를 바꾸기 전에 먼저 프롬프트를 줄이고 동작을 단순화하세요.
자격 증명을 올바르게 처리
API 키는 환경 변수나 비밀 관리자에서 불러오고, 커밋된 파일에서는 절대 불러오지 마세요. 환경마다 다른 키를 사용하여 유출된 개발 키가 프로덕션에 닿지 않게 하세요.
URL 만료 가정에 주의
프로덕션에서 가장 흔한 실수는 반환된 영상 URL을 영구 링크로 취급하여 몇 달 뒤 사용자 인터페이스에 그대로 렌더링하는 것입니다. 파일을 다운로드하고 다시 호스팅하는 것을 작업의 일부로 삼고, 자체 URL을 저장하세요.
이런 습관이 있으면 통합은 매우 작아집니다. 제출, 폴링, 다운로드, 저장입니다.
관련 글
모든 아티클 보기 →-
튜토리얼
HiAPI API로 hailuo-2.3-fast/image-to-video 호출하는 방법: curl과 Python 실전
빠르고 저렴한 이미지-투-비디오 등급의 첫 실행 요청 — 모델 ID부터 MP4 다운로드까지
-
튜토리얼
HiAPI에서 Kandinsky 6.0 Pro 텍스트-투-비디오 사용하기: curl 및 Python 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드
-
튜토리얼
HiAPI API로 kling-4.0/text-to-video를 사용하는 방법: curl, Python 및 실행 가능한 요청 예제
개발자를 위한 실전 가이드: 영화적 프롬프트, 동기화 오디오, 비동기 폴링 및 출력 다운로드