튜토리얼
hiapi API를 사용해 이미지 해상도를 높이는 방법: 4K 업스케일 워크플로
2K/4K 생성형 업스케일을 위한 실행 가능한 이미지 대 이미지 방식으로, Python, 콜백, 오류 처리를 포함합니다.
저해상도 제품 이미지, 작은 AI 생성 썸네일, 또는 오래된 스캔본이 있는데 선명한 2K/4K 버전이 필요하다면, 별도의 초해상도 서비스를 갖출 필요가 없습니다. hiapi의 통합 /v1/tasks 엔드포인트를 사용하면 여러 이미지 모델에 동일한 요청을 보낼 수 있습니다. 이 모델들은 기존 이미지를 받아 더 높은 해상도 등급으로 다시 그립니다. 본 방식은 전체 실행 가능한 흐름을 보여줍니다: 작업 제출, 폴링(또는 콜백 수신)으로 결과 가져오기, 그런 다음 업스케일된 파일을 다운로드합니다.
한 가지 솔직히 말씀드리면: hiapi는 현재 (아직) 픽셀 보존형 초해상도 전용 모델을 공개하지 않았습니다. 여기서 얻는 것은 생성형 업스케일입니다. 모델이 더 높은 목표 해상도에서 소스 이미지를 다시 그리며, 구도 유지와 세부 보완을 요구하는 프롬프트를 따릅니다. 사진과 일러스트에서는 이것이 흔히 사람들이 말하는 '이미지 해상도 향상'이지만, 무손실 보간은 아니므로, 예를 들어 작은 글자가 있는 스크린샷을 비트 단위로 정확하게 픽셀 스케일링해야 한다면 이 방법을 사용하지 마세요.
무엇을 구축하고 무엇을 먼저 준비할지
다음과 같은 작은 스크립트를 구축합니다:
- 기존 이미지에 대한 참조를 업로드합니다 (공개 URL이면 됨 — 자체 CDN, R2, S3 등)
- 4K 재그리기를 요청하는 이미지 대 이미지 작업을 제출합니다
- 작업이 완료될 때까지 폴링하고 더 높은 해상도의 결과를 다운로드합니다
시작하기 전에:
- hiapi 계정과 API 키가 필요합니다. 대시보드의 API Keys 페이지에서 생성하세요. 아래 모든 요청에는
Authorization: Bearer sk-<your-key>가 필요합니다 — 키 없이는 이 엔드포인트를 호출할 수 없습니다. - 업스케일하려는 이미지에 대한 공개 접근 가능한 URL이 필요합니다. hiapi의 작업 워커가 서버 측에서 이미지를 가져오므로
localhost경로나 비공개 버킷은 사용할 수 없습니다 — 먼저 공개 호스트에 업로드하세요. - Python 3.8+와
requests설치(pip install requests), 또는 셸에서 테스트하려면curl을 바로 사용하면 됩니다.
최소 실행 예제
가장 깔끔한 선택은 seedream-5.0-lite/image-to-image입니다. 입력 스키마가 정확히 네 개의 필드 — prompt, image_urls, aspect_ratio, resolution — 를 요구하며, resolution은 2K 또는 4K만 허용합니다 (이 라우트에는 1K 등급이 없으며, 이는 실수로 이미지를 축소하지 않게 해줍니다).
import time
import requests
API_KEY = "sk-your-hiapi-key" # from https://www.hiapi.ai/en/dashboard/api-keys
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
def create_upscale_task(source_image_url: str) -> str:
payload = {
"model": "seedream-5.0-lite/image-to-image",
"input": {
"prompt": "Same image, preserved composition and colors, sharp fine detail, no artifacts",
"image_urls": [source_image_url],
"aspect_ratio": "1:1", # match your source image's ratio
"resolution": "4K",
},
}
resp = requests.post(BASE, headers=HEADERS, json=payload, timeout=60)
resp.raise_for_status()
body = resp.json()
task_id = body["data"]["taskId"]
return task_id
def wait_for_result(task_id: str, timeout_s: int = 300, poll_every: int = 5) -> str:
deadline = time.time() + timeout_s
while time.time() < deadline:
resp = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30)
resp.raise_for_status()
task = resp.json()["data"]
if task["status"] == "success":
return task["output"][0]["url"]
if task["status"] == "fail":
err = task.get("error", {})
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(poll_every)
raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")
if __name__ == "__main__":
task_id = create_upscale_task("https://your-cdn.example.com/product-photo-small.jpg")
result_url = wait_for_result(task_id)
print("4K result:", result_url)
요청이 어떻게 생겼는지만 보고 싶다면, 다음은 curl로 보내는 동등한 작업 생성 호출입니다:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-your-hiapi-key" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-5.0-lite/image-to-image",
"input": {
"prompt": "Same image, preserved composition and colors, sharp fine detail, no artifacts",
"image_urls": ["https://your-cdn.example.com/product-photo-small.jpg"],
"aspect_ratio": "1:1",
"resolution": "4K"
}
}'
이 요청에 대해 몇 가지 짚고 넘어갈 점:
image_urls는 배열입니다 — 이 모델이 첫 번째 요소만 읽더라도 그렇습니다. 목록 대신 맨 문자열을 전달하는 것은 400 오류의 흔한 원인입니다.- 출력 URL은 만료됩니다.
wait_for_result()가 반환되면 즉시 바이트를 다운로드해 직접 저장하세요 — hiapi가 호스팅하는 링크를 영구 리소스 URL로 사용하지 마세요. - 소스 이미지가 정사각형이 아니라면
aspect_ratio를 그에 맞게 설정하세요 (4:3,16:9,9:16,3:2,2:3또는21:9). 그러면 모델이 주체를 자르거나 채우지 않습니다.
프로덕션 환경에서의 방법
규모가 커지면 폴링보다 콜백을 우선하세요. 업스케일할 이미지가 몇 장을 넘는다면 각 작업마다 루프에서 GET /v1/tasks/<id>를 두드리지 말고, callback 객체를 전달해 hiapi가 결과를 푸시하도록 하세요:
payload = {
"model": "seedream-5.0-lite/image-to-image",
"input": {...},
"callback": {
"url": "https://your-service.example.com/hooks/hiapi-task",
"when": "final",
},
}
웹훅은 폴링과 동일한 작업 객체(status, output, error)를 받습니다 — 네트워크 재시도로 두 번 이상 전달될 수 있으므로 구조를 방어적으로 검증하세요.
자체 측에서 작업별로 멱등성에 유리한 키를 준비하세요. 작업 API는 현재 클라이언트 제공 멱등성 키를 받지 않으므로, 작업 러너가 실패한 HTTP 호출을 재시도할 수 있다면 중복 작업을 제출하기 전에 해당 소스 이미지에 대해 이미 taskId를 저장했는지 확인하세요 — 그렇지 않으면 자체 측의 짧은 타임아웃이 같은 파일에 대해 두 번 청구되는 업스케일이 될 수 있습니다.
두 가지 매우 다른 오류 형태를 처리하세요. 잘못된 형식의 요청 본문은 HTTP 400과 함께 평평한 {"code": 400, "error_code": "INVALID_REQUEST", "message": "..."}를 반환합니다. API 키가 없거나 잘못되면 HTTP 401과 함께 중첩된 {"error": {"code": "permission_denied", "message": "..."}}를 반환합니다. 상태 코드를 먼저 확인한 후 분기하세요:
if resp.status_code == 401:
raise RuntimeError(f"auth error: {resp.json()['error']['message']}")
if resp.status_code == 400:
raise RuntimeError(f"bad request: {resp.json()['message']}")
resp.raise_for_status()
가지고 있는 입력에 따라 모델을 선택하세요. 아래 세 라우트는 모두 같은 /v1/tasks 엔드포인트에 있습니다 — model 문자열과 input 필드만 다릅니다:
| 보유한 것 | 모델 | 필수 입력 필드 |
|---|---|---|
| 기존 이미지가 있고 깔끔한 2K/4K 재그리기를 원함 | seedream-5.0-lite/image-to-image |
prompt, image_urls, aspect_ratio, resolution (2K|4K) |
| 기존 이미지가 있고 품질과 비용 사이에서 절충을 원함 | gpt-image-2/image-to-image@ext |
prompt, image_urls, quality (low|medium|high), resolution (1K|2K|4K) |
| 소스 이미지가 없음 — 텍스트 설명으로 완전히 새로운 고해상도 리소스 생성 | wan2.7-image/text-to-image |
prompt (추가로 선택적 resolution과 aspect_ratio) |
두 번째 행의 @ext 접미사에 주목하세요 — 이는 기본 gpt-image-2 모델의 라우트 변형이며 (hiapi는 일부 모델을 둘 이상의 라우트 아래에서 약간 다른 가격/품질 등급으로 제공합니다), 독립된 모델 계열이 아닙니다. 각각의 요청당 정확한 비용은 선택한 해상도와 품질 등급에 따라 달라지므로, 예산 로직에 값을 하드코딩하지 말고 가격 페이지의 현재 숫자를 확인하세요.
제출 전에 검증하세요. 이 세 모델은 모두 알 수 없는 입력 필드를 조용히 무시하지 않고 직접 거부하며 (additional properties 'x' not allowed), resolution과 aspect_ratio 같은 열거형 필드는 대소문자와 값에 민감합니다. 래퍼를 구축한다면 위의 정확한 열거형 값으로 클라이언트 측에서 검증하여 오타가 요청을 낭비하지 않고 빠르게 실패하도록 하세요.
관련 읽기
- Wan 2.7 Image — 텍스트 대 이미지 API, 프롬프트만으로 완전히 새로운 고해상도 이미지를 생성합니다.
- GPT Image 2 API, 위 표에서 사용된 품질/해상도 등급별 대안입니다.
- hiapi API 가격, 각 모델과 등급의 현재 요청당 비용을 확인하세요.
- hiapi 문서, 모든 콜백 옵션을 포함한 전체 작업 수명 주기 참조를 확인하세요.
자주 묻는 질문
hiapi에 전용 이미지 확대기나 초해상도 모델이 있나요? 픽셀 보존형 전용 모델은 없습니다. 위 워크플로는 범용 이미지 대 이미지 모델을 사용해 더 높은 해상도 등급에서 이미지를 다시 생성하며, 사진과 일러스트에는 잘 작동하지만 무손실 확대는 아닙니다.
이미지 내용을 바꾸지 않고 해상도를 높일 수 있나요? 모델에 구도, 색상, 주체를 정확히 유지하도록 프롬프트함으로써 (“동일한 이미지, 구도 변경 없음, 요소 추가/제거 없음, 세부 묘사와 선명도만 향상”) 매우 근접하게 할 수 있지만, 보간이 아닌 생성형 재그리기이므로 미세한 텍스처에서는 진정한 무손실 확대기와 비교해 미묘한 차이가 여전히 나타납니다.
생성할 수 있는 최대 해상도는 얼마인가요?
위 세 모델의 상한은 모두 4K 해상도 등급입니다. 이보다 큰 크기가 필요하면 소스 이미지를 타일로 나누어 각 블록을 개별 업스케일하거나, API 호출 후 클라이언트 측 스케일링 단계를 추가해야 합니다.
이것을 시도하려면 API 키가 필요한가요?
필요합니다 — 모든 /v1/tasks 호출은 Authorization: Bearer sk-<your-key>를 요구합니다. 작업 생성에 키 없는 샌드박스는 없습니다. 먼저 대시보드에서 키를 발급받으세요.
폴더 전체의 이미지를 일괄 업스케일할 수 있나요?
가능합니다 — 이미지 URL을 순회하며 이미지마다 하나의 작업을 제출한 뒤, 각 taskId를 폴링하거나 (양이 많을 때 더 좋음) 콜백 URL을 등록해 각 작업 생성 시 저장한 taskId로 결과를 작업에 다시 매칭하세요.
왜 제 요청이 “additional properties not allowed”로 실패하나요?
모델 스키마가 인식하지 못하는 필드를 보냈기 때문입니다 — 예를 들어 resolution + aspect_ratio 대신 size를 사용했거나, 다른 모델의 예제에서 여분의 매개변수를 복사한 경우입니다. 각 모델이 받는 정확한 필드 이름은 위의 필수 필드 표를 확인하세요.
관련 글
모든 아티클 보기 →-
튜토리얼
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 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드