Skip to main content

ASR 服务开发接入指引

1. 接入前准备​

1.1 前提条件​

  • 已注册 Player Network 控制台,并完成业务项目创建。
  • 若采用 SDK 接入,客户端 Player Network SDK 版本需为 1.32 及以上。

1.2 接入方式选择​

接入方式适用场景接入特点安全注意事项
SDK 接入(推荐)业务已接入 Player Network SDK,客户端可直接调用 SDK 能力。开发链路较短,适合游戏内实时功能。客户端只使用 SDK 所需参数,不应保存 secret。
API 接入仅接入 ASR 服务,或由游戏后端统一代理调用。便于统一鉴权、限流、日志审计和业务封装。secret 仅保存在可信后端或密钥管理系统。

1.3 音频与语言准备​

准备项说明建议
语言代码ASR 识别语种,如 zh、en。按玩家当前语言或业务场景设置;不确定时由后端/管理端明确配置。
PCM 参数application/json 协议传入裸 PCM 数据;当前示例采用 16 kHz、16-bit、单声道。采集端必须保证实际 PCM 参数与服务要求一致,再进行 base64 编码。
音频格式支持 WAV 与 GVoice Opus。audioFormat:1-WAV,2-GVoice Opus。客户端录音格式必须与 audioFormat 一致。
音频路径/文件SDK 侧使用本地 VoicePath;API 文件上传使用 data Part。上传前校验文件存在、可读取、大小和时长合理。
时间戳application/json 协议需传 JSON 字符串格式的 timeStamp,其中包含 start/end。start 为 Unix 秒级时间戳,end 可按 start + 音频时长 计算。

2. 管理端操作​

  1. 首次进入 ASR 服务,点击「立即免费体验」完成 ASR 服务功能初始化。

ASR 服务功能初始化入口

  1. API 接入时,按照以下说明完成管理端配置:
配置项操作说明
功能入口前往「项目信息」,选择「AI 语音识别」。
获取参数在「API 参数」区域获取 APPID(appId) 和 AppSecret(secret),用于签发请求鉴权所需的 JWT Token。具体要求见「3.2.1 JWT Token 生成要求」。
白名单配置在「白名单配置」区域填写游戏后端出口 IP,确认无误后保存。

ASR 服务 API 白名单 / 场景配置入口

3. 后台 API 接入​

3.1 协议选择​

协议Content-Type音频传入方式适用场景注意事项
协议 1application/jsonaudioFile 字段传 base64 编码的裸 PCM 音频数据。电竞直播场景。示例 PCM 参数为 16 kHz、16-bit、单声道;需要传 appId、audioFile、gameCode、srcLang、timeStamp、traceId。
协议 2(推荐)multipart/form-datameta Part 传 JSON 配置;data Part 传音频二进制文件。玩家游戏内场景的语音识别、客户端上传 WAV/GVoice Opus 文件。meta 与 data 两个 Part 的 Content-Type 会被检查,必须按要求填写。
协议说明

协议 1 仅支持通过后台 API 接入;协议 2 除支持后台 API 接入外,还可通过客户端 SDK 接入。SDK 接入方式请参考「4. 客户端 SDK 接入」。

3.2 接口信息​

后台调用 ASR 服务 API 时,请根据当前部署环境选择对应完整地址;接口路径为 /api/v2/speechai/asr。

IP 白名单

调用接口前,需要在 Player Network 管理端配置游戏后端出口 IP 白名单,否则接口无法成功调用。配置方式请参考「2. 管理端操作」。

环境完整调用地址说明
腾讯云 test 环境https://asr-test.intlgame.com/api/v2/speechai/asr腾讯云测试环境使用。
项目说明
接口路径POST <API域名>/api/v2/speechai/asr
Content-Typemultipart/form-data 或 application/json
AuthorizationBearer <token>
鉴权方式JWT,签名算法 HS256;payload.data.account 与 appId 保持一致。
能力说明语音识别接口,统一支持 base64 编码的 PCM 音频数据和文件上传音频。

3.2.1 JWT Token 生成要求​

  • appId 和 secret 从管理端获取,具体操作见「查看参数获取方式」;secret 仅保存在可信后端或密钥管理系统中。
  • 使用 secret 作为 HS256 签名密钥。
  • JWT payload.data.account 必须等于请求中的 appId。
  • JWT payload.exp 使用 Unix 秒级过期时间;后端示例设置为签发后 300 秒过期。
  • 请求头使用 Authorization: Bearer <token>。

3.3 application/json 请求参数​

