教程
如何通过 HiAPI 调用 mirelo-sfx-2.0 API:curl、Python 与异步轮询
mirelo-sfx-2.0 的功能及适用场景
mirelo-sfx-2.0 是可通过 HiAPI 调用的文本转音效模型。你向它提供一段自然语言描述——例如“沉重的木门缓慢吱呀打开”或“硬币掉在大理石桌面上”——它就会生成一段与提示词匹配的短音频片段。
当你需要按需生成的音效设计、而非从采样库中授权获取时,这就是应当使用的端点:
- 游戏与应用原型开发:为交互、UI 事件和环境循环生成占位或最终音效。
- 视频与播客后期制作:无需预约录音棚,即可用拟音风格音频填补空白。
- 生成式管线:从脚本、分镜或用户输入中获取提示词,并将生成的 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 展开,因此密钥永远不会出现在源代码中。 - 用
json=代替-d——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")
有几点值得特别说明:
- 轮询间隔。两秒是音效的合理默认值。紧凑循环轮询会浪费配额,还可能触发速率限制,却不会让结果来得更快。
- 总体截止时间。始终为循环设定上限。卡住的任务应让你的作业失败,而不是永远挂起工作进程。
- 状态值。将未知状态值视为“仍在处理”而非假设成功,并在成功和失败状态上显式分支。
- 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魔数开头。检查前四个字节可在截断下载到达存储之前将其捕获。 - 持久存储。写入对象存储,并将键与任务 ID 一起保存在数据库中。将生成的音频视为可缓存的产物,而非临时响应。
- 播放或处理。标准工具——
wave、soundfile或任何音频播放器——可直接打开该文件。然后你可以裁剪静音、归一化响度或转换为其他格式用于交付。
由于文件是普通 WAV,将其接入 Web 端点或游戏引擎资产管线无需特殊处理。
常见故障点及修复方法
大多数集成问题可归入几个可预测的类别。
身份验证错误(401 / 403)
401 几乎总是意味着 Authorization 请求头缺失、格式错误或由空环境变量构建。请确认 HIAPI_API_KEY 在进程运行的 shell 中已导出——而不仅在编辑器中——并且请求头读作 Bearer <key>,中间只有一个空格。403 通常意味着密钥有效但无权访问该模型;请检查你账号的模型权限。
格式错误的载荷(400 / 422)
最常见的原因是请求体不是有效 JSON——curl 命令中引号不配对是典型例子。发送前用 JSON 检查器验证。第二常见原因是缺少 model 字段或提示词嵌套层级错误;模型期望 input.prompt,而非顶层 prompt。最后,检查提示词非空且长度在模型文档规定的限制内。
轮询过于频繁
没有休眠的紧凑 while 循环会产生大量状态请求,可能触发速率限制,并让你正在等待的任务变慢。使用一到两秒的固定间隔,并行运行多个作业时加入抖动,并始终强制执行最大等待时间。
将创建视为完成
创建响应看起来像成功并返回 200,但不包含音频。如果你的代码立即读取 output 字段,它将失败或写入空文件。在接触结果之前,始终通过状态端点。
静默超时与重试
任务创建时的网络超时重试是安全的,但在一次实际已成功的超时之后重试创建调用会产生重复作业。如果端点支持幂等键,请使用它们;否则在重试前列出最近任务进行核对。
磁盘与存储边缘情况
写入 WAV 字节时,以二进制模式("wb")打开文件。文本模式会损坏文件头。如果你按提示词名称存储输出,两个相同提示词的任务会互相覆盖——请按任务 ID 作为文件键。
有了这些防护措施,mirelo-sfx-2.0 集成就是一条短管线:创建、轮询、持久化。从 curl 调用开始,移植到 Python,并将任务 ID 作为你的真相来源。