AGTCloud API Docs
文档指南API Reference集成与资源更新与帮助
音频处理Muse Voice Transcribe

实时转写

通过 Muse Voice Transcribe WebSocket 持续发送 PCM 音频并接收实时转写事件。

Muse Voice Transcribe 实时接口通过持久 WebSocket 接收裸 PCM 音频,并持续返回进度、语音轮次和转写事件。该接口只生成文本,不生成语音回复。

WSS
wss://api.agtcloud.cn/v1/asr/realtime

认证与连接

WebSocket 建立后,应在 10 秒内发送首个 JSON 文本帧。Bearer API Key 位于 authorization.accessToken,不是 WebSocket 握手 Header。

项目值
连接地址wss://api.agtcloud.cn/v1/asr/realtime
鉴权位置首个 JSON 文本帧的 authorization.accessToken
模型muse-voice-transcribe-1.0
可选查询参数sessionId,仅透传会话标识,不表示支持断线恢复或历史会话查询

首帧不包含 type,最大为 64 KiB。收到包含 sessionId 的成功响应后,再开始发送音频;WebSocket 升级成功不代表首帧鉴权已经通过。

会话流程

  1. 建立 WebSocket 连接。
  2. 发送包含鉴权、模型和音频配置的首帧。
  3. 等待服务端返回 sessionId。
  4. 按实时速率发送裸 PCM 二进制帧,同时持续接收事件。
  5. 音频结束后发送 {"type":"endStream"}。
  6. 继续接收尾部转写和关闭消息。

speechComplete 只表示一个语音轮次完成,不表示整个会话结束。发送 endStream 后也应继续读取服务端事件,直到连接关闭。

首帧参数

字段类型说明
authorization.accessTokenstring必填,格式为 Bearer your-api-key
modelstring必填,使用 muse-voice-transcribe-1.0
audioEncodingstring必填,实时音频使用 PCM_16KHZ 或 PCM_24KHZ
modestring可选:PUSH_TO_TALK、ENDPOINTING、DIARIZATION
partialModestring可选:CUMULATIVE 返回累计文本,DELTA 返回新增文本
keywordsstring[]可选,提示术语或专名
languageBiasstring[]可选,提示预期语言
emitAudioProgressboolean可选,是否返回音频处理进度事件
zdrOverrideboolean可选的数据处理选项;是否生效取决于当前服务和账户权限

音频输入

音频必须是不含 WAV 文件头的 PCM16 little-endian、单声道数据,并与首帧声明的 16 kHz 或 24 kHz 采样率一致。每个音频帧不超过 1 MiB,字节长度必须为偶数。

建议以 100 ms 为一个音频块并按实时速率发送:24 kHz 对应 4800 字节,16 kHz 对应 3200 字节。静音期间如需维持连续时间线,也应发送相同格式的 PCM 静音数据。

# 生成 24 kHz、单声道、PCM16 裸音频
ffmpeg -i input.mp3 -ac 1 -ar 24000 -c:a pcm_s16le -f s16le audio.pcm

Python 示例

安装 WebSocket 客户端并准备好 audio.pcm 后运行示例。发送和接收在不同线程中进行,避免音频上传阻塞服务端事件处理。

python -m pip install websocket-client
WSSMuse 实时转写连接
import json
import sys
import threading
import websocket

url = "wss://api.agtcloud.cn/v1/asr/realtime"
stop = threading.Event()
sender = None
ws = websocket.create_connection(url, timeout=40, enable_multithread=True)

def send_audio():
    try:
        with open(sys.argv[1], "rb") as audio:
            while not stop.is_set():
                chunk = audio.read(4800)
                if not chunk:
                    break
                if len(chunk) % 2:
                    raise ValueError("PCM 字节数必须为偶数")
                ws.send_binary(chunk)
                if stop.wait(len(chunk) / 48000):
                    return
        if not stop.is_set():
            silence = bytes(4800)
            for _ in range(10):
                ws.send_binary(silence)
                if stop.wait(0.1):
                    return
            ws.send(json.dumps({"type": "endStream"}))
    except Exception as exc:
        print("发送中断:", exc)
        stop.set()
        ws.close()

try:
    ws.send(json.dumps({
        "authorization": {"accessToken": "Bearer your-api-key"},
        "model": "muse-voice-transcribe-1.0",
        "audioEncoding": "PCM_24KHZ",
        "mode": "ENDPOINTING",
        "partialMode": "CUMULATIVE",
        "languageBias": ["Mandarin Chinese"],
        "emitAudioProgress": True
    }))
    ack = json.loads(ws.recv())
    if ack.get("type") == "error" or not ack.get("sessionId"):
        raise RuntimeError("连接初始化失败: " + json.dumps(ack, ensure_ascii=False))
    print("sessionId:", ack["sessionId"])
    sender = threading.Thread(target=send_audio, daemon=True)
    sender.start()
    while not stop.is_set():
        message = ws.recv()
        if not message:
            break
        event = json.loads(message)
        print(json.dumps(event, ensure_ascii=False))
        if event.get("type") == "error":
            break
finally:
    stop.set()
    ws.close()
    if sender is not None:
        sender.join(timeout=2)

事件 Reference

audioProcessedMs 表示累计处理进度,不应把多个事件的值相加。使用 CUMULATIVE 时,新的部分文本替换上一份累计结果;使用 DELTA 时,按增量追加文本。

服务端事件 · Progress

audioProgress

返回当前累计处理的音频进度。

字段类型必填说明示例值
type字符串是固定为 audioProgress。audioProgress
audioProcessedMs整数是累计处理的音频时长,单位为毫秒。1600
JSON 示例
{
  "type": "audioProgress",
  "audioProcessedMs": 1600
}

speechComplete.transcript 包含当前语音轮次的完整转写结果。会话收尾时,final: true 的 transcript 事件可能不包含文本;客户端不应使用空字符串覆盖已经保存的累计文本或 speechComplete.transcript。

会话限制与错误处理

会话最长约 60 分钟。连续 15 秒没有客户端消息可能触发输入收尾;网络或服务端状态也可能提前结束连接。客户端应设置总时长、读取超时和有限重试策略。

关闭码含义处理建议
1008策略或协议错误检查首帧结构、鉴权、参数以及后续控制消息
1011服务端或上游中断保存 sessionId、错误事件和关闭原因后再决定是否重试
1013服务暂时不可用或限流使用退避策略进行有限重试

计费

实时转写按已处理音频时长计费,具体价格以当前站点的模型广场为准。进度事件中的毫秒值用于表示处理时间线,不应作为独立账单逐条累加。

参考资料