HiAPI
블로그

튜토리얼

HiAPI로 HappyHorse 1.1 텍스트-투-비디오 API 호출하기: 바로 쓸 수 있는 curl + Python 튜토리얼

Jun 27, 2026
HiAPI로 HappyHorse 1.1 텍스트-투-비디오 API 호출하기: 바로 쓸 수 있는 curl + Python 튜토리얼
모델
happyhorse-1.1

HappyHorse 1.1은 알리바바의 텍스트-투-비디오 모델입니다: 720p / 1080p 비디오 클립을 지원하며, 길이는 3–15초이고, 한 번의 호출로 네이티브 오디오가 생성됩니다(별도의 사운드트랙 단계 불필요). HiAPI는 다른 모든 생성형 모델과 동일한 통합 비동기 엔드포인트를 통해 이 모델을 제공하므로, 이미 /v1/tasks에서 이미지 모델을 호출해 본 적이 있다면 달라지는 것은 모델 id와 몇 가지 input 필드뿐입니다.

이 페이지는 실제 동작하는 통합을 배포하는 데 필요한 최소한의 내용을 제공합니다: 정확한 schema, 그대로 복사할 수 있는 curl, Python 폴링 클라이언트, 그리고 프로덕션용 콜백 패턴. 또한 모델이 받지 않는 두 가지 그리 명확하지 않은 사항(audio 스위치와 seed)을 짚어 주므로, 400 하나 때문에 요청을 낭비하는 일이 없습니다.

사전 조건. HiAPI 콘솔에서 키를 발급받아 HIAPI_API_KEY로 export하세요. 모든 요청은 Authorization: Bearer sk-…로 인증됩니다; 복습이 필요하면 Authentication을 참고하세요.

엔드포인트와 요청 구조

모든 것이 하나의 엔드포인트를 통해 이루어집니다:

POST https://api.hiapi.ai/v1/tasks
Authorization: Bearer sk-<your-key>
Content-Type: application/json

요청 본문에는 최상위 키가 세 개 있습니다:

  • model — happyhorse-1.1/text-to-video (리터럴 모델 id — 슬래시를 유지하세요).
  • input — 모델 특정 필드. HappyHorse 1.1 T2V의 경우:
    • prompt (문자열, 필수) — 비디오 클립을 설명합니다.
    • resolution (720p | 1080p, 기본값 1080p).
    • aspect_ratio (16:9 | 9:16 | 3:4 | 4:3 | 4:5 | 5:4 | 1:1 | 9:21 | 21:9, 기본값 16:9).
    • duration (정수, 3–15, 기본값 5). 비용은 초 수에 따라 증가합니다.
  • callback (선택, 객체) — callback.url HTTPS 엔드포인트 + callback.when: "final". HiAPI는 각 작업의 최종 결과를 해당 주소로 정확히 한 번 POST합니다.

사용 가능해 보이지만 실제로는 불가능한 두 가지:

  • ❌ audio 필드가 없습니다. 오디오는 비디오와 함께 네이티브로 생성되며 스위치가 없습니다. "audio": true를 보내면 additional properties 'audio' not allowed가 반환됩니다.
  • ❌ seed 필드가 없습니다. 마찬가지로 400이 반환됩니다. 지금 배치 결정성이 필요하다면 여러 버전을 생성한 뒤 고르세요 — 조정할 수 있는 seed 레버가 없습니다.

최소한의 유효한 요청 본문:

{
  "model": "happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "해변을 달리는 골든 리트리버, 슬로우 모션, 잔잔한 파도, 따뜻한 노을 톤",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "duration": 5
  }
}

최소 실행 예제: curl

작업 생성 — 응답은 즉시 반환되며 taskId 하나만 포함합니다:

curl -sS -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.1/text-to-video",
    "input": {
      "prompt": "아침 안개에 잠긴 설산 호수, 느린 카메라 푸시인, 따뜻한 시네마틱 조명",
      "resolution": "1080p",
      "aspect_ratio": "16:9",
      "duration": 5
    }
  }'
# => {"code":200,"data":{"taskId":"tk-hiapi-01KW3..."},"message":"success"}

그런 다음 종료 상태에 도달할 때까지 폴링합니다:

