讯飞语音-接口调用流程
接口鉴权
- 在握手阶段,请求方需要对请求进行签名,服务端通过签名来校验请求的合法性。
- 鉴权方法:在请求地址后面加上鉴权相关参数。(参考以下鉴权URL示例)
wss://iat-api.xfyun.cn/v2/iat?authorization=YXBpX2tleT0ia2V5eHh4eHh4eHg4ZWUyNzkzNDg1MTlleHh4eHh4eHgiLCBhbGdvcml0aG09ImhtYWMtc2hhMjU2IiwgaGVhZGVycz0iaG9zdCBkYXRlIHJlcXVlc3QtbGluZSIsIHNpZ25hdHVyZT0iSHAzVHk0WmtTQm1MOGpLeU9McFFpdjlTcjVudm1lWUVIN1dzTC9aTzJKZz0i&date=Wed%2C%2010%20Jul%202019%2007%3A35%3A43%20GMT&host=iat-api.xfyun.cn
- 鉴权参数
host
不同语音服务对应的服务器地址不同,你可以在指定服务的开发文档中找到,比如:语音听写服务的地址参考如下:
- 中英文(推荐使用):
iat-api.xfyun.cn- 中英文:
ws-api.xfyun.cn- 小语种:
iat-niche-api.xfyun.cn参考:接口要求
date
- date必须是
UTC+0或GMT时区,RFC1123格式(Wed, 10 Jul 2019 07:35:43 GMT)。- 服务端会对Date进行时钟偏移检查,最大允许300秒的偏差,超出偏差的请求都将被拒绝。
authorization
authorization_origin
参数
authorizationbase64编码前(authorization_origin)的格式如下api_key="$api_key", algorithm="hmac-sha256", headers="host date request-line", signature="$signature"
api_key是在 控制台 获取的APIKey。algorithm是加密算法(仅支持hmac-sha256)。headers是参与签名的参数,是固定的参数名(“host date request-line”),而非参数的值。signature需要通过加密得到,是使用加密算法对参与签名的参数签名后并使用base64编码的字符串。
获取密钥
- 获取接口密钥
APIKey和APISecret。- 在 讯飞开放平台-创建新应用 创建WebAPI平台应用并添加语音听写(流式版)服务后即可查看。
signature_origin
signature原始字段由host,date,request-line三个参数按照格式拼接而成,拼接格式如下(其中\n为换行符,:后面有一个空格):host: $host\ndate: $date\n$request-line示例假设
url = wss://iat-api.xfyun.cn/v2/iat、date = Wed, 10 Jul 2019 07:35:43 GMT,那么signature原始字段(signature_origin)则为host: iat-api.xfyun.cn date: Wed, 10 Jul 2019 07:35:43 GMT GET /v2/iat HTTP/1.1
对signature_origin签名
使用
hmac-sha256算法结合apiSecret对signature_origin签名,获得签名后的摘要signature_sha。其中apiSecret是在控制台获取的APISecret。signature_sha=hmac-sha256(signature_origin, $apiSecret)关于
hmac-sha256:hmac-sha256
对signature_sha编码
使用
base64编码对signature_sha进行编码,获得最终的signature。signature=base64(signature_sha)关于
base64:base64
拼接authorization
根据以上信息拼接
authorizationbase64编码前(authorization_origin)的字符串。api_key="keyxxxxxxxx8ee279348519exxxxxxxx", algorithm="hmac-sha256", headers="host date request-line", signature="Hp3Ty4ZkSBmL8jKyOLpQiv9Sr5nvmeYEH7WsL/ZO2Jg="注意headers是参与签名的参数,请注意是固定的参数名(“host date request-line”),而非这些参数的值。
对authorization_origin编码
对
authorization_origin进行 base64 编码获得最终的authorization参数。authorization = base64(authorization_origin)关于
base64:base64
鉴权url生成示例
鉴权结果
- 如果握手成功,会返回
HTTP 101状态码,表示协议升级成功。- 如果握手失败,则根据不同错误类型返回不同HTTP Code状态码,同时携带错误描述信息,详细错误说明如下:
握手失败返回示例HTTP/1.1 401 Forbidden Date: Thu, 06 Dec 2018 07:55:16 GMT Content-Length: 116 Content-Type: text/plain; charset=utf-8 { "message": "HMAC signature does not match" }
接口数据传输与接收
- 握手成功后客户端和服务端会建立Websocket连接,客户端通过Websocket连接可以同时上传和接收数据。当服务端有识别结果时,会通过Websocket连接推送识别结果到客户端。
- 发送数据时,如果间隔时间太短,可能会导致引擎识别有误。
- 建议每次发送音频间隔40ms,每次发送音频字节数(即java示例demo中的frameSize)为一帧音频大小的整数倍。
- 整个会话时长最多持续60s,或者超过10s未发送数据,服务端会主动断开连接。
- 数据上传完毕,客户端需要上传一次数据结束标识表示会话已结束。
更多说明参考官网:接口调用流程
请求参数
公共参数
业务参数
业务数据流参数
请求参数示例
{ "common": { // 公共请求参数 "app_id": "123456" }, "business": { "language": "zh_cn", "domain": "iat", "accent": "mandarin" }, "data": { "status": 0, "format": "audio/L16;rate=16000", "encoding": "raw", "audio":"exSI6ICJlbiIsCgkgICAgInBvc2l0aW9uIjogImZhbHNlIgoJf..." } }数据上传结束标识示例{ "data":{ "status":2 } }
返回参数
动态修正返回参数
若开通了动态修正功能并设置了
dwa=wpgs(仅中文支持),还有如下字段返回:
vinfo返回参数
若设置了
vinfo=1,还有如下字段返回(若同时开通并设置了dwa=wpgs,则vinfo失效):
返回参数示例
{ "code": 0, "message": "success", "sid": "iatxxxxxxxxxxxxx", "data": { "result": { "bg": 0, "ed": 0, "ls": false, "pgs": "rpl", "rg": [ 1, 1 ], "sn": 2, "ws": [ { "bg": 0, "cw": [ { "sc": 0, "w": "测试" } ] }, { "bg": 0, "cw": [ { "sc": 0, "w": "一下" } ] } ] }, "status": 1 } }
错误码
官网:错误码
加密算法说明
hmac-sha256
HMAC-SHA256是一种基于散列函数的消息认证码(HMAC),常用于:API 请求签名、消息完整性验证、用户身份认证。- 它结合了
SHA-256哈希算法 和 一个密钥(key),生成一个固定长度的摘要(MAC),确保数据未被篡改且来源可信。
HMAC-SHA256 工作原理
HMAC(key, message) = SHA256((key ⊕ opad) || SHA256((key ⊕ ipad) || message))
⊕是异或操作opad/ipad是固定填充值||表示拼接
示例
const crypto = require('crypto');
const message = 'hello';
const key = 'my-secret-key';
const hmac = crypto.createHmac('sha256',key).update(message).digest('base64');
console.log(hmac); import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class HmacSha256Java17 {
public static String hmacSha256(String key, String message) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKey);
byte[] hash = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
// 返回 Base64 编码结果(也可以改为十六进制编码)
return Base64.getEncoder().encodeToString(hash);
}
public static void main(String[] args) throws Exception {
String key = "my-secret-key";
String message = "hello";
String signature = hmacSha256(key, message);
System.out.println(signature);
}
}使用第三方库,更加简洁
- 添加 Maven 依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.16.0</version>
</dependency>- 加密
import org.apache.commons.codec.digest.HmacUtils;
String sign = HmacUtils.hmacSha256Hex("secret", "message");base64
Base64是一种将二进制数据(如文件、字节流等)转换为 ASCII 字符串格式的编码方式,广泛应用于数据传输,如在 URL 中传输二进制数据、API 请求中的签名等。- 它的主要优点是兼容性好,避免了直接传输二进制可能导致的乱码或协议冲突问题。
- 缺点是数据膨胀,Base64 编码后的数据大约会比原始二进制数据增加 33%。
Base64 编码/解码原理
编码:将 3 字节(24 bits)转换为 4 个字符,每个字符是从 Base64 字符集(包含 A-Z、a-z、0-9、+、/)中选择的。解码:将 4 个 Base64 字符恢复为 3 字节。
示例
- 编码字符串为 Base64
const str = "Hello, World!";
const encoded = btoa(str); // base64 编码,btoa() = binary to ASCII
console.log(encoded); // 输出: "SGVsbG8sIFdvcmxkIQ=="- 解码 Base64 为字符串
const str = "Hello, World!";
const encoded = btoa(str);
const decoded = atob(encoded); // base64 解码,atob() = ASCII to binary
console.log(decoded); // 输出: "Hello, World!"⚠️ 注意:btoa() 只能处理 ASCII 字符串(即 Latin-1),如果你的字符串包含中文或 emoji,推荐使用下面的安全方式
function encodeBase64(str) {
return btoa(unescape(encodeURIComponent(str)));
}
function decodeBase64(str) {
return decodeURIComponent(escape(atob(str)));
}
const base64 = encodeBase64("你好,世界");
console.log(base64); // 输出:"5L2g5aW977yM5LiW55WM"
console.log(decodeBase64(base64)); // 输出:你好,世界const str = "Hello, Node!";
const base64 = Buffer.from(str).toString('base64');
console.log(base64); // 输出:"SGVsbG8sIE5vZGUh"
const decoded = Buffer.from(base64, 'base64').toString();
console.log(decoded); // 输出:Hello, Node!import java.util.Base64;
public class Base64Example {
public static void main(String[] args) {
String message = "Hello, World!";
// 编码
String encoded = Base64.getEncoder().encodeToString(message.getBytes());
System.out.println("Encoded: " + encoded); // 输出:SGVsbG8sIFdvcmxkIQ==
// 解码
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String decoded = new String(decodedBytes);
System.out.println("Decoded: " + decoded); // 输出:Hello, World!
}
}
Java 还支持 URL-safe 的 Base64 编码,适用于在 URL 中传输 Base64 字符串时(避免使用 + 和 / )
import java.util.Base64;
public class Base64Example {
public static void main(String[] args) {
String message = "Hello, World!";
// URL-safe 编码
String encoded = Base64.getUrlEncoder().encodeToString(message.getBytes());
System.out.println("URL-safe Encoded: " + encoded);
// encoded 进行解码
byte[] decodedBytes = Base64.getUrlDecoder().decode(encoded);
String decoded = new String(decodedBytes);
System.out.println("URL-safe Decoded: " + decoded); // 输出:Hello, World!
}
}









