教程
如何通过 HiAPI API 使用 mureka-9.5/instrumental:curl 与 Python 指南
mureka-9.5/instrumental 在 HiAPI 上的功能
mureka-9.5/instrumental 是 HiAPI 上的一个文本生成音乐端点,专门针对纯器乐输出进行调优——背景音乐、循环片段、铺底音乐和配乐。你用提示词描述曲目,提交单个任务,HiAPI 返回一个完成的音频资源,你可以下载并放入游戏、视频剪辑、播客或产品演示中。
instrumental(器乐)这个词是关键。该端点面向没有主唱人声表演的音乐,因此适合需要旁白或对白保持清晰可懂的场景。如果你需要带歌词的演唱曲目,那是另一个问题;如果你需要在配音下方铺一层干净的背景音乐,这才是正确的工具。
在以下情况选择该端点:
- 你想要生成的背景音乐(BGM),而不是从音乐库中取材。
- 你需要快速、以编程方式生成大量变体,而不是一次定制的委托创作。
- 你的流水线已经使用 HTTP,你想把音乐当作任何其他资源生成步骤来处理。
- 你关心可预测的请求形态:提交、轮询、下载。
与其他音乐生成端点一样,工作是异步的。提交后返回一个任务,你需要跟踪它直到生成音频。从一开始就围绕这一点设计代码,其余集成工作就都是常规操作了。
在产品中的适用位置
典型的使用者是按需需要曲目的内容流水线:一个想在每个片段下方铺一层音乐的视频渲染器,一个想要环境循环片段的游戏,或者一个让用户输入情绪并听到结果的 prototyping 工具。由于该端点由文本驱动,你可以用已有的元数据——流派、节奏感、情绪和预期时长——来模板化提示词,并在渲染时生成。
将每个请求视为一个具有自身生命周期的生成任务。这种框架能让你的重试逻辑、日志记录和成本核算保持合理。
发送请求之前的准备
在首次调用成功之前,需要满足几个条件。它们都不复杂,但漏掉一个就是首次请求失败最常见的原因。
凭证
你需要一个 HiAPI API 密钥。把它当作机密对待:从环境变量如 HIAPI_API_KEY 加载,绝不要硬编码到你提交的脚本中,如果泄露就轮换它。密钥通过 Authorization 头以 bearer 令牌形式发送。
export HIAPI_API_KEY="your_api_key_here"
端点与传输
你通过 HiAPI 统一 API 调用 mureka-9.5/instrumental 模型。基础 URL 是 HiAPI API 主机;模型标识符按照 HiAPI 为该端点记录的约定放在请求负载或路径中。使用 HTTPS,发送 Content-Type: application/json,并发送 JSON 正文。
不要猜测参数名。HiAPI 记录了该模型接受的字段;该集合之外的任何内容最好情况是被忽略,最坏情况是被拒绝。如果你想要的字段没有文档记录,它就不是契约的一部分——围绕已有的内容来构建。
需要准备的内容
- 描述音乐的提示词:流派、乐器编制、情绪、节奏感和预期用途。
- 模型公开的、有文档记录的时长或变体选项。
- 一个用于存储任务标识符以及稍后存储下载 URL 的位置。
- 从代码运行位置到 HiAPI 主机的网络访问。
关于时间的说明
生成不是即时的。将客户端超时设置得宽松些,并预期需要轮询。同步思维——发送请求并阻塞直到音频在同一响应中返回——会导致代码不稳定。
一个可用的 curl 请求
从 curl 开始。它移除了你和 HTTP 对话之间的每一层,所以如果有问题你能立即看到。
调用
curl -sS -X POST "$HIAPI_BASE_URL" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "mureka-9.5/instrumental",
"input": {
"prompt": "warm lo-fi hip hop instrumental, mellow electric piano, soft vinyl crackle, relaxed 80 bpm, no vocals"
}
}'
先设置这两个环境变量,这样除了你选择的内容之外,不会有敏感信息以明文形式留在 shell 历史记录中:
export HIAPI_BASE_URL="https://api.hiapi.ai/v1/..." # 使用该端点有文档记录的路径
export HIAPI_API_KEY="your_api_key_here"
各部分的作用
-X POST— 提交是一个创建操作。-H "Authorization: Bearer ..."— 使用你的账户对调用进行认证。-H "Content-Type: application/json"— 告诉服务器正文是 JSON;省略它,许多服务器会直接拒绝正文。-d '{...}'— JSON 负载。model字段指定端点;input对象承载你的提示词和其他有文档记录的字段。-sS— 静默进度,但仍显示错误。在脚本中很有用。
读取响应
响应是 JSON。你要寻找一个任务或作业标识符以及一个状态字段。漂亮地打印出来以便检查:
curl -sS -X POST "$HIAPI_BASE_URL" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d @payload.json | jq .
保留标识符。它是后续每次状态检查的句柄。不要把整个响应体解析到你的应用中;提取任务 ID 和状态,并存储原始响应以供调试。
如果你得到非 2xx 状态,读取正文——HiAPI 返回结构化的错误消息,通常会指出有问题的字段。
Python 中的相同请求
Python 版本与 curl 调用完全对应:相同的头,相同的 JSON 正文。为简洁起见使用 requests,或者如果你想要零依赖,使用标准库。
使用 requests
import os
import requests
API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ["HIAPI_BASE_URL"]
payload = {
"model": "mureka-9.5/instrumental",
"input": {
"prompt": (
"warm lo-fi hip hop instrumental, mellow electric piano, "
"soft vinyl crackle, relaxed 80 bpm, no vocals"
)
},
}
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
resp = requests.post(BASE_URL, json=payload, headers=headers, timeout=30)
resp.raise_for_status()
data = resp.json()
job_id = data["id"] # use the documented field name
print("submitted:", job_id, data.get("status"))
使用标准库
如果你无法添加依赖:
import json, os, urllib.request
req = urllib.request.Request(
os.environ["HIAPI_BASE_URL"],
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}",
"Content-Type": "application/json",
},
method="POST",
)
with urllib.request.urlopen(req, timeout=30) as r:
data = json.load(r)
实用习惯
- 仅在提交时使用
timeout=30。轮询需要自己的循环和自己的超时。 - 解析之前调用
raise_for_status()。错误响应体不是任务。 - 将任务 ID 提取包装在一个小辅助函数中,这样字段名变更只需一行修复。
- 绝不要记录 API 密钥;改为记录任务 ID 和状态。
- 将负载作为代码中的字典保留,序列化一次,以便测试可以对其断言。
处理异步任务与轮询
提交是第一步。生成在服务器端进行并稍后完成,因此你轮询状态端点直到任务报告终态。
循环形态
- 提交任务,捕获 ID。
- 短暂休眠。
- 查询该 ID 的状态。
- 如果状态是排队中或处理中,退避并重复。
- 如果状态是成功状态,读取输出。
- 如果状态是失败状态,记录错误并停止——不要盲目重试。
一个可靠的实现
import time, random, requests
def wait_for_job(job_id, base_status_url, headers,
timeout_s=600, initial_delay=2.0, max_delay=30.0):
deadline = time.monotonic() + timeout_s
delay = initial_delay
while time.monotonic() < deadline:
r = requests.get(f"{base_status_url}/{job_id}", headers=headers, timeout=30)
r.raise_for_status()
status = r.json()["status"]
if status in ("succeeded", "completed", "success"):
return r.json()
if status in ("failed", "error", "cancelled"):
raise RuntimeError(f"job {job_id} ended as {status}: {r.text}")
time.sleep(delay + random.uniform(0, 0.5)) # jitter
delay = min(delay * 1.5, max_delay) # exponential backoff
raise TimeoutError(f"job {job_id} did not finish in {timeout_s}s")
每个细节为何重要
- 抖动(Jitter)防止在多个任务并行运行时同步重试。
- 退避(Backoff)防止在曲目渲染时猛击状态端点。
- 截止时间(Deadline)将无限挂起转化为流水线可以处理的干净异常。
- 终态检查应匹配 HiAPI 文档记录的状态字符串。对照 API 参考确认它们,而不是相信猜测。
- 重试应围绕瞬时网络错误(超时、5xx),而不是围绕已经因验证错误而失败的任务。
运维提示
在开始轮询之前持久化 job_id。如果你的进程死了,你可以恢复轮询,而不是为第二次生成付费。记录带时间戳的状态转换,这样你可以看到时间花在哪里。如果你运行许多任务,通过队列并行轮询少量任务,而不是在每个任务上阻塞一个请求线程。
获取器乐输出并下载
器乐模式通过你的请求表达,该端点专门用于此类输出。在实践中,提示词措辞会强化这一点:命名乐器、描述情绪,并声明没有 vocals。要求人声线的提示词与端点的目的相冲突。
音频出现在哪里
当任务达到成功状态时,状态响应携带结果。预期音频以单独获取的 URL 形式交付,而不是状态 JSON 中的 base64。读取响应并从有文档记录的输出字段中提取下载 URL。
result = wait_for_job(job_id, status_url, headers)
# 前几次仔细检查结果,然后固定该字段。
audio_url = result["output"]["audio_url"] # 在 API 参考中确认字段名
with requests.get(audio_url, stream=True, timeout=60) as r:
r.raise_for_status()
with open(f"{job_id}.mp3", "wb") as f:
for chunk in r.iter_content(chunk_size=65536):
f.write(chunk)
下载习惯
- 流式写入磁盘。音乐文件很大;将它们完全加载到内存中是可以避免的压力。
- 检查内容类型。使用响应暗示的扩展名存储文件,而不是硬编码的扩展名。
- 将 URL 视为临时。及时下载,或者仅在文档说明其稳定时持久化 URL。将字节复制到你自己的存储中以实现持久保存。
- 只获取一次。在没有完成标记的情况下在重试循环中下载,很容易创建部分文件。写入临时名称,成功后重命名。
- 记录来源。将任务 ID 和提示词与文件一起存储。以后需要变体时,你有确切的输入。
常见失败点与修复
大多数首次集成问题都落在一个短列表中。以下是检查清单。
401 / 403 — 认证。头是错的,密钥缺失,或者环境变量解析为空字符串。验证密钥在运行代码的同一 shell 或进程中设置,并且头准确读取为 Authorization: Bearer <key>。
400 — 负载格式错误。缺少 model、mureka-9.5/instrumental 中有拼写错误、无效 JSON,或端点不接受的字段。先用 curl 发送正文,以将负载与代码隔离。发送前验证 JSON;尾随逗号是经典问题。
415 或空正文错误 — 内容类型。必须存在 Content-Type: application/json。一些 HTTP 客户端在你传递 json= 时会自动设置它,但不是所有。
轮询超时。你的截止时间太短,你的退避太激进,或者任务确实失败了而你将其分类为仍在运行。对照文档检查确切的状态字符串,并在调试时打印每次状态转换。
缺少下载 URL。你读取了错误的字段,或者你在任务达到终态成功状态之前读取了响应。记录一次完整的成功负载,确认音频 URL 的路径,然后固定它。
重复生成。你的轮询器崩溃了,有东西重新提交了。在轮询之前持久化任务 ID,并在提交新任务之前检查现有任务。
速率限制。对 429 响应带抖动地退避,并排队工作,而不是从许多线程同时爆发。
按此顺序处理它们——认证、负载、内容类型、轮询、输出——你通常一次就能找到原因。一旦 curl 调用及其 Python 孪生版本都端到端成功,端点就在做你要求的事情:将提示词转化为器乐曲目,并交给你一个下载 URL。