
# websocket接口
#### 功能介绍
一句话识别WebSocket接口支持识别1min以内的音频，交互过程如[图 客户端和服务端交互流程]所示，主要分为开始识别、发送音频数据，结束识别、断开连接四个步骤。
WebSocket接口同http接口一致按次计费，只要建立连接成功，发送音频，服务开始识别，则本次调用计费生效。如果用户发送错误end请求或者持续20s未发送音频而产生了报错，该次调用依然认为生效。如果连接成功后未发送音频直接断开，或者请求字段不正确而产生异常，则认为本次调用无效，不会纳入计费次数。
图1客户端和服务端交互流程   
![](https://support.huaweicloud.com/api-sis/zh-cn_image_0000001194123749.png "点击放大")
#### 授权信息
账号具备所有API的调用权限，如果使用账号下的IAM用户调用当前API，该IAM用户需具备调用API所需的权限，具体权限要求请参见[权限和授权项](https://support.huaweicloud.com/usermanual-sis/sis_09_0016.html)。
#### wss-URI
- wss-URI格式 wss /v1/{project_id}/asr/short-audio
  
- 参数说明
  表1参数说明 
  | 参数名        | 是否必选 | 说明                                                                               |
  |:---|:---|:---|
  | project_id | 是    | 项目编号。获取方法，请参见[获取项目ID](https://support.huaweicloud.com/api-sis/sis_03_0008.html)。 |
     
  表2请求Header参数 
  | 参数                    | 是否必选 | 参数类型   | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
  |:---|:---|:---|:---|
  | X-Auth-Token          | 是    | String | 用户Token。 用于获取操作API的权限。获取方法请参见[认证鉴权](https://support.huaweicloud.com/api-sis/sis_03_0058.html)。响应消息头中X-Subject-Token的值即为Token。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
  | Enterprise-Project-Id | 否    | String | 企业项目ID。SIS支持通过企业项目管理（EPS）对不同用户组和用户的资源使用，进行分账。 获取方法：进入"[企业项目管理](https://console.huaweicloud.com/eps/?#/eps/manager/projects)"页面，单击企业项目名称，在企业项目详情页获取Enterprise-Project-Id（企业项目ID）。 ![](https://support.huaweicloud.com/api-sis/zh-cn_image_0000001902367409.png "点击放大") 企业项目创建步骤请参见用户指南。 说明： 账户创建企业项目后，在传参时，有以下三类场景。 - 携带正确的ID，正常使用SIS服务，账单归到企业ID对应的企业项目中。  - 携带错误的ID，正常使用SIS服务，账单的企业项目会被分类为"default"。  - 不携带ID，正常使用SIS服务，账单的企业项目会被分类为"default"。   |
     
  
 
#### 开始识别
- 功能介绍 当wss握手请求收到成功响应后，客户端到服务端的通信协议会升级为WebSocket协议。通过WebSocket协议，客户端发送开始识别请求，用于配置一句话识别的配置信息。
  
- 请求消息
  表3参数说明 
  | 参数名     | 是否必选 | 参数类型   | 说明                                                                                    |
  |:---|:---|:---|:---|
  | command | 是    | String | 表示客户端发送开始识别请求，参数值需设置为START。                                                           |
  | config  | 是    | Object | 配置信息。结构信息请参见[表 config数据结构]。 |
     
   表4config数据结构 
  | 参数                                                                  | 是否必选 | 参数类型   | 说明                                                                                                                                            |
  |:---|:---|:---|:---|
  | audio_format                                                        | 是    | String | 支持语音的格式，请参见[表 audio_format取值范围]。                                                          |
  | property  | 是    | String | 所使用的模型特征串。通常是 "语种_采样率_领域"的形式，例如chinese_8k_common。请参见[表 property取值范围]。                                       |
  | add_punc                                                            | 否    | String | 表示是否在识别结果中添加标点，取值为yes 、 no，默认no。                                                                                                              |
  | digit_norm                                                          | 否    | String | 表示是否将语音中的数字识别为阿拉伯数字，取值为yes 、 no，默认为yes。识别结束后，会将数字识别为阿拉伯数字。                                                                                    |
  | interim_results                                                     | 否    | String | 是否输出中间结果，可以为yes或no。默认为no，表示不输出中间结果。                                                                                                           |
  | vocabulary_id                                                       | 否    | String | 热词表id，不使用热词则不填写。 创建热词表信息请参考[创建热词表 - CreateVocabulary](https://support.huaweicloud.com/api-sis/sis_03_0071.html)。 |
  | need_word_info                                                      | 否    | String | 表示是否在识别结果中输出分词结果信息，取值为"yes"和"no"，默认为"no"。                                                                                                     |
     
   表5property取值范围 
  | property取值           | 说明                                                                                                                                                |
  |:---|:---|
  | chinese_8k_general   | 支持采样率为8k的中文普通话语音识别，采用新一代端到端识别算法，识别准确率更高。 格式支持pcm8k16bit/alaw8k8bit/ulaw8k8bit，区域支持cn-east-3和cn-north-4（强烈推荐使用）。     |
  | chinese_16k_general  | 支持采样率为16k的中文普通话语音识别，采用新一代端到端识别算法，识别准确率更高。 格式支持pcm16k16bit/alaw16k8bit/ulaw16k8bit，区域支持cn-east-3和cn-north-4（强烈推荐使用）。 |
  | chinese_8k_common    | 支持采样率为8k的中文普通话语音识别，此为旧版引擎，建议使用chinese_8k_general。                                                                                                 |
  | chinese_16k_common   | 支持采样率为16k的中文普通话语音识别，此为旧版引擎，建议使用chinese_8k_general。                                                                                                |
  | sichuan_16k_common   | 支持采样率为16k的中文普通话与四川话方言语音识别。区域仅支持cn-north-4。                                                                                                        |
  | cantonese_16k_common | 支持采样率为16k的粤语方言语音识别。区域仅支持cn-north-4。                                                                                                               |
  | shanghai_16k_common  | 支持采样率为16k的上海话方言语音识别。区域仅支持cn-north-4。                                                                                                              |
     
   表6audio_format取值范围 
  | audio_format取值 | 说明                   |
  |:---|:---|
  | pcm16k16bit    | 16k16bit单通道录音数据。     |
  | pcm8k16bit     | 8k16bit单通道录音数据。      |
  | ulaw16k8bit    | 16k8bit ulaw单通道录音数据。 |
  | ulaw8k8bit     | 8k8bit ulaw单通道录音数据。  |
  | alaw16k8bit    | 16k8bit alaw单通道录音数据。 |
  | alaw8k8bit     | 8k8bit alaw单通道录音数据。  |
     
  ![](https://support.huaweicloud.com/api-sis/public_sys-resources/note_3.0-zh-cn.png)
  目前仅支持裸音频格式，特别是PCM编码的WAV格式，不支持其他WAV头或ARM格式的编码。
  
- 示例
  ```
  {
    "command": "START",
    "config":
    {
      "audio_format": "pcm8k16bit",
      "property": "chinese_8k_general",
      "add_punc": "yes",
      "interim_results": "yes",
      "need_word_info": "yes"
    }
  }
  ```
  
- 状态码 状态码请参见[状态码](https://support.huaweicloud.com/api-sis/sis_03_0044.html)。
  
- 错误码 错误码请参见[错误码](https://support.huaweicloud.com/api-sis/sis_03_0045.html)。
  
 
#### 发送音频数据
在收到"开始识别"的响应之后，可以开始发送音频数据。为了节省流量，音频以二进制数据帧形式（binary message）的方式发送。
音频数据将分片发送，即在获得一定量音频数据的同时就可以发送一个binary message，每个分片建议在50ms\~1000ms之间，建议在需要实时反馈的情况下100ms，不需要实时反馈的情况下500ms。
#### 结束识别
- 功能介绍 对于识别中的对话，需要在WebSocket上发送"结束识别"的请求来取消或结束识别。 "结束识别"请求使用文本类型的数据帧(text message)发送，命令和参数以json字符串的形式提供。
  
- 请求消息
  表7参数说明 
  | 参数名     | 是否必选 | 参数类型   | 说明                     |
  |:---|:---|:---|:---|
  | command | 是    | String | 表示客户端结束识别请求，参数值设置为END。 |
     
  
- 示例
  ```
  {
    "command": "END"
  }
  ```
  
- 状态码 状态码请参见[状态码](https://support.huaweicloud.com/api-sis/sis_03_0044.html)。
  
- 错误码
错误码请参见[错误码](https://support.huaweicloud.com/api-sis/sis_03_0045.html)。
#### 响应结果
- 开始识别响应
  由于WebSocket是全双工的，因此响应就是从服务器端发送给客户端的消息，但也并不是所有的请求信息都有一条对应的响应。服务器端收到"开始识别"请求时，会给出如下响应消息，以json字符串形式放置在text message中。
  表8响应参数 
  | 参数名       | 参数类型   | 说明                       |
  |:---|:---|:---|
  | resp_type | String | 响应类型。参数值为START，表示开始识别响应。 |
  | trace_id  | String | 服务内部的令牌，可用于在日志中追溯具体流程。   |
     
  示例
  ```
  {
      "resp_type": "START",
      "trace_id": "567e8537-a89c-13c3-a882-826321939651"
  }
  ```
  
- 结果响应 服务端在收到客户端发送的连续音频数据后， 当服务端识别出结果后会实时向客户端按句推送识别结果响应消息， 以json字符串形式放置在text message中。
  
  表9响应参数 
  | 参数名       | 参数类型             | 说明                                                                                                            |
  |:---|:---|:---|
  | resp_type | String           | 响应类型。参数值为RESULT，表示识别结果响应。                                                                                     |
  | trace_id  | String           | 服务内部的令牌，可用于在日志中追溯具体流程。                                                                                        |
  | segments  | Array of Objects | 多句结果。 请参考[表 segment 数据结构]。 |
     
   表10segment 数据结构 
  | 参数名        | 参数类型    | 说明                                                                                                         |
  |:---|:---|:---|
  | start_time | Integer | 一句的起始时间戳，单位为ms。                                                                                            |
  | end_time   | Integer | 一句的结束时间戳，单位为ms。                                                                                            |
  | is_final   | Boolean | true表示是最终结果， false表示为中间临时结果。                                                                               |
  | result     | Object  | 调用成功表示识别结果，调用失败时无此字段。 请参考[表 result数据结构]。 |
     
   表11result数据结构 
  | 参数名       | 参数类型            | 说明                                                                                                                                                      |
  |:---|:---|:---|
  | text      | String          | 识别结果。                                                                                                                                                   |
  | score     | Float           | 识别结果的置信度，取值范围：0\~1。由于中间结果会不断刷新和纠正，此置信度会不断变化，直到返回当前句子的最终结果，置信度才固定不变。 说明： 目前置信度作用不是太大，请勿过多依赖此值。 |
  | word_info | Array of Object | 分词输出列表。                                                                                                                                                 |
     
  表12word_info 数据结构 
  | 参数名        | 是否必选 | 参数类型    | 说明   |
  |:---|:---|:---|:---|
  | start_time | 否    | Integer | 起始时间 |
  | end_time   | 否    | Integer | 结束时间 |
  | word       | 否    | String  | 分词   |
     
  示例
  ```
  {
    "resp_type": "RESULT",
    "trace_id": "149edb8a-664b-4f0d-9935-847a57b1e3a5",
    "segments": [
      {
        "start_time": 0,
        "end_time": 5480,
        "is_final": true,
        "result": {
          "text": "欢迎大家使用华为云语音交互服务。",
          "score": 0.8452650904655457,
          "word_info": [
            {
              "start_time": 1700,
              "end_time": 1800,
              "word": "欢"
            },
            {
              "start_time": 1940,
              "end_time": 2040,
              "word": "迎"
            },
            {
              "start_time": 2180,
              "end_time": 2280,
              "word": "大"
            },
            {
              "start_time": 2300,
              "end_time": 2400,
              "word": "家"
            },
            {
              "start_time": 2480,
              "end_time": 2580,
              "word": "使"
            },
            {
              "start_time": 2660,
              "end_time": 2760,
              "word": "用"
            },
            {
              "start_time": 2900,
              "end_time": 3000,
              "word": "华"
            },
            {
              "start_time": 3080,
              "end_time": 3180,
              "word": "为"
            },
            {
              "start_time": 3260,
              "end_time": 3360,
              "word": "云"
            },
            {
              "start_time": 3560,
              "end_time": 3660,
              "word": "语"
            },
            {
              "start_time": 3660,
              "end_time": 3720,
              "word": "音"
            },
            {
              "start_time": 3860,
              "end_time": 3960,
              "word": "交"
            },
            {
              "start_time": 4040,
              "end_time": 4140,
              "word": "互"
            },
            {
              "start_time": 4280,
              "end_time": 4380,
              "word": "服"
            },
            {
              "start_time": 4460,
              "end_time": 4560,
              "word": "务"
            }
          ]
        }
      }
    ]
  }
  ```
  
- 错误响应 错误响应，包括如下情况：
  - 配置串错误，包括存在不识别的配置串，或者配置串值的范围不合法。
  
  - 时序不正确，比如连续发送两次"开始识别"指令。
  
  - 识别过程中发生错误，比如音频解码发生错误。
  
  
  
  表13响应参数 
  | 参数名        | 参数类型   | 说明                                                                                         |
  |:---|:---|:---|
  | resp_type  | String | 参数值为ERROR，表示错误响应。                                                                          |
  | trace_id   | String | 服务内部的跟踪令牌，可用于在日志中追溯具体流程。 在某些错误情况下，可能没有此字段。 |
  | error_code | String | 错误码列表。详细错误码解释，请参见[错误码](https://support.huaweicloud.com/api-sis/sis_03_0045.html)。          |
  | error_msg  | String | 返回错误信息。                                                                                    |
     
  示例
  ```
  {
      "resp_type": "ERROR",
      "trace_id": "567e8537-a89c-13c3-a882-826321939651",
      "error_code": "SIS.0002",
      "error_msg": "***"
  }
  ```
  
- 结束识别响应 服务器端收到"结束识别"请求时或语音识别过程中发生错误，服务端会向客户端推送如下响应消息，以json字符串形式放置在text message中。
  
  表14响应参数 
  | 参数名       | 参数类型   | 说明                                                                       |
  |:---|:---|:---|
  | resp_type | String | 参数值为END，表示结束识别响应。                                                        |
  | trace_id  | String | 服务内部的令牌，可用于在日志中追溯具体流程。                                                   |
  | reason    | String | 结束原因，详情请参见[表 结束原因表]。 |
     
   表15结束原因表 
  | 参数名    | 说明         |
  |:---|:---|
  | NORMAL | 正常结束。      |
  | ERROR  | 识别过程中发生错误。 |
     
  示例
  ```
  {
      "resp_type": "END",
      "trace_id": "567e8537-a89c-13c3-a882-826321939651",
      "reason": "NORMAL"
  }
  ```
  
 
#### 代码示例
```
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
/**
 * 此demo仅供测试使用，强烈建议使用SDK
 * 使用前需已配置okhttp、okio jar包。jar包可通过下载SDK获取。
 */
public class SasrWebsocketDemo {
  public void sasrWebsocketDemo() {
    try {
      // endpoint和projectId需要替换成实际信息。
      String url = "wss://{{endpoint}}/v1/{{project_id}}/asr/short-audio";
      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_general\"}}");
      webSocket.send(ByteString.of(data));  // audio太大注意要分片发送，否则会报错。建议分片大小3200
      webSocket.send("{  \"command\": \"END\"}");
      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("connected");
    }
    @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) {
    SasrWebsocketDemo sasrWebsocketDemo = new SasrWebsocketDemo();
    sasrWebsocketDemo.sasrWebsocketDemo();
  }
}
```
