更新时间:2024-05-08 GMT+08:00
分享

实时语音识别连续模式

功能介绍

连续识别模式的语音总长度限制为五小时,适合于会议、演讲和直播等场景。

连续识别模式在流式识别的基础上,结合了语音的端点检测功能。语音数据也是分段输入,但是连续识别模式将会在处理数据之前进行端点检测,如果是语音才会进行实际的解码工作,如果检测到静音,将直接丢弃。如果检测到一段语音的结束点,就会直接将当前这一段的识别结果返回,然后继续检测后面的语音数据。因此在连续识别模式中,可能多次返回识别结果。如果送入的一段语音较长,甚至有可能在一次返回中包括了多段的识别结果。

由于引入了静音检测,连续识别模式通常会比流式识别能具有更高的效率,因为对于静音段将不会进行特征提取和解码操作,因而能更有效地利用CPU。而流式识别通常和客户端的端点检测功能相结合,只将检测到的有效语音段上传到服务器进行识别。

wss-URI

  • wss-URI格式

    wss /v1/{project_id}/rasr/continue-stream

  • 参数说明
    表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);

相关文档