튜토리얼
HiAPI에서 kandinsky-6.0-pro/image-to-video 튜토리얼: curl + Python
HiAPI에서 사용 가능한 이미지-투-비디오 요청 보내기: 첫 프레임 업로드부터 비동기 폴링, 최종 다운로드까지
HiAPI의 image-to-video 흐름 개요
HiAPI의 모든 이미지-투-비디오 호출은 동일한 세 단계 수명 주기를 따릅니다. 이를 미리 이해하면 이어지는 튜토리얼이 신비롭기보다는 순차적으로 보일 것입니다.
단계 1: 작업 제출
kandinsky-6.0-pro/image-to-video 엔드포인트에 첫 프레임 이미지와 원하는 움직임을 설명하는 짧은 프롬프트를 담아 POST 요청을 보냅니다. 응답은 비디오 바이트 스트림이 아니라 작업을 수락하고 작업 식별자를 반환합니다. 이후 모든 작업은 이 핸들을 통해 이루어집니다.
단계 2: 상태 폴링
비디오 생성에는 시간이 걸리므로 이 엔드포인트는 비동기입니다. 작업 식별자로 상태 라우트를 호출하면 큐 대기 중, 처리 중, 성공 또는 실패 등 작업의 현재 상태를 보고합니다. 상태가 종결 상태에 도달할 때까지 짧은 간격으로 반복 확인합니다.
단계 3: 출력 가져오기
작업이 성공을 보고하면 상태 페이로드에 완성된 비디오의 위치가 포함됩니다. 이를 다운로드하여 디스크에 기록합니다. 이것이 전부입니다.
왜 이 형태가 중요한가
제출과 폴링의 분리는 우연이 아닙니다. 즉, HTTP 클라이언트가 전체 렌더링 동안 소켓을 열어둘 필요가 없고, 작업 식별자를 저장해 두었다가 떠났다가 돌아와 재개할 수 있습니다. 오류가 발생하면 상태 필드가 어디서 잘못되었는지 알려주므로 불투명한 타임아웃보다 훨씬 유용합니다.
세 단계를 기억하세요: 제출, 폴링, 다운로드. 아래 curl과 Python 예제는 동일한 시퀀스를 두 가지 방식으로 표현한 것일 뿐입니다.
첫 프레임과 API 자격 증명 준비
첫 호출 전에 문제가 생기는 곳은 보통 두 가지뿐입니다: 키와 이미지. 지금 둘 다 정리하면 튜토리얼의 나머지가 순조로울 것입니다.
API 키를 환경 변수로 설정
키를 소스 파일에 붙여넣지 마세요. 셸에서 내보내면 curl과 Python 모두 아무것도 하드코딩하지 않고 가져올 수 있습니다:
export HIAPI_API_KEY="your_api_key_here"
Windows PowerShell의 동등한 표현은 $env:HIAPI_API_KEY="your_api_key_here"입니다. 계속하기 전에 셸이 이를 읽을 수 있는지 확인하세요:
echo "$HIAPI_API_KEY" | head -c 4; echo
키의 처음 몇 문자를 볼 수 있어야 합니다. 아무것도 보이지 않는다면 변수가 현재 셸 세션에 유지되지 않은 것이며, 이는 이후 401 응답이 발생하는 흔한 원인입니다.
유효한 첫 프레임 이미지 선택
첫 프레임은 전체 비디오의 피사체, 구도, 종횡비를 결정합니다. 몇 가지 실용적 제약이 대부분의 거부를 방지합니다:
- 형식: JPEG나 PNG 같은 표준 웹 이미지 형식을 사용하세요. 희귀 코덱, 점진적 가장자리 사례, CMYK 색상 프로필을 피하세요.
- 접근성: API가 실제로 이 바이트를 읽을 수 있어야 합니다. URL을 전달하는 경우 공개적으로 접근 가능하거나 올바르게 인증되었는지 확인하세요. 인라인 데이터를 전달하는 경우 인코딩이 완전한지 확인하세요.
- 크기: 합리적인 크기의 이미지가 가장 빨리 검증됩니다. 매우 큰 파일은 요청을 느리게 하고 업로드 오류의 흔한 원인입니다.
- 내용: 움직임의 시작점으로 적합한 프레임을 선택하세요. 피사체가 명확하고 배경이 단순해야 합니다. 움직임 프롬프트는 이 프레임에서 멀어지는 방법을 설명하므로, 복잡한 프레임은 복잡한 비디오를 만듭니다.
이미지 참조 방법 결정
요청 본문은 URL 또는 인라인 인코딩 데이터로 첫 프레임을 가리킬 수 있습니다. 이미지가 있는 위치에 따라 선택하세요:
- 파일이 이미 호스팅되어 공개적으로 읽을 수 있다면 URL이 가장 깔끔한 옵션입니다.
- 이미지가 로컬 또는 비공개라면 인라인 인코딩이 더 큰 페이로드를 대가로 전체 요청을 자체 포함시킵니다.
어느 쪽이든 curl과 Python에서 이미지 참조에 동일한 변수 형태를 사용하면 두 예제가 직접 비교 가능하게 유지됩니다.
curl로 요청 보내기
다음은 완전한 제출 요청입니다. 자신의 이미지 참조와 프롬프트로 교체한 후 실행하세요.
curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image": "https://your-host.example/first-frame.jpg",
"prompt": "slow dolly-in on the subject, gentle ambient motion, stable camera",
"duration": 5,
"aspect_ratio": "16:9"
}'
각 부분의 역할
- URL은
kandinsky-6.0-pro/image-to-video모델을 특정합니다. 모델 선택은 요청 본문이 아닌 경로에 있으므로 여기서 오타가 나면 친절한 검증 메시지 대신 404가 반환됩니다. Authorization은 내보낸 환경 변수의 bearer 토큰을 전달합니다. 다른 어떤 것도 호출을 인증하지 않습니다.Content-Type: application/json은 JSON 본문이 있는 모든 POST에 중요합니다. 생략하면 일부 프록시가 페이로드가 API에 도달하기 전에 손상시킵니다.image는 첫 프레임 참조입니다. 여기서는 URL 형태를 사용하며, 이미지가 비공개라면 인라인 인코딩 문자열을 사용하세요.prompt는 움직임을 설명합니다. 이미지에 포함된 내용을 반복하지 말고 움직임과 카메라 동작에 관해 작성하세요.duration및aspect_ratio는 출력을 형성합니다. 종횡비는 첫 프레임과 일치해야 하며, 불일치하면 잘리거나 검은 여백이 추가됩니다. 청구는 생성된 출력 기준으로 측정되므로 이 설정이 비용도 결정합니다.
응답 읽기
성공적인 제출은 비디오가 아닌 작업 페이로드를 반환합니다. 여기서 작업 식별자를 캡처하세요. 나중에 상태 엔드포인트에 전달할 것입니다:
curl -sS -X POST "https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @body.json | jq -r '.id'
인라인 -d 대신 body.json 파일을 사용하면 긴 프롬프트와 인코딩된 이미지를 읽기 쉬운 상태로 유지할 수 있습니다. jq는 선택 사항이지만 응답을 한 줄로 만들어 다음 호출에 바로 붙여넣을 수 있습니다.
Python으로 동일한 엔드포인트 호출
Python 버전은 동일한 요청, 동일한 본문이며, 재사용을 위해 함수로 감싸졌습니다. 요청 본문을 curl 버전과 동일하게 유지하세요. 두 가지를 함께 보여주는 이유가 바로 그것입니다.
import os
import json
import requests
API_BASE = "https://api.hiapi.ai/v1"
ENDPOINT = f"{API_BASE}/kandinsky-6.0-pro/image-to-video"
def submit_video_job(image_ref: str, prompt: str, duration: int = 5, aspect_ratio: str = "16:9") -> str:
"""Submit a first-frame image-to-video job and return the job id."""
api_key = os.environ.get("HIAPI_API_KEY")
if not api_key:
raise RuntimeError("HIAPI_API_KEY is not set in this environment")
body = {
"image": image_ref,
"prompt": prompt,
"duration": duration,
"aspect_ratio": aspect_ratio,
}
response = requests.post(
ENDPOINT,
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json=body,
timeout=60,
)
if response.status_code >= 400:
raise RuntimeError(f"submit failed: {response.status_code} {response.text}")
payload = response.json()
return payload["id"]
if __name__ == "__main__":
job_id = submit_video_job(
image_ref="https://your-host.example/first-frame.jpg",
prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
)
print(json.dumps({"job_id": job_id}, indent=2))
Python 버전에 대한 설명
- 키가 없으면 빠르게 실패합니다. 명시적 환경 검사는 가장 흔한 오류를 원격 401이 아닌 로컬의 명확한 오류로 바꿉니다.
json=bodyvsdata=json.dumps(body).json=을 전달하면 requests가 콘텐츠 유형을 대신 설정하므로 헤더를 최소한으로 유지할 수 있습니다.data=로 변경하는 경우Content-Type을 명시적으로 설정하세요.- 넉넉한 타임아웃. 비디오 제출은 때때로 큰 이미지 페이로드 전송을 포함합니다. 너무 짧은 타임아웃은 거짓 실패를 낳습니다.
- 오류 시 응답 본문을 읽으세요. 상태 코드와 응답 본문을 함께 throw하면 실패 메시지가 API가 무엇을 반대하는지 실제로 알려줍니다.
첫 프레임이 로컬 파일이라면 읽고 base64로 인코딩한 후 해당 문자열로 submit_video_job 내의 image_ref를 교체하세요. 함수 시그니처는 변경되지 않으며, 두 호출 스타일이 동일한 요청 본문 정의를 공유하는 이유가 바로 이것입니다.
작업 폴링 및 비디오 다운로드
제출된 작업은 완성된 비디오가 아닙니다. 작업이 종결 상태에 도달할 때까지 폴링한 후 다운로드하세요.
폴링 루프
import time
import requests
def wait_for_video(job_id: str, interval: float = 10.0, max_wait: float = 600.0) -> str:
"""Poll the job until it finishes; return the output URL."""
import os
api_key = os.environ["HIAPI_API_KEY"]
url = f"https://api.hiapi.ai/v1/kandinsky-6.0-pro/image-to-video/{job_id}"
headers = {"Authorization": f"Bearer {api_key}"}
deadline = time.time() + max_wait
while time.time() < deadline:
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
payload = response.json()
status = payload.get("status")
if status == "succeeded":
return payload["output"]
if status == "failed":
raise RuntimeError(f"job failed: {payload.get('error', 'unknown error')}")
time.sleep(interval)
raise TimeoutError(f"job {job_id} did not finish within {max_wait}s")
세 가지 세부 사항이 이 루프를 잘 작동하게 합니다:
- 운에 맡기지 말고 간격을 두고 백오프하세요. 약 10초의 고정 수면이 합리적인 시작점입니다. 타이트한 루프에서 엔드포인트를 마구 두드리지 마세요.
- 모든 종결 상태를 처리하세요.
succeeded는 출력을,failed는 오류 메시지를 제공합니다. 둘 다 종료로 처리해야 합니다. 성공만 확인하는 루프는 죽은 작업에서 마감 시간까지 계속 돌 것입니다. - 대기 시간을 제한하세요.
max_wait는 스크립트가 멈춘 작업 뒤에서 영원히 실행되지 않고 종료되도록 보장합니다.
완성된 비디오 다운로드
출력 URL을 받으면 전체 파일을 메모리에 로드하지 말고 스트리밍으로 디스크에 쓰세요:
def download_video(output_url: str, path: str = "result.mp4") -> str:
with requests.get(output_url, stream=True, timeout=120) as response:
response.raise_for_status()
with open(path, "wb") as handle:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
handle.write(chunk)
return path
모든 부분을 결합하면:
job_id = submit_video_job(
image_ref="https://your-host.example/first-frame.jpg",
prompt="slow dolly-in on the subject, gentle ambient motion, stable camera",
)
output_url = wait_for_video(job_id)
saved = download_video(output_url, "kandinsky_result.mp4")
print(f"saved to {saved}")
프로덕션 환경에서는 제출이 성공하는 즉시 job_id를 저장하세요. 프로세스가 재시작되면 저장된 식별자로 폴링 루프에 다시 진입할 수 있으며, 새 제출에 비용을 지불할 필요가 없습니다.
일반적인 요청 및 작업 오류 문제 해결
대부분의 실패는 키, 이미지 또는 작업 상태의 세 가지 범주에 속합니다. 다른 것을 변경하기 전에 범주를 먼저 분리하세요.
키 거부
증상: 작업 생성 전 인증 또는 권한 부여 오류.
- 변수가 현재 셸에서 실제로 내보내졌는지 확인하세요:
echo "$HIAPI_API_KEY". - 키와 함께 공백이나 줄 바꿈이 붙여넣어지지 않았는지 확인하고 제거하세요.
- 헤더가
Authorization으로 표기되고 값이Bearer로 시작하며 뒤에 공백이 오는지 확인하세요. - curl은 되지만 Python은 안 된다면 동일한 인터프리터에서
os.environ.get("HIAPI_API_KEY")를 출력해 보세요. 변수가 셸에는 있지만 스크립트가 상속하는 환경에는 없을 수 있습니다.
이미지 거부
증상: 제출 시 검증 오류 또는 작업이 즉시 실패.
- 형식 오류 또는 희귀 형식. 표준 JPEG 또는 PNG로 다시 내보내고 재시도하세요. CMYK 프로필과 특이한 코덱이 흔한 원인입니다.
- URL 접근 불가. 시크릿 브라우저 창에서 이미지 URL을 열어 보세요. 바이트를 얻지 못한다면 API도 얻지 못합니다.
- 인라인 인코딩 손상. 로컬에서 base64로 인코딩했다면 문자열을 한 번 디코딩해 유효한 이미지인지 확인한 후 전송하세요.
- 종횡비 불일치. 비디오가 잘리거나 검은 여백이 생겨 돌아온다면 사후에 출력과 씨름하지 말고
aspect_ratio를 첫 프레임과 맞추세요.
작업이 끝나지 않거나 실패
증상: 상태가 queued/processing에 계속 머물거나 failed를 보고.
- error 필드를 읽으세요. 실패한 작업은 메시지를 담고 있습니다. 일반적으로 어떤 필드나 조건이 잘못되었는지 지적합니다. 추측하지 말고 전체 상태 페이로드를 기록하세요.
- 비동기 설계를 존중하세요. 몇 초 기다린 후 확인하는 것은 정상입니다. 2초 후 포기하는 타이트한 재시도 루프는 상태 메커니즘이 아닙니다.
- 대기 시간을 제한하세요. 작업이 합리적인 상한을 초과하면 실패로 처리하고 작업 ID를 노출한 후 새 작업을 제출하세요. 영원히 폴링하지 마세요.
- 알려진 정상 호출과 비교하세요. 사용자 정의 이미지가 실패하면 이 튜토리얼 앞부분의 정확한 curl에 작은 공개 이미지와 짧은 프롬프트로 실행해 보세요. 성공하면 문제는 입력에 있고, 그것도 실패하면 문제는 자격 증명이나 요청 형태에 있습니다.
성공 후 다운로드 오류
작업이 succeeded를 보고했지만 다운로드가 실패하면 출력 URL이 만료되었거나 접근 제어가 적용되었을 수 있습니다. 만료된 URL을 재시도하지 말고 작업을 다시 폴링하여 새 출력 위치를 얻으세요.
이 범주를 순서대로 처리하세요: 키, 그다음 이미지, 그다음 작업 상태. 각 오류는 원인을 빠르게 좁혀 줍니다. 전체 루프는 이것입니다: 첫 프레임 제출, 완료까지 폴링, 결과 다운로드.
관련 글
모든 아티클 보기 →-
튜토리얼
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 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드