参数类型必填说明
appIdstring是管理员分配的 appId。
audioFilestring是裸 PCM 音频字节经 base64 编码后的字符串;示例参数为 16 kHz、16-bit、单声道。
gameCodestring是业务代码,标识业务场景;错填会报错。
srcLangstring是目标语音识别语言代码,如 zh、en。
timeStampjson string是JSON 字符串,包含 Unix 秒级 start 和 end;注意不是嵌套 JSON 对象。
traceIdstring是唯一请求 ID,用于跟踪请求。
gameLangstring否玩家游戏语言,无玩家时可不传。
systemLangstring否玩家系统语言,无玩家时可不传。
openIdstring否用户 ID,暂未用到。
sessionIdstring否会话 ID,暂未用到。

timeStamp 字段​

字段类型必填说明
startfloat64是音频片段开始时间,Unix 秒级时间戳。
endfloat64是音频片段结束时间,Unix 秒级时间戳;可使用 start + 音频字节数 / (采样率 × 每样本字节数 × 声道数) 计算。

例如,16 kHz、16-bit、单声道 PCM 的音频时长计算方式为:

duration = len(pcm_bytes) / (16000 * (16 // 8) * 1)
application/json 请求示例
POST /api/v2/speechai/asr HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>

{
"appId": "<app-id>",
"audioFile": "<base64编码的PCM音频数据>",
"traceId": "asr-json-001",
"srcLang": "zh",
"gameCode": "<game-code>",
"timeStamp": "{\"start\": 1672531200, \"end\": 1672531260.0}"
}

完整的 Python 调用示例见「附录:后端接入伪代码」中的“协议 1”。

3.4 multipart/form-data 请求参数​

Part 名称Content-Type必填说明
metaapplication/json是JSON 配置,描述 appId、audioFormat、gameCode、语言、traceId 等基本信息。
dataapplication/octet-stream是音频二进制文件,目前支持 WAV 和 GVoice Opus。

meta 参数​

参数类型必填说明
appIdstring是管理员分配的 appId。
audioFormatint是音频格式:1-WAV,2-GVoice Opus。
gameCodestring是业务代码,标识业务场景。
traceIdstring是唯一请求 ID,用于跟踪请求。
srcLangstring否目标语音识别语言,如 zh、en;游戏内场景通常可不传,更多用于电竞直播。
gameLangstring否玩家游戏语言。
systemLangstring否玩家系统语言。
openIdstring否用户 ID,暂未用到。
sessionIdstring否会话 ID,暂未用到。
timeStampjson string否时间戳信息,包含 start、end。
multipart/form-data 请求示例
POST /api/v2/speechai/asr HTTP/1.1
Content-Type: multipart/form-data; boundary=----boundary
Authorization: Bearer <token>

------boundary
Content-Disposition: form-data; name="meta"
Content-Type: application/json

{
"appId": "<app-id>",
"audioFormat": 1,
"traceId": "asr-file-001",
"srcLang": "en",
"gameLang": "en",
"systemLang": "en",
"gameCode": "<game-code>"
}
------boundary
Content-Disposition: form-data; name="data"; filename="voice.wav"
Content-Type: application/octet-stream

(binary)
------boundary--

实际接入时建议由 HTTP 客户端自动生成 multipart boundary,不要手工固定请求头中的 boundary。完整的 Python 调用示例见「附录:后端接入伪代码」中的“协议 2”。

3.5 响应处理​

响应字段类型说明处理建议
retCodeint返回码,0 表示成功。非 0 时进入错误处理和日志上报。
messagestring返回消息。日志记录,不建议原样展示给玩家。
traceIdstring请求跟踪 ID。问题排查时提供给 PNT 支持。
resultobjectASR 识别结果,仅成功时返回。读取 result.text 作为完整识别文本。
result.startfloat64音频片段开始时间。流媒体或分片识别场景可使用。
result.endfloat64音频片段结束时间。流媒体或分片识别场景可使用。
result.textstring识别出的完整文本内容。展示或进入后续翻译/审核流程。
result.words[]Word单词级详细信息列表。用于字幕时间轴、置信度或说话人展示;为空时忽略。
Word 参数字段类型说明
textstring单个单词的文本内容。
startfloat64单词在音频中的开始时间(秒)。
endfloat64单词在音频中的结束时间(秒)。
scorefloat64单词识别的置信度分数。
speakerstring说话人标识,用于区分不同说话人。
成功响应示例
{
"retCode": 0,
"message": "success",
"traceId": "29d7b34e-3521-4f16-9c5a-12b36c466382",
"result": {
"start": 1770780974,
"end": 1770780980.017,
"text": "Hello World!",
"words": null
}
}

3.6 错误处理建议​

错误类型可能原因处理建议
鉴权失败token 过期、签名错误、appId 与 token account 不一致。重新生成 token;检查 appId/secret;确认 Authorization 头格式。
参数错误缺少 appId、gameCode、traceId、audioFile;audioFormat 不支持;meta/data Part Content-Type 不正确。按协议校验必填字段;multipart 请求需明确设置 Part Content-Type。
音频格式错误音频不是 WAV/GVoice Opus,或 base64 解码失败。客户端上传前校验格式;服务端记录文件类型和大小。
音频时长异常音频为空、过短、过长或 duration 不符合服务要求。客户端限制录音时长;后端添加预校验。
识别为空或噪声音频噪声过大、无人声或触发噪声过滤。前端提示玩家重新录制;必要时降噪或限制环境噪声。
服务内部错误ASR 服务或依赖异常。短暂重试;仍失败时联系 PNT 支持并提供 traceId。

4. 客户端 SDK 接入​

版本要求

SDK 接入 ASR 服务能力需使用 Player Network SDK 1.32 及以上版本。低于 1.32 的版本不支持相关能力,需先完成 SDK 升级。

4.1 调用流程​

  1. 确认客户端已接入 Player Network SDK,并完成登录态初始化。
  2. 录制或获取本地音频文件,确保格式为 WAV 或 GVoice Opus。
  3. 构造 INTLTranslatorVoiceV2Req 请求结构体,填入 VoicePath、AudioFormat、GameCode、TraceId 等字段。
  4. 调用 SDK 已封装的音频翻译/ASR 接口提交请求。实际方法名以当前 SDK 版本文档为准。
  5. 在 INTLTranslatorResult 回调中读取 asrRsp,优先按 ASR V2 结构解析 result.text。
  6. 展示识别文本,或继续进入文本翻译、敏感词审核、聊天发送等业务流程。

4.2 INTLTranslatorVoiceV2Req 字段说明​

字段类型必填说明填写建议
VoicePathString是音频文件路径。确保文件存在且客户端有读取权限。
AudioFormatInteger是目前支持 WAV 和 GVoice Opus:1-WAV,2-GVoice Opus。按实际文件格式填写,不能混填。
GameCodeString是AI 翻译服务为游戏分配的 gameCode。使用管理端场景切换获取的值。
SessionIdString否流式 ASR 的会话 ID。非流式/普通文件识别可不填。
GameLanguageString否游戏语言设置。可填玩家当前游戏语言。
ExtInfoString否额外信息。可填 JSON 字符串。
TraceIdString是用于跟踪的唯一请求 ID。建议每次请求生成唯一 UUID。
客户端 ASR V2 请求结构示例(伪代码,方法名以 SDK 实际版本为准)
INTLTranslatorVoiceV2Req req;
req.VoicePath = "<local-voice-file.wav>";
req.AudioFormat = 1; // 1-WAV, 2-GVoice Opus
req.GameCode = "<game-code>";
req.SessionId = "";
req.GameLanguage = "zh";
req.ExtInfo = "";
req.TraceId = "client-asr-trace-001";

// SDK.AudioTranslateV2(req, OnTranslatorResult);

4.3 asrRsp 回调处理​

  • ASR 结果在 asrRsp 中返回,游戏侧需要自行解析。
  • ASR V2 推荐读取 asr_rsp.result.text 作为识别结果。
  • start、end、words 主要用于流媒体或字幕类场景,普通游戏内语音转文字可忽略。
  • 回调 retCode 为 0 时才展示识别文本;非 0 时提示重新录制或稍后再试。
asrRsp V2 核心结构示例
{
"ret": 0,
"msg": "success",
"translator_rsp": "",
"asr_rsp": {
"retCode": 0,
"message": "success",
"traceId": "traceId",
"result": {
"text": "Hello World!",
"start": 0,
"end": 0,
"words": null
}
}
}

5. 联调与验收​

5.1 验收清单​

检查项通过标准问题定位字段
功能初始化管理端已完成 ASR 服务初始化。项目 ID、appId
gameCode传入 gameCode 与管理端场景一致。gameCode、traceId
协议选择base64 使用 application/json;文件上传使用 multipart/form-data。Content-Type、请求体
PCM 参数协议 1 的 PCM 采样率、位深、声道数与服务要求一致,且 base64 编码前为原始音频字节。PCM 参数、解码后字节数
timeStamp协议 1 传入包含 start/end 的 JSON 字符串,时间跨度与音频时长一致。timeStamp、音频时长
音频格式WAV/GVoice Opus 与 audioFormat 一致。audioFormat、文件后缀、音频头
multipart Partmeta 为 application/json;data 为 application/octet-stream。Part Content-Type
识别结果成功时 result.text 或 asr_rsp.result.text 有内容。retCode、message、traceId
空音频/噪声无人声或噪声场景能提示重新录制。retCode、音频时长、traceId
异常兜底鉴权、参数、格式、服务异常均有业务提示。retCode、message、traceId

5.2 上线前确认​

  • 生产域名、白名单、限流配置已确认。
  • 后端 token 过期时间合理,具备自动刷新能力。
  • 日志中不打印 secret、完整 token 和完整音频内容。
  • 客户端具备录音失败、识别失败、重新录制等兜底流程。
  • 关键错误码和 traceId 已接入监控告警或问题上报。
客户端体验建议

录音前提示玩家保持安静环境;录音中展示时长;上传识别中显示 loading;失败时提供“重新录制”入口。

ASR 识别文本建议在发送前展示给玩家确认,避免误识别内容直接发送。

6. 常见问题与排障建议​

问题可能原因解决方案
ASR 上传文件后报参数错误multipart 的 meta/data Part 名称或 Content-Type 不正确。确认 meta=application/json,data=application/octet-stream。
JSON 协议参数错误timeStamp 被传成嵌套对象而非 JSON 字符串,或 PCM 参数与服务要求不一致。使用 json.dumps({"start": ..., "end": ...});检查采样率、位深和声道数。
ASR 识别为空音频无有效人声、噪声过大或录音权限异常。客户端先本地校验录音文件大小/时长;提示玩家重新录制。
ASR 音频格式错误上传格式与 audioFormat 不一致,或不是 WAV/GVoice Opus。统一录音编码;WAV 传 audioFormat=1,GVoice Opus 传 audioFormat=2。
鉴权失败token 缺失、过期、签名错误,或请求体 appId 与 token account 不一致。重新生成 token;检查 secret;确认 Authorization: Bearer <token> 格式。
SDK 回调 invalid config / ret 91002后台配置缺失。联系 Player Network 助手补充配置。

附录:后端接入伪代码​

app_id 和 secret 用于签发 JWT token,token 通过 Authorization 请求头用于接口鉴权。生产环境中请从安全配置或密钥管理系统读取凭据,不要将其硬编码到代码仓库。

协议 1:application/json​

该协议将裸 PCM 音频字节编码为 base64 字符串。以下示例采用 16 kHz、16-bit、单声道 PCM,并根据音频字节数计算时长。

Python 伪代码:application/json 调用 ASR
import base64
import json
import time
import uuid

import jwt
import requests

# app_id 和 secret 从管理端获取,用于签发 JWT token。
app_id = "<app_id>" # AppID
secret = "<secret>" # AppSecret
api_url = "https://<api-domain>/api/v2/speechai/asr"

token = jwt.encode(
{
"data": {"account": app_id},
"exp": int(time.time()) + 300,
},
secret,
algorithm="HS256",
)

sample_rate = 16000
bit_depth = 16
num_channels = 1

pcm_bytes: bytes = ... # 从语音 SDK 等来源获取的裸 PCM 音频字节

base64_pcm_audio = base64.b64encode(pcm_bytes).decode("utf-8")
duration = len(pcm_bytes) / (
sample_rate * (bit_depth // 8) * num_channels
)

ts = int(time.time())
body = {
"appId": app_id,
"audioFile": base64_pcm_audio,
"gameCode": "<game-code>",
"srcLang": "<src-lang>",
"timeStamp": json.dumps({"start": ts, "end": ts + duration}),
"traceId": str(uuid.uuid4()),
}

resp = requests.post(
api_url,
json=body,
headers={"Authorization": f"Bearer {token}"},
timeout=30,
)
resp.raise_for_status()
print(json.dumps(resp.json(), indent=4, ensure_ascii=False))

协议 2:multipart/form-data​

该协议通过 meta Part 传入 JSON 配置,通过 data Part 上传 WAV 或 GVoice Opus 音频文件。audioFormat 必须与文件的实际编码一致。

Python 伪代码:multipart/form-data 调用 ASR
import json
import time
import uuid
from pathlib import Path

import jwt
import requests

# app_id 和 secret 从管理端获取,用于签发 JWT token。
app_id = "<app_id>" # AppID
secret = "<secret>" # AppSecret
api_url = "https://<api-domain>/api/v2/speechai/asr"

token = jwt.encode(
{
"data": {"account": app_id},
"exp": int(time.time()) + 300,
},
secret,
algorithm="HS256",
)

meta = {
"appId": app_id,
"audioFormat": 1, # 1-WAV,2-GVoice Opus
"traceId": str(uuid.uuid4()),
"gameLang": "<player-game-lang>",
"systemLang": "<player-system-lang>",
"gameCode": "<game-code>",
}

audio_path = Path("<audio-file-path>")

with audio_path.open("rb") as f:
files = {
"meta": (None, json.dumps(meta), "application/json"),
"data": (audio_path.name, f, "application/octet-stream"),
}
resp = requests.post(
api_url,
files=files,
headers={"Authorization": f"Bearer {token}"},
timeout=30,
)

resp.raise_for_status()
print(json.dumps(resp.json(), indent=4, ensure_ascii=False))