HiAPI
블로그

튜토리얼

kling-3.0-omni/transformation API 사용법: curl과 Python으로 구현하는 비디오 리스타일링

Oct 14, 2026
kling-3.0-omni/transformation API 사용법: curl과 Python으로 구현하는 비디오 리스타일링

kling-3.0-omni/transformation은 Kling 3.0 Omni의 비디오-투-비디오 모델입니다. 소스 비디오와 텍스트 프롬프트를 제공하면 원본의 움직임과 타이밍은 유지하면서 장면, 스타일, 피사체 등 비디오의 외형을 다시 작성합니다. hiapi에서는 다른 모든 생성 모델과 동일한 통합 비동기 엔드포인트 POST /v1/tasks를 통해 호출합니다. 이 가이드는 실제로 검증된 파라미터 표, 바로 복사해 붙여넣을 수 있는 curl 요청, 완전한 Python 클라이언트(폴링 및 결과 다운로드 담당), 그리고 실제 애플리케이션에 연결하기 전에 필요한 프로덕션 패턴(콜백, 멱등성, 오류 처리)을 제공합니다.

아래의 모든 필드 이름, 열거형 값, 응답 구조는 실제 API와 대조하여 확인했습니다.

구축할 내용 + 사전 요구 사항

리스타일링 작업을 제출하고, 완료될 때까지 기다린 후, 리스타일링된 .mp4를 다운로드하는 작은 프로그램입니다. 두 가지가 필요합니다:

  1. hiapi API 키. hiapi 콘솔에서 생성하세요. 형식은 sk-...와 유사합니다. 모든 요청에는 Authorization: Bearer sk-<your-key>를 사용합니다.
  2. 공개적으로 접근 가능한 소스 비디오 URL. 모델이 서버 측에서 비디오를 다운로드하므로, 로컬 파일 경로가 아닌 공개 http(s) URL(자체 CDN, 공개 객체가 있는 R2/S3 등)이어야 합니다. URL은 하나만 허용됩니다.

모델 및 파라미터

요청의 외부 구조는 {"model": ..., "input": {...}}입니다. input의 스키마는 엄격합니다. 다음 세 필드만 허용되며, 그 외의 필드가 있으면 400이 반환됩니다.

필드 유형 필수 설명
prompt string 예 목표 스타일/장면/피사체를 설명합니다. 리스타일링 강도도 여기서 조절합니다. 숫자형 strength/fidelity 파라미터는 없습니다.
video_urls array 예 공개 소스 비디오 URL 정확히 하나(minItems는 1, maxItems는 1).
resolution string 열거형 예 720p, 1080p, 4k 중 하나.

실수하기 쉬운 몇 가지:

  • duration 파라미터는 없습니다. 출력 길이와 화면 비율은 소스 비디오를 따르며(3~15.5초), 최종 출력 길이를 기준으로 과금됩니다.
  • 모델 id 자체에 -omni가 포함되어 있습니다: kling-3.0-omni/transformation(일부 다른 Omni 엔드포인트는 kling-3.0/...을 사용합니다). 이 id를 그대로 model 값으로 사용하세요.
  • 리스타일링 강도는 프롬프트로 제어됩니다. 약간의 변경을 원하면 "약하게 리스타일링하고 얼굴 특징과 조명을 유지"라고 쓰고, 큰 변경을 원하면 "2D 셀룰로이드 카툰으로 완전히 재상상"이라고 쓰세요.

최소 실행 예제(curl)

# 1) 리스타일링 작업 생성
curl -s https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kling-3.0-omni/transformation",
    "input": {
      "prompt": "이 장면을 부드러운 종이 질감과 따뜻한 황혼 조명이 있는 수채화 애니메이션 스타일로 리스타일링하세요. 원본 카메라 움직임과 피사체는 유지하세요.",
      "video_urls": ["https://your-cdn.example.com/source-clip.mp4"],
      "resolution": "720p"
    }
  }'
# -> {"code":200,"data":{"taskId":"tk-hiapi-01..."},"message":"success"}

# 2) 작업이 종료 상태에 도달할 때까지 폴링
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01... \
  -H "Authorization: Bearer sk-<your-key>"
# data.status 순서: queued -> handling -> archiving -> success
# 성공 시 data.output[0].url이 리스타일링된 .mp4입니다.

폴링에 사용하는 작업 id는 생성 응답의 data.taskId에서 가져옵니다. 최상위 id가 아닙니다. 상태 문자열은 queued / handling / archiving / success(종료 상태) 또는 fail입니다. succeeded/completed라고 가정하지 마세요.

완전한 Python 클라이언트(생성 → 폴링 → 다운로드)

import os
import time
import requests

API_KEY = os.environ["HIAPI_KEY"]            # 당신의 sk-... 키
BASE = "https://api.hiapi.ai"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}


def create_restyle(source_video_url: str, prompt: str, resolution: str = "720p") -> str:
    body = {
        "model": "kling-3.0-omni/transformation",
        "input": {
            "prompt": prompt,
            "video_urls": [source_video_url],   # 정확히 하나의 공개 URL
            "resolution": resolution,           # "720p" | "1080p" | "4k"
        },
    }
    r = requests.post(f"{BASE}/v1/tasks", json=body, headers=HEADERS, timeout=30)
    r.raise_for_status()
    data = r.json()
    if data.get("code") != 200:
        raise RuntimeError(f"제출이 거부됨: {data}")
    return data["data"]["taskId"]


