Documentation

开发者文档

模型 API、图片与视频生成、音频、联网搜索,以及各客户端接入方式。

音频

这页能做什么

你可以把音频文件转成文字,或通过 WebSocket 持续发送 PCM 音频做实时转写。

前置条件

  • 已有 LokoSpace API Key,请求头使用 Authorization: Bearer <你的 LokoSpace API Key>
  • 账号积分足够支付本次识别
  • 文件转写模型出现在 GET /audio/models 的返回里
  • 实时语音模型还必须满足 supports_realtime: true,并且实时入口已开通
  • 文件转写单个文件不超过 25MB;实时语音只接受 PCM 16-bit
  • 实时语音是单独开通的能力,未开通时握手直接返回 404

可用模型

curl https://sheverai.com/8811c8/api/llm/v1/audio/models \
  -H "Authorization: Bearer $LOKO_KEY"
{
  "object": "list",
  "data": [
    {
      "id": "<音频模型 ID>",
      "object": "model",
      "display_name": "示例音频模型",
      "capabilities": ["audio"],
      "protocol": "<协议标识>",
      "supports_realtime": false,
      "billing": {
        "mode": "per_second",
        "credits_per_second": "<每秒积分>",
        "min_seconds": 1
      }
    }
  ]
}
字段类型说明
objectstring固定为 list
dataarray可用音频模型
data[].idstring请求体里的 model
data[].objectstring固定为 model
data[].display_namestring展示名称
data[].capabilitiesarray模型能力标签
data[].protocolstring服务端音频协议标识。判断能否实时,直接看 supports_realtime
data[].supports_realtimeboolean是否可用于实时语音
data[].billing.modestring固定为 per_second
data[].billing.credits_per_secondnumber每秒积分
data[].billing.min_secondsinteger最短计费秒数

文件转写和实时语音是两个入口。文件转写通常使用 supports_realtime 为 false 的模型;只有 supports_realtime 为 true 的模型才适合实时入口。

文件转写

请求

上传本地文件:

curl https://sheverai.com/8811c8/api/llm/v1/audio/transcriptions \
  -H "Authorization: Bearer $LOKO_KEY" \
  -F "file=@speech.mp3" \
  -F "language=zh" \
  -F "enable_itn=true"

也可以传远程地址:

curl https://sheverai.com/8811c8/api/llm/v1/audio/transcriptions \
  -H "Authorization: Bearer $LOKO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "audio_url": "https://cdn.example.com/speech.mp3",
    "language": "zh"
  }'
字段类型必填说明
filebinary否表单文件,最大 25MB。与 audio_url、audio_base64 三选一
audio_urlstring否http(s) 或 oss:// 地址
audio_base64string否base64 音频,也可以带 data URL 前缀
mime_typestring否音频 MIME,默认 audio/wav
modelstring否音频模型 ID,不传时用服务端默认模型
languagestring否指定识别语言,如 zh
enable_itnboolean否是否做数字、日期等文本规整,默认 false
Idempotency-Keystring否请求头。建议传,相同键重试返回已结算结果

file、audio_url、audio_base64 必须提供一个。

返回

{
  "text": "今天下午三点开会。",
  "language": "zh",
  "duration": 12,
  "usage": { "seconds": 12 },
  "lokospace_billing": {
    "requestId": "<请求 ID>",
    "creditsUsed": "<本次扣除积分>",
    "balanceAfter": "<扣除后余额>"
  }
}
字段类型说明
textstring识别文本
languagestring | null识别语言,可能为空
durationinteger识别音频的秒数,已经按向上取整处理;实际扣费还受 min_seconds 约束
usageobject上游模型服务返回的用量对象,字段随模型而定
lokospace_billing.requestIdstring本次请求 ID
lokospace_billing.creditsUsednumber本次实际扣除积分
lokospace_billing.balanceAfternumber | null扣除后余额
lokospace_billing.duplicateboolean命中相同幂等键的重放时为 true,首次调用不返回

成功响应带 x-lokospace-request-id 和 x-lokospace-credits-used 两个头。

实时语音

地址与鉴权

wss://sheverai.com/8811c8/api/llm/v1/audio/realtime?model=<实时模型 ID>

model 可以省略,省略时使用服务端默认实时模型。建议显式传入 GET /audio/models 中 supports_realtime: true 的 id。

方式写法适用
请求头Authorization: Bearer <你的 LokoSpace API Key>服务端、桌面端,优先使用
查询参数?token=<你的 LokoSpace API Key>不能设置请求头的客户端。URL 可能进入日志
首帧{"type":"auth","token":"<你的 LokoSpace API Key>"}浏览器。首帧必须在 5 秒内发出

查询参数鉴权与 model 同时使用时,写成 ?model=<实时模型 ID>&token=<你的 LokoSpace API Key>。

用首帧鉴权时,首帧必须是 JSON;二进制首帧会被拒绝。首帧之后、鉴权完成前的消息会短暂缓存,最多 16 条,鉴权通过后按顺序转发。

事件

客户端发给服务端:

事件作用
session.update配置音频格式、采样率、声道。开始发音频前发一次
input_audio_buffer.append发送一帧 PCM,audio 是 base64。可以连续发送
input_audio_buffer.commit结束当前语音段,触发识别
{
  "type": "session.update",
  "session": {
    "input_audio_format": "pcm",
    "sample_rate": 16000,
    "input_audio_channels": 1
  }
}