TASK_ID=tk-hiapi-01KW3...

curl -sS "https://api.hiapi.ai/v1/tasks/$TASK_ID" \
  -H "Authorization: Bearer $HIAPI_API_KEY"
# .data.status가 "handling"인 동안 몇 초 쉬고 재시도합니다.
# 성공 시:
# {
#   "code": 200,
#   "data": {
#     "status": "success",
#     "model": "happyhorse-1.1/text-to-video",
#     "output": [
#       {"type":"video","url":"https://temp.hiapi.ai/.../...-0.mp4","expireAt":1783130616}
#     ],
#     ...
#   }
# }

mp4 URL은 임시입니다(expireAt은 약 7일 후의 Unix 타임스탬프). 작업이 성공하면 즉시 다운로드하여 영구 보관하세요 — 핫링크하지 마세요. 장기 저장을 HiAPI가 관리하길 원한다면 Output Storage 문서에서 출력을 임시 저장소에서 영구 저장소로 승격하는 방법을 확인하세요.

Python: 작고 프로덕션 형태의 클라이언트

실제 클라이언트에는 세 가지가 필요합니다: id를 반환하는 create_task, 데드라인을 두고 폴링하는 wait_task, 그리고 다운로드 단계. 이 뼈대는 세 가지를 모두 포함하며 HiAPI의 Python SDK 페이지에서 출발점에 가깝습니다 — 작게 유지하고 여기서 확장하세요.

# pip install requests
import os, time, json, requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}


def create_task(prompt: str, *, resolution="1080p", aspect_ratio="16:9", duration=5) -> str:
    body = {
        "model": "happyhorse-1.1/text-to-video",
        "input": {
            "prompt": prompt,
            "resolution": resolution,
            "aspect_ratio": aspect_ratio,
            "duration": duration,
        },
    }
    r = requests.post(API_BASE, headers={**HEADERS, "Content-Type": "application/json"},
                      data=json.dumps(body), timeout=60)
    r.raise_for_status()
    data = r.json()
    if data.get("code") != 200:
        raise RuntimeError(f"create failed: {data}")
    return data["data"]["taskId"]


def wait_task(task_id: str, *, timeout_s: int = 600, poll: int = 5) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS, timeout=30)
        r.raise_for_status()
        task = r.json().get("data") or {}
        status = task.get("status")
        if status == "success":
            return task
        if status == "fail":
            raise RuntimeError(f"task {task_id} failed: {task.get('error')}")
        time.sleep(poll)
    raise TimeoutError(f"task {task_id} did not finish within {timeout_s}s")


def download(url: str, path: str) -> None:
    with requests.get(url, stream=True, timeout=120) as r:
        r.raise_for_status()
        with open(path, "wb") as f:
            for chunk in r.iter_content(1 << 14):
                f.write(chunk)


if __name__ == "__main__":
    task_id = create_task(
        "비 온 뒤 밤의 네온 거리, 바닥에 비친 반사, "
        "사이버펑크 분위기, 느린 팬",
        resolution="720p", aspect_ratio="9:16", duration=5,
    )
    task = wait_task(task_id)
    url = task["output"][0]["url"]
    download(url, "out.mp4")
    print("saved out.mp4")

프로덕션 관련 유의 사항:

  • 상태 필드. success 또는 fail 이외의 값은 모두 진행 중으로 간주하세요(플랫폼은 현재 handling을 사용합니다).
  • raise_for_status만으로는 부족합니다. 일부 유효성 검사 오류의 경우 HiAPI는 HTTP 200을 반환하지만 code가 200이 아닙니다 — 반드시 data["code"]도 확인하세요. 새 통합에서 가장 흔한 것은 401 permission_denied이며, 이는 bearer token이 잘못되었거나 없음을 의미합니다 — HIAPI_API_KEY를 다시 export하고 콘솔에서 확인하세요.

프로덕션: 폴링보다 콜백 우선

빠른 시작을 넘어서는 모든 경우에는 HiAPI에 webhook을 제공하여 작업 완료 시 호출하도록 하세요:

