实时语音识别连续模式
功能介绍
连续识别模式的语音总长度限制为五小时,适合于会议、演讲和直播等场景。
连续识别模式在流式识别的基础上,结合了语音的端点检测功能。语音数据也是分段输入,但是连续识别模式将会在处理数据之前进行端点检测,如果是语音才会进行实际的解码工作,如果检测到静音,将直接丢弃。如果检测到一段语音的结束点,就会直接将当前这一段的识别结果返回,然后继续检测后面的语音数据。因此在连续识别模式中,可能多次返回识别结果。如果送入的一段语音较长,甚至有可能在一次返回中包括了多段的识别结果。
由于引入了静音检测,连续识别模式通常会比流式识别能具有更高的效率,因为对于静音段将不会进行特征提取和解码操作,因而能更有效地利用CPU。而流式识别通常和客户端的端点检测功能相结合,只将检测到的有效语音段上传到服务器进行识别。
wss-URI
- 参数说明
表1 参数说明 参数名
是否必选
说明
project_id
是
项目编号。获取方法,请参见获取项目ID。
表2 请求Header参数 参数
是否必选
参数类型
描述
X-Auth-Token
是
String
用户Token。
用于获取操作API的权限。获取方法请参见认证鉴权。响应消息头中X-Subject-Token的值即为Token。
Enterprise-Project-Id
否
String
企业项目ID。SIS支持通过企业项目管理(EPS)对不同用户组和用户的资源使用,进行分账。
获取方法:进入“企业项目管理”页面,单击企业项目名称,在企业项目详情页获取Enterprise-Project-Id(企业项目ID)。
企业项目创建步骤请参见用户指南。
说明:账户创建企业项目后,在传参时,有以下三类场景。
- 携带正确的ID,正常使用SIS服务,账单归到企业ID对应的企业项目中。
- 携带错误的ID,正常使用SIS服务,账单的企业项目会被分类为“default”。
- 不携带ID,正常使用SIS服务,账单的企业项目会被分类为“default”。
- 请求示例(伪码)
wss://{endpoint}/v1/{project_id}/rasr/continue-stream Request Header: X-Auth-Token: MIINRwYJKoZIhvcNAQcCoIINODCCDTQCAQExDTALBglghkgBZQMEAgEwgguVBgkqhkiG...
“endpoint”即调用API的请求地址,不同服务不同区域的“endpoint”不同,具体请参见终端节点。
- Python3语言请求代码示例
# -*- coding: utf-8 -*- # 此demo仅供测试使用,强烈建议使用sdk。需提前安装websocket-client, 执行pip install websocket-client import websocket import threading import time import json def rasr_demo(): url = 'wss://{{endpoint}}/v1/{{project_id}}/rasr/continue-stream' # endpoint和project_id需替换 audio_path = '音频路径' token = '用户对应region的token' header = { 'X-Auth-Token': token } with open(audio_path, 'rb') as f: data = f.read() body = { 'command': 'START', 'config': { 'audio_format': 'pcm8k16bit', 'property': 'chinese_8k_common' } } def _on_message(ws, message): print(message) def _on_error(ws, error): print(error) ws = websocket.WebSocketApp(url, header, on_message=_on_message, on_error=_on_error) _thread = threading.Thread(target=ws.run_forever, args=(None, None, 30, 20)) _thread.start() time.sleep(1) ws.send(json.dumps(body), opcode=websocket.ABNF.OPCODE_TEXT) now_index = 0 byte_len = 4000 while now_index < len(data): next_index = now_index + byte_len if next_index > len(data): next_index = len(data) send_array = data[now_index: next_index] ws.send(send_array, opcode=websocket.ABNF.OPCODE_BINARY) now_index += byte_len time.sleep(0.05) ws.send("{\"command\": \"END\", \"cancel\": \"false\"}", opcode=websocket.ABNF.OPCODE_TEXT) time.sleep(10) ws.close() if __name__ == '__main__': rasr_demo()
- Java语言请求代码示例
import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.WebSocket; import okhttp3.WebSocketListener; import okio.ByteString; import java.net.URL; /** * 此demo仅供测试使用,强烈建议使用SDK * 使用前需已配置okhttp、okio jar包。jar包可通过下载SDK获取。 */ public class RasrDemo { public void rasrDemo() { try { // endpoint和projectId需要替换成实际信息。 String url = "wss://{{endpoint}}/v1/{{project_id}}/rasr/continue-stream"; String token = "对应region的token"; byte[] data = null; // 存放将要发送音频的byte数组 OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder().url(url).header("X-Auth-Token", token).build(); WebSocket webSocket = okHttpClient.newWebSocket(request, new MyListener()); webSocket.send("{\"command\": \"START\", \"config\": {\"audio_format\": \"pcm8k16bit\", \"property\": \"chinese_8k_common\"}}"); webSocket.send(ByteString.of(data)); webSocket.send("{ \"command\": \"END\", \"cancel\": false}"); Thread.sleep(10000); webSocket.close(1000, null); } catch (Exception e) { e.printStackTrace(); } } class MyListener extends WebSocketListener { @Override public void onOpen(WebSocket webSocket, Response response) { System.out.println("conneected"); } @Override public void onClosed(WebSocket webSocket, int code, String reason) { System.out.println("closed"); } @Override public void onFailure(WebSocket webSocket, Throwable t, Response response) { t.printStackTrace(); } @Override public void onMessage(WebSocket webSocket, String text) { System.out.println(text); } } public static void main(String[] args) { RasrDemo rasrDemo = new RasrDemo(); rasrDemo.rasrDemo(); } }
- JavaScript(nodejs推荐使用v18.20.2 (LTS)版本)
// 导入 Node.js 的 ws 库 const WebSocket = require('ws'); function continueStremDemo(endpoint,audioPath, projectID, token) { const url = `wss://${endpoint}/v1/${projectID}/rasr/continue-stream`; // 替换 endpoint 和 projectID // 读取音频文件内容 const fs = require('fs'); let data = fs.readFileSync(audioPath); // HTTP Headers中携带Token const headers = { 'X-Auth-Token': token, // 企业id 可选加 // 'Enterprise-Project-Id': 企业id }; // 创建WebSocket实例 const ws = new WebSocket(url, { headers // 添加自定义HTTP头 }); ws.on('open', async () => { const body = { command: 'START', config: { audio_format: 'pcm16k16bit', property: 'chinese_16k_general' } }; ws.send(JSON.stringify(body)); let nowIndex = 0; const byteLen = 3200; // 禁止空值输入 建议范围 2000-10000 while (nowIndex < data.length) { const nextIndex = nowIndex + byteLen; const sendArray = data.slice(nowIndex, nextIndex > data.length ? data.length : nextIndex); ws.send(sendArray, { binary: true }); nowIndex += byteLen; await new Promise(resolve => setTimeout(resolve, 100)); // 模拟延时(单位ms) } const endCommand = JSON.stringify({ command: 'END', cancel: 'false' }); ws.send(endCommand); }); ws.on('message', (data) => { if (data instanceof Buffer) { // 将Buffer转换为UTF-8编码的字符串 const messageString = data.toString('utf8'); console.log('Received (converted from Buffer):', messageString); const type = JSON.parse(messageString).resp_type; if (type ==='END' || type ==='ERROR') { ws.close(); } } }); ws.on('error', (error) => { console.error('WebSocket Error:', error); }); }; continueStremDemo(endpoint,audioPath, projectID, token);