网关会原样转发 session.update,并按 input_audio_format、sample_rate、input_audio_channels 识别计费口径。字段名要与所选模型的实时协议一致。

input_audio_format 支持 pcm(16-bit PCM)、pcm16、pcm_s16le 等写法。采样率 8000 到 192000,声道 1 到 8。音频开始发送后不能改格式。

{"type":"input_audio_buffer.append","audio":"<base64 PCM>"}
{"type":"input_audio_buffer.commit"}

服务端回给客户端的事件原样转发。连接级事件有 session.created、session.updated,错误事件是 error。识别完成事件通常为 conversation.item.input_audio_transcription.completed,读取其中的 transcript;不同模型也可能返回增量事件,按 type 处理,以实际返回为准。

{
  "type": "error",
  "error": {
    "type": "insufficient_credits",
    "code": "INSUFFICIENT_CREDITS",
    "message": "积分余额不足,实时语音会话已结束"
  }
}

调用示例

先安装 ws,再把音频转成 16 kHz、16-bit、单声道 PCM。

const fs = require('fs');
const WebSocket = require('ws');

const key = process.env.LOKO_KEY;
const model = process.env.LOKO_REALTIME_MODEL;
const url = 'wss://sheverai.com/8811c8/api/llm/v1/audio/realtime?model='
  + encodeURIComponent(model);

const ws = new WebSocket(url, {
  headers: { Authorization: 'Bearer ' + key }
});

ws.on('open', () => {
  ws.send(JSON.stringify({
    type: 'session.update',
    session: {
      input_audio_format: 'pcm',
      sample_rate: 16000,
      input_audio_channels: 1
    }
  }));

  const pcm = fs.readFileSync('speech.pcm'); // 16 kHz, 16-bit, mono
  const chunk = 3200; // 100 ms
  let offset = 0;

  const timer = setInterval(() => {
    if (offset >= pcm.length) {
      clearInterval(timer);
      ws.send(JSON.stringify({ type: 'input_audio_buffer.commit' }));
      return;
    }
    ws.send(JSON.stringify({
      type: 'input_audio_buffer.append',
      audio: pcm.subarray(offset, offset + chunk).toString('base64')
    }));
    offset += chunk;
  }, 100);
});

ws.on('message', (raw) => {
  let event;
  try { event = JSON.parse(raw.toString()); } catch (_) { return; }
  if (event.type === 'error') console.error(event.error);
  const text = event.transcript
    || event.item?.content?.[0]?.transcript
    || event.delta;
  if (text) console.log(text);
});

ws.on('close', (code, reason) => {
  console.log('closed', code, reason.toString());
});

计费说明

文件转写按 per_second 计费,是后结算:识别成功后才扣费,失败不扣费。计费秒数 = ceil(max(上游返回的音频秒数, min_seconds)),且至少 1 秒;总价 = 每秒积分 × 计费秒数。调用前会按文件头估算时长做余额预检,估算失败时按 60 秒;预检不扣费,余额不足直接返回 402,不调用上游。成功结算后,相同 Idempotency-Key 重试返回原结果,不重复扣费。

实时语音也按 per_second 计费,按实际转发给上游的 PCM 字节换算秒数。默认每满 10 秒预扣一次,结束时按实际秒数多退少补;0 秒会话不扣费。余额不足时服务端发 error 并以 4402 关闭,不会继续转发音频。

1 元 = 100 积分。单价从 model_pricing 读取,文档不写死具体价格,以 GET /models 返回为准;文件转写和实时语音的每秒单价也可以在 GET /audio/models 的 billing 里看到。

错误与常见问题

状态含义处理
400缺少音频、URL 非法、base64 为空、实时音频格式不支持按返回的 message 修正
401密钥缺失、无效、已撤销或已过期重新创建或更换密钥
402积分不足。实时会话内对应关闭码 4402充值后重试
404模型不存在或未启用;实时入口未开通也返回 404重新拉取 /audio/models,确认实时能力已开通
413AUDIO_TOO_LARGE:base64 音频超过 25MB压缩或切分后重试
429上游模型服务并发或频率受限;实时入口对应并发会话数上限退避后重试
502上游模型服务失败、超时,或没有识别出文本稍后重试
503没有配置按秒定价,或渠道凭证不可用联系管理员检查模型定价与渠道

实时语音关闭码:

关闭码含义
4401鉴权失败或首帧超时
4402积分不足
4408会话达到最长时长
4429同账号并发会话数已达上限
1011上游连接异常或实时会话错误

常见问题:

  • 文件转写支持哪些格式?服务端会从 WAV、MP3、MP4 的文件头估算时长,具体能识别哪些编码由模型决定。估算不到时按 60 秒做余额预检。
  • 实时为什么只支持 PCM?服务端按 PCM 字节数换算计费秒数,压缩格式无法准确换算,会返回 AUDIO_REALTIME_FORMAT_UNSUPPORTED。
  • 实时中途能改采样率吗?不能。开始发送音频后改格式会返回错误并结束会话。
  • 实时最长多久?默认单会话 30 分钟,同一账号默认 2 路并发。
  • 断线会重复扣费吗?不会按整段预估扣费,只按已经转发给上游的音频结算,差额退回。