{
  "model": "happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "아침 안개에 잠긴 설산 호수, 느린 카메라 푸시인, 따뜻한 시네마틱 조명",
    "resolution": "1080p",
    "aspect_ratio": "16:9",
    "duration": 5
  },
  "callback": {
    "url": "https://your-domain.com/hiapi/callback",
    "when": "final"
  }
}

콜백 핸들러가 다음을 보장하도록 하세요:

  • taskId로 중복 제거. success와 fail 모두 종료 상태입니다 — 서비스는 동일한 taskId를 두 번 받으면 무시(no-op)로 처리해야 합니다(taskId를 키로 하는 멱등 쓰기).
  • 빠르게 2xx 반환. 무거운 작업(mp4 다운로드, 영구 저장, 사용자 알림)은 큐에 넣으세요. Webhook 핸들러는 몇 초 안에 확인 응답해야 합니다.
  • GET /v1/tasks/:id를 폴백으로 유지. webhook이 유실된 경우(배포, 네트워크 흔들림), id로 멈춘 작업을 가져와 동일한 핸들러를 적용하는 대사(reconciliation) 정기 작업이 가장 간단한 안전망입니다.

한 가지 경로를 선택해야 한다면: 폴링은 일회성 스크립트와 로컬 디버깅에 적합하고, 실제 트래픽이 있는 곳이라면 어디든 콜백을 사용해야 합니다.

올바른 매개변수 선택 (resolution × aspect_ratio × duration)

요구 사항 resolution aspect_ratio duration
소셜 미디어 세로형 짧은 클립, 최저 비용 720p 9:16 5
정사각형 프리뷰 / 썸네일 루프 720p 1:1 3
가로형 내러티브 / 광고 샷 1080p 16:9 5–8
와이드스크린 키 비주얼 클립 1080p 21:9 8–12

비용은 해상도와 길이에 따라 증가합니다 — 정확한 초당 가격은 HiAPI 가격을 참고하세요. 올바른 값을 모를 때는 비워 두세요: resolution은 기본값 1080p, aspect_ratio는 기본값 16:9, duration은 기본값 5입니다.

자주 묻는 질문

HappyHorse 1.1 텍스트-투-비디오에 seed 매개변수가 있나요? 없습니다. API는 additional properties 'seed' not allowed로 seed를 거부합니다. 선택할 여러 옵션이 필요하면 동일한 prompt로 여러 작업을 제출하세요 — 서로 다른 실행은 자연스럽게 차이를 만듭니다.

오디오를 켜거나 끄려면 어떻게 하나요? 할 수 없습니다 — HappyHorse 1.1은 동일한 호출에서 네이티브로 오디오 트랙을 생성합니다. schema에 audio 스위치가 없으며, 보내면 400이 반환됩니다. 무음 클립이 필요하면 후처리에서 오디오를 제거하세요.

유효한 길이는 무엇인가요? 3에서 15(초) 사이의 정수입니다. 이 범위를 벗어나면 duration: minimum: got 0, want 3 또는 duration: maximum: got 20, want 15가 반환됩니다. 소수도 거부됩니다(필드 타입이 정수).

어떤 화면 비율을 지원하나요? 아홉 가지입니다: 16:9, 9:16, 3:4, 4:3, 4:5, 5:4, 1:1, 9:21, 21:9. 기본값은 16:9입니다.

output[].url은 얼마나 오래 유효한가요? 약 일주일입니다 — 응답에 expireAt Unix 타임스탬프가 포함됩니다. mp4를 즉시 다운로드하여 재호스팅(S3, R2, 사용자의 CDN)하거나 Output Storage API를 통해 영구 저장소로 승격하세요.

이미지-투-비디오는요? HappyHorse 1.1은 동일한 엔드포인트에 I2V 변형이 있습니다 — HappyHorse 1.1 I2V를 참고하세요. 동일한 인증, 동일한 비동기 생명주기, 다른 input schema.

전체 비동기 API 레퍼런스는 어디에 있나요? 요청 엔벨로프는 Create Task, 폴링 엔드포인트는 Get Task Detail, 표준 입력 schema는 HappyHorse 1.1 T2V 모델 페이지에 있습니다. 처음부터 시작한다면 Quickstart가 첫 호출을 끝까지 안내합니다.

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

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

API 문서 보기