튜토리얼
HiAPI로 mirelo-sfx-2.0 API를 호출하는 방법: curl, Python 및 비동기 폴링
mirelo-sfx-2.0의 기능 및 적용 시나리오
mirelo-sfx-2.0은 HiAPI를 통해 호출할 수 있는 텍스트-투-사운드 효과 모델입니다. "무거운 나무 문이 천천히 삐걱거리며 열리는 소리" 또는 "대리석 테이블 위로 동전이 떨어지는 소리"와 같은 자연어 설명을 제공하면, 프롬프트에 맞는 짧은 오디오 클립을 생성합니다.
샘플 라이브러리에서 라이선스를 취득하는 대신, 필요할 때 생성하는 사운드 디자인이 필요하다면 바로 이 엔드포인트를 사용해야 합니다:
- 게임 및 앱 프로토타이핑: 인터랙션, UI 이벤트, 환경 루프를 위한 임시 또는 최종 사운드 효과를 생성합니다.
- 영상 및 팟캐스트 후반 작업: 녹음실 예약 없이 폴리 사운드(foley) 스타일 오디오로 빈 공간을 채웁니다.
- 생성형 파이프라인: 스크립트, 스토리보드 또는 사용자 입력에서 프롬프트를 받아 생성된 WAV를 출력물에 첨부합니다.
이 모델은 사운드 설명이 명확하고 길이가 짧을 때 가장 좋은 성능을 발휘합니다. 음악, 음성 또는 긴 오디오가 필요한 경우에는 다른 모델 계열을 사용해야 합니다. mirelo-sfx-2.0은 개별 사운드 효과에 특화되어 있습니다.
생성이 비동기식이므로, 블로킹 HTTP 호출이 아닌 작업 기반 통합을 계획하세요. 이 튜토리얼의 나머지 부분에서는 원시 curl 요청부터 완성된 WAV를 폴링하여 가져오는 Python 클라이언트까지 이 통합을 구축합니다.
사전 요구사항 및 인증 설정
첫 호출을 하기 전에 다음을 준비했는지 확인하세요:
- HiAPI 계정과 API 키. HiAPI 콘솔에서 키를 생성하고 관리할 수 있습니다. 키는 비밀번호처럼 취급하세요: 환경 변수나 키 관리자에서 로드하고, 절대 코드 저장소에 커밋하지 마세요.
- HTTP 요청을 보낼 도구. 이 실습에서는
curl만 있으면 되며, 코드 예제는 Python 3.8+를 사용합니다. - Python의 HTTP 클라이언트. 예제는 간결성을 위해
requests를 사용하지만, JSON과 헤더를 보낼 수 있는 클라이언트라면 무엇이든 괜찮습니다.
HiAPI는 모든 모델에 단일 기본 URL과 단일 인증 방식을 사용하므로, 여기서 배우는 규칙은 다른 엔드포인트에도 그대로 적용됩니다:
export HIAPI_API_KEY="your-api-key-here"
모든 요청은 Authorization 헤더에 키를 담아 전송합니다:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
모델 식별자는 요청 본문에서 "model": "mirelo-sfx-2.0"으로 전달됩니다. 별도의 SDK를 설치할 필요가 없습니다. HTTP 클라이언트가 HiAPI 기본 URL에 접근할 수 있다면 해당 모델을 호출할 수 있습니다.
실용적인 조언 하나: 기본 URL을 각 파일에 하드코딩하지 말고 구성 변수에 저장하세요. 로컬 스크립트에서 스테이징 또는 프로덕션 서비스로 마이그레이션할 때 한 곳만 수정하면 되도록 하기 위해서입니다.
curl 요청 단계별 분석
생성 요청은 HiAPI 작업 생성 엔드포인트로 보내는 인증된 HTTP POST입니다. 다음은 전체 호출입니다:
curl -sS -X POST "$HIAPI_BASE_URL/v1/tasks" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "mirelo-sfx-2.0",
"input": {
"prompt": "heavy wooden door creaking open slowly, old house ambience"
}
}'
부분별로 분석하면:
-X POST— 작업 생성은 쓰기 작업입니다. 이 경로에GET을 사용하면 작업이 시작되지 않습니다.- URL — 이 엔드포인트는 새로운 생성 작업을 받습니다. 기본 URL은
HIAPI_BASE_URL에 저장되어 있으므로 동일한 명령을 모든 환경에서 사용할 수 있습니다. Authorization— bearer 토큰은 계정을 식별하며 과금 기준이 됩니다. 헤더 누락 또는 형식 오류는401의 가장 흔한 원인입니다.Content-Type: application/json— 본문은 JSON입니다. 이 헤더가 없으면 서버가 페이로드를 거부하거나 잘못 파싱합니다.model— mirelo-sfx-2.0을 선택합니다. HiAPI는 이 필드를 기반으로 라우팅하므로 URL을 변경하지 않고도 모델을 전환할 수 있습니다.input.prompt— 사운드에 대한 텍스트 설명입니다. 구체적이고 물리적인 설명(재질, 동작, 환경)이 추상적인 설명보다 더 좋은 결과를 생성합니다.
성공적으로 제출해도 오디오는 반환되지 않습니다. 대신 식별자(보통 id 필드)가 포함된 작업 객체를 반환하며, 이를 사용해 상태를 확인합니다. 응답에서 해당 ID를 캡처하세요. 나중에 WAV를 검색할 때 필요한 단서입니다.
코드에 통합하기 전에 요청 구조를 확인하려면 터미널에서 이 명령을 그대로 실행해 보세요. 성공하면 Python으로 변환하는 것은 기계적인 작업입니다.
Python에서의 동일한 호출
Python 버전은 동일한 URL, 헤더, 본문을 유지합니다. 단지 이를 딕셔너리와 클라이언트 호출로 표현할 뿐입니다:
import os
import requests
BASE_URL = os.environ["HIAPI_BASE_URL"]
API_KEY = os.environ["HIAPI_API_KEY"]
def create_sfx_task(prompt: str) -> str:
response = requests.post(
f"{BASE_URL}/v1/tasks",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={
"model": "mirelo-sfx-2.0",
"input": {"prompt": prompt},
},
timeout=30,
)
response.raise_for_status()
return response.json()["id"]
shell 버전과의 차이점:
- 환경 접근 —
os.environ이 shell 확장을 대체하므로 키가 소스 코드에 나타나지 않습니다. -d대신json=—requests가 딕셔너리를 직렬화하고 콘텐츠 유형을 설정합니다. 수동 헤더를 제거해도 되지만 유지해도 무방합니다.raise_for_status()— 비 2xx 응답을 예외로 전환하므로 에러 처리는 이 지점에 두어야 합니다.timeout— 클라이언트 타임아웃은 정체된 연결이 작업 프로세스를 멈추는 것을 방지합니다. 작업 생성은 빠르며, 긴 대기는 폴링 중에 발생합니다.
반환 값은 작업 ID입니다. 이를 저장하세요. 해당 생성에 대한 유일한 핸들입니다. 여기서 Python 경로와 curl 경로가 합쳐집니다. 오디오가 존재하려면 둘 다 폴링 단계가 필요합니다.
요청 본문이 단순한 데이터이므로 프롬프트를 매개변수화하고 설명 목록을 반복하여 사운드 효과를 일괄 생성할 수 있으며, 각 프롬프트에 대해 작업을 생성하고 ID를 수집합니다.
비동기 작업 처리 및 결과 폴링
사운드 생성에는 시간이 걸립니다. 밀리초가 아닌 초 단위입니다. 따라서 HiAPI는 이를 작업으로 모델링합니다. 생성 호출은 즉시 ID를 반환하고, 두 번째 엔드포인트는 해당 작업이 아직 실행 중인지, 완료되었는지 또는 실패했는지 보고합니다.
일반적인 루프는 다음과 같습니다:
- 작업을 생성하고 ID를 캡처합니다.
- 해당 ID로 작업 상태 엔드포인트를 폴링합니다.
- 상태가 여전히 처리 중이면 잠시 기다린 후 다시 폴링합니다.
- 상태가 성공을 보고하면 응답에서 출력을 읽습니다.
- 상태가 실패를 보고하면 중단하고 에러를 발생시킵니다.
Python에서:
import time
def wait_for_task(task_id: str, timeout_s: int = 300) -> dict:
deadline = time.time() + timeout_s
while time.time() < deadline:
response = requests.get(
f"{BASE_URL}/v1/tasks/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=30,
)
response.raise_for_status()
task = response.json()
status = task.get("status")
if status == "succeeded":
return task
if status == "failed":
raise RuntimeError(task.get("error", "task failed"))
time.sleep(2)
raise TimeoutError(f"task {task_id} did not finish in time")
몇 가지 특별히 언급할 점:
- 폴링 간격. 2초는 사운드 효과에 합리적인 기본값입니다. 타이트한 루프 폴링은 할당량을 낭비하고 속도 제한을 유발할 수 있지만 결과를 더 빨리 가져오지는 않습니다.
- 전체 데드라인. 항상 루프에 상한을 설정하세요. 멈춘 작업은 작업 프로세스를 영원히 멈추게 하는 대신 작업을 실패시켜야 합니다.
- 상태 값. 알 수 없는 상태 값을 성공으로 가정하지 말고 "아직 처리 중"으로 취급하며, 성공 및 실패 상태에서 명시적으로 분기하세요.
- Webhook(제공되는 경우). HiAPI 계정이 완료 콜백을 지원한다면 서버 측 프로덕션 코드에서 폴링 대신 이를 우선 사용하세요. 스크립트와 프로토타입에서는 폴링이 여전히 가장 간단한 옵션입니다.
작업 ID를 프롬프트와 함께 자체 데이터베이스에 저장하여 나중에 재생성 없이 재시도, 감사 또는 출력 재조회를 할 수 있도록 하세요.
반환된 WAV 응답 읽기
작업이 성공을 보고하면 응답에 생성된 오디오가 포함됩니다. 엔드포인트 버전에 따라 출력이 WAV 파일 URL 또는 인라인 오디오 데이터로 나타날 수 있습니다. 두 경우 모두 "저장 가능한 바이트"로 취급하세요.
성공한 작업 객체는 output과 같은 필드 아래에 출력을 담고 있으며, 보통 모델 이름, 원본 프롬프트, 시간 정보 등의 메타데이터도 포함합니다. 오디오 자체는 표준 WAV 컨테이너이므로 커스텀 디코더 없이 모든 오디오 라이브러리에 전달할 수 있습니다.
URL 기반 결과를 영구 저장하려면:
result = wait_for_task(task_id)
audio_url = result["output"]["audio_url"]
wav_bytes = requests.get(audio_url, timeout=60).content
with open(f"{task_id}.wav", "wb") as f:
f.write(wav_bytes)
오디오가 디코딩된 데이터 형태로 도착하면 쓰기 전에 base64 디코딩을 수행하세요:
import base64
wav_bytes = base64.b64decode(result["output"]["audio_base64"])
with open(f"{task_id}.wav", "wb") as f:
f.write(wav_bytes)
바이트를 얻은 후:
- 파일 헤더 검증. WAV 파일은
RIFF매직 넘버로 시작합니다. 처음 4바이트를 확인하면 잘린 다운로드가 스토리지에 도달하기 전에 잡아낼 수 있습니다. - 영구 저장. 객체 스토리지에 쓰고 키를 작업 ID와 함께 데이터베이스에 저장하세요. 생성된 오디오는 임시 응답이 아닌 캐시 가능한 아티팩트로 취급하세요.
- 재생 또는 처리. 표준 도구(
wave,soundfile또는 모든 오디오 플레이어)로 파일을 직접 열 수 있습니다. 그런 다음 무음 트리밍, 라우드니스 정규화 또는 전달용 다른 형식으로 변환할 수 있습니다.
파일이 일반 WAV이므로 웹 엔드포인트나 게임 엔진 에셋 파이프라인에 연결하는 데 특별한 처리가 필요하지 않습니다.
흔한 장애 지점 및 해결 방법
대부분의 통합 문제는 몇 가지 예측 가능한 범주로 나눌 수 있습니다.
인증 오류(401 / 403)
401은 거의 항상 Authorization 헤더가 누락되었거나, 형식이 잘못되었거나, 빈 환경 변수로 구성되었음을 의미합니다. HIAPI_API_KEY가 에디터에서뿐만 아니라 프로세스가 실행되는 shell에 내보내졌는지 확인하고, 헤더가 Bearer <key>로 표기되며 사이에 공백이 하나만 있는지 확인하세요. 403은 보통 키가 유효하지만 해당 모델에 대한 접근 권한이 없음을 의미합니다. 계정의 모델 권한을 확인하세요.
잘못된 형식의 페이로드(400 / 422)
가장 흔한 원인은 요청 본문이 유효한 JSON이 아닌 경우입니다. curl 명령에서 따옴표 짝이 맞지 않는 것이 전형적인 예입니다. 전송 전에 JSON 검사기로 검증하세요. 두 번째로 흔한 원인은 model 필드 누락 또는 프롬프트 중첩 계층 오류입니다. 모델은 최상위 prompt가 아닌 input.prompt를 기대합니다. 마지막으로 프롬프트가 비어 있지 않고 모델 문서에 명시된 길이 제한 내에 있는지 확인하세요.
너무 빈번한 폴링
sleep 없이 타이트한 while 루프를 돌리면 대량의 상태 요청이 발생하여 속도 제한을 유발하고 대기 중인 작업을 더 느리게 만들 수 있습니다. 1~2초의 고정 간격을 사용하고, 여러 작업을 병렬로 실행할 때는 지터를 추가하며, 항상 최대 대기 시간을 강제하세요.
생성을 완료로 착각
생성 응답은 성공처럼 보이고 200을 반환하지만 오디오는 포함하지 않습니다. 코드가 즉시 output 필드를 읽으면 실패하거나 빈 파일을 쓰게 됩니다. 결과에 접근하기 전에 항상 상태 엔드포인트를 거치세요.
조용한 타임아웃과 재시도
작업 생성 시 네트워크 타임아웃 후 재시도하는 것은 안전하지만, 실제로는 성공한 타임아웃 이후 생성 호출을 재시도하면 중복 작업이 발생합니다. 엔드포인트가 멱등성 키를 지원하면 사용하고, 그렇지 않으면 재시도 전에 최근 작업을 나열하여 확인하세요.
디스크 및 스토리지 엣지 케이스
WAV 바이트를 쓸 때는 파일을 바이너리 모드("wb")로 여세요. 텍스트 모드는 파일 헤더를 손상시킵니다. 출력을 프롬프트 이름으로 저장하면 동일한 프롬프트의 두 작업이 서로 덮어쓰게 됩니다. 파일 키는 작업 ID로 사용하세요.
이러한 보호 조치를 갖추면 mirelo-sfx-2.0 통합은 생성, 폴링, 영구 저장으로 이어지는 짧은 파이프라인입니다. curl 호출로 시작하고, Python으로 이식하고, 작업 ID를 진실의 원천으로 삼으세요.
관련 글
모든 아티클 보기 →-
튜토리얼
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 튜토리얼
요청 우선 실전 데모: 프롬프트에서 비디오 클립까지의 호출 구성, 요청 제출, 완료 상태 폴링 및 결과 다운로드