def wait_for_video(task_id: str, poll_s: int = 10, timeout_s: int = 900) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{BASE}/v1/tasks/{task_id}", headers=HEADERS, timeout=30)
        r.raise_for_status()
        data = r.json()["data"]
        status = data["status"]
        if status == "success":
            return data["output"][0]["url"]
        if status == "fail":
            raise RuntimeError(f"작업 실패: {data.get('error')}")
        time.sleep(poll_s)                      # queued / handling / archiving
    raise TimeoutError(f"{task_id}이(가) {timeout_s}초 내에 완료되지 않았습니다")


if __name__ == "__main__":
    task_id = create_restyle(
        source_video_url="https://your-cdn.example.com/source-clip.mp4",
        prompt=(
            "이 장면을 부드러운 종이 질감과 따뜻한 황혼 조명이 있는 "
            "수채화 애니메이션 스타일로 리스타일링하세요. 원본 카메라 움직임과 피사체는 유지하세요."
        ),
        resolution="720p",
    )
    print("작업:", task_id)

    url = wait_for_video(task_id)
    print("비디오 URL:", url)

    # 출력 파일은 temp.hiapi.ai에 있으며 만료됩니다(약 7일). 지금 즉시 다운로드하세요.
    clip = requests.get(url, timeout=120).content
    with open("restyled.mp4", "wb") as f:
        f.write(clip)
    print("restyled.mp4 저장됨", len(clip), "바이트")

키를 환경 변수에 넣고 실행하세요:

export HIAPI_KEY=sk-<your-key>
python restyle.py

프로덕션 패턴

잦은 폴링 대신 콜백 사용

스크립트 외의 모든 상황에서는 폴링 루프를 유지하지 않도록 webhook을 등록하세요. callback은 최상위 필드로, model 및 input과 같은 레벨이며 절대 input 안에 두면 안 됩니다:

{
  "model": "kling-3.0-omni/transformation",
  "input": {
    "prompt": "이 장면을 굵은 외곽선이 있는 2D 셀룰로이드 카툰 스타일로 리스타일링하세요. 원본 움직임은 유지하세요.",
    "video_urls": ["https://your-cdn.example.com/source-clip.mp4"],
    "resolution": "1080p"
  },
  "callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}
  • callback.when은 final(기본값)만 허용합니다. 작업이 종료 상태에 도달하면 한 번 큐에 들어가며, 성공과 실패 모두에서 트리거됩니다. 전달 의미론은 최소 한 번(at-least-once)이므로 동일한 콜백이 여러 번 도착할 수 있습니다(아래 참조).
  • 전달되는 POST 요청 본문은 GET /v1/tasks/<id>로 얻는 data 객체와 동일합니다. 따라서 핸들러는 다시 가져오지 않고도 status, output[].url, error를 읽을 수 있습니다.
  • callback을 input에 넣으면 제출 시 additional properties 'callback' not allowed 오류로 실패합니다(각 모델의 input 스키마는 엄격합니다).

멱등성과 전달 의미론

콜백은 정확히 한 번이 아니라 최소 한 번입니다. 동일한 taskId가 여러 번 도착할 수 있습니다. 핸들러의 키로 taskId를 사용하고, "완료 표시 + 비디오 저장" 단계를 멱등적으로 만드세요. hiapi는 비 2xx/타임아웃 콜백을 즉시 → +1분 → +5분 → +20분, 최대 4회 시도 리듬으로 재시도합니다. 엔드포인트가 HTTP 2xx를 반환해야 재시도가 중단됩니다.

출력을 즉시 다운로드

data.output[0].url은 temp.hiapi.ai를 가리키며 expireAt(Unix 타임스탬프, 약 7일 TTL)을 가집니다. 만료 후 객체는 삭제되며 해당 URL은 404를 반환합니다. 작업을 다시 폴링하면 동일한 URL이 반환되지만 파일이 재생성되지는 않습니다. 작업이 성공하면 즉시 바이트를 자체 스토리지로 복사하세요.

오류 처리

분기 처리해야 하는 세 가지 실패 형태:

  • 요청 오류(HTTP 400) — 평면 구조, 작업이 생성되지 않음: {"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: resolution: value must be one of '720p', '1080p', '4k'"}
  • 인증 실패(HTTP 401) — 중첩 구조: {"error":{"code":"permission_denied","type":"hiapi_error", ...}}
  • 작업 실패 — 제출은 200과 taskId를 반환하지만, 이후 폴링에서 data.status == "fail" 및 data.error가 표시됩니다. 실패한 작업은 과금되지 않습니다(작업이 최종적으로 실패하면 사전 차감액이 환불됩니다). 소스 URL에 접근할 수 없거나 다운로드할 수 없는 경우가 여기에 해당합니다.

비용

kling-3.0-omni/transformation은 출력 초 단위로 과금되며, 요율은 요청한 해상도에 따라 달라집니다(720p 초당 $0.143, 1080p 초당 $0.193, 4k 초당 $0.479, 2026년 10월 21일 확인). 비디오를 대량 처리하기 전에 실시간 hiapi 가격 페이지에서 현재 초당 요율을 확인하세요. 비디오 작업은 이미지 작업보다 비용이 훨씬 빠르게 누적됩니다.

관련 문서

자주 묻는 질문

리스타일링 강도는 어떻게 제어하나요? 파라미터가 아니라 프롬프트로 제어합니다. strength, fidelity, creativity 필드는 없습니다. 약한 편집은 "약하게 리스타일링하고 얼굴과 조명을 유지"라고 쓰고, 큰 편집은 "완전히 재상상하여

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

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

API 문서 보기