IBM Cloud Docs
WebSocket 接口

WebSocket 接口

IBM Watson® Speech to Text 服务的 WebSocket 接口是客户机与服务进行交互的最自然的方法。 要将 WebSocket 接口用于语音识别,请首先使用 /v1/recognize 方法来建立与服务的持久连接。 然后,您可以通过连接发送文本和二进制消息,以启动和管理识别请求。

WebSocket 凭借自身的优点,成为语音识别的首选机制。 有关更多信息,请参阅 WebSocket 接口的优点。 有关 WebSocket 界面及其参数的更多信息,请参阅 API和SDK参考

管理 WebSocket 连接

WebSocket 的认可请求和响应周期包括以下步骤:

  1. 打开连接
  2. 启动识别请求
  3. 发送音频和接收识别结果
  4. 结束识别请求
  5. 发送其他请求和修改请求参数
  6. 使连接保持活动
  7. 关闭连接

客户机将数据发送到服务时,所有 JSON 消息必须作为文本消息传递,并且所有音频数据必须作为二进制消息传递。

以下示例代码片段是用 JavaScript 编写的,并基于 HTML5 WebSocket API。 如需了解有关 WebSocket 协议的更多信息,请参阅互联网工程任务组(IETF) 意见征询(RFC)6455

打开连接

Speech to Text 服务使用 WebSocket Secure (WSS) 协议使 /v1/recognize 方法在以下端点可用:

wss://api.{location}.speech-to-text.watson.cloud.ibm.com/instances/{instance_id}/v1/recognize

其中 {location} 指示应用程序的托管位置:

  • us-south 表示达拉斯
  • us-east 表示华盛顿
  • eu-de 表示法兰克福
  • au-syd 表示悉尼
  • jp-tok 表示东京
  • eu-gb 表示伦敦
  • kr-seo 表示首尔

{instance_id} 是您服务实例的唯一标识符。

文档中的示例将 wss://api.{location}.speech-to-text.watson.cloud.ibm.com/instances/{instance_id} 缩写为 {ws_url}。 所有 WebSocket 示例都将该方法称为 {ws_url}/v1/recognize

一个 WebSocket 客户端调用 /v1/recognize 方法,并带有以下查询参数,用于与服务建立经过身份验证的连接。 您只能通过 WebSocket URL 的查询参数来指定请求的这些方面。

access_token (必需 字符串)

传递有效的访问令牌,以建立与服务的已认证连接。 必须在访问令牌到期之前建立连接。 传递访问令牌仅用于建立已认证的连接。 建立连接后,可以使其无限期保持活动。 只要连接保持打开,您始终会处于已认证状态。 对于在令牌到期时间后持续存在的活动连接,无需刷新访问令牌。 一旦建立了连接,它就可以保持活动状态,即使在删除令牌或其凭证之后也是如此。

  • IBM Cloud 传递 Identity and Access Management (IAM) 访问令牌以向服务进行认证。 通过调用传递的是 IAM 访问令牌,而不是传递 API 密钥。 更多信息,请参见 验证至 IBM Cloud
  • IBM Cloud Pak for Data IBM Software Hub 传递访问令牌,就像传递 AuthorizationHTTP 请求的标头。 更多信息,请参见 验证至 IBM Cloud Pak for Data
model (可选 字符串)

指定要用于转录的语言模型。 如果您没有指定模型,则默认使用 en-US_BroadbandModel。 有关更多信息,请参阅

language_customization_id (可选 字符串)

指定要用于通过连接发送的所有请求的定制语言模型的全局唯一标识 (GUID)。 定制语言模型的基本模型必须与 model 参数的值相匹配。 如果您包含自定义语言模型ID,则必须使用拥有自定义模型的服务实例的凭证来提出请求。 缺省情况下,不会使用定制语言模型。 有关更多信息,请参阅 使用定制语言模型进行语音识别

acoustic_customization_id (可选 字符串)

指定自定义声学模型的GUID,用于通过连接发送的所有请求。 定制声学模型的基本模型必须与 model 参数的值相匹配。 如果您要添加自定义声学模型ID,则必须使用拥有自定义模型的服务实例的凭据提出请求。 缺省情况下,不会使用定制声学模型。 有关更多信息,请参阅 使用定制声学模型进行语音识别

base_model_version (可选 字符串)

指定要用于通过连接发送的所有请求的基本 model 的版本。 此参数主要与针对新基本模型升级的定制模型配合使用。 缺省值取决于此参数是否与定制模型配合使用。 有关更多信息,请参阅 使用升级后的定制模型发出语音识别请求

x-watson-metadata (可选 字符串)

将客户标识与通过连接传递的所有数据相关联。 此参数接受自变量 customer_id={id},其中 id 是要与数据关联的随机或通用字符串。 必须对该自变量进行 URL 编码,以转入该参数,例如 customer_id%3dmy_customer_ID。 缺省情况下,没有客户标识与数据相关联。 有关更多信息,请参阅信息安全

x-watson-learning-opt-out (可选 布尔值)

IBM Cloud 指示服务是否记录通过连接发送的请求和结果。 要阻止 IBM 访问您的数据以进行一般服务改进,请为此参数指定 true。 有关更多信息,请参阅请求日志记录

以下 JavaScript 代码片段将打开与服务的连接。 对 /v1/recognize 方法的调用传递 access_tokenmodel 查询参数,后者用于指示服务使用西班牙语宽带模型。 建立连接后,客户机定义了事件侦听器(onOpenonClose 等)以响应来自服务的事件。 客户机可以将连接用于多个识别请求。

var access_token = '{access_token}';
var wsURI = '{ws_url}/v1/recognize'
  + '?access_token=' + access_token
  + '&model=es-ES_BroadbandModel';
var websocket = new WebSocket(wsURI);

websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };

客户机可以打开与服务的多个并行 WebSocket 连接。 并行连接数仅受限于服务的容量,这通常不会对用户造成任何问题。

启动识别请求

要启动识别请求,客户机将通过已建立的连接向服务发送 JSON 文本消息。 客户机在发送要转录的任何音频之前,必须先发送此消息。 邮件必须包含 action 参数,但通常可以省略 content-type 参数:

action (必需 字符串)
指定要执行的操作:
content-type (可选 字符串)
标识请求的音频数据的格式(MIME 类型)。 对于 audio/alawaudio/basicaudio/l16audio/mulaw 格式,此参数是必需的。 有关更多信息,请参阅音频格式

消息还可以包含可选参数,以指定请求处理方式的其他方面以及要返回的信息。 这些其他参数包括 interim_results 参数,此参数仅可用于 WebSocket 接口。

  • 有关所有语音识别功能的更多信息,请参阅 参数摘要
  • 有关 interim_results 参数的更多信息,请参阅 临时结果

以下 JavaScript 代码片段通过 WebSocket 连接发送用于识别请求的初始化参数。 这些调用包含在客户机的 onOpen 函数中,以确保这些调用仅在建立连接后发送。

function onOpen(evt) {
  var message = {
    action: 'start',
    content-type: 'audio/l16;rate=22050'
  };
  websocket.send(JSON.stringify(message));
}

如果成功接收请求,服务将返回以下文本消息,表明其为 listeninglistening 状态表明服务实例已配置(JSON start 消息有效),并已准备好接受识别请求的音频。

{'state': 'listening'}

如果客户机为识别请求指定了无效的查询参数或 JSON 字段,那么服务的 JSON 响应会包含 warnings 字段。 此字段描述每个无效自变量。 尽管出现警告,请求仍会成功。

发送音频和接收识别结果

在发送初始 start 消息后,客户即可开始向服务发送音频数据。 客户机无需等待服务使用 start 消息来响应 listening 消息。 开始侦听后,服务会处理在 listening 消息之前发送的任何音频。

客户机必须将音频作为二进制数据发送。 客户每次 send 请求最多可发送100 MB的音频数据。 对于任何请求,客户机都必须发送至少 100 字节的音频。 客户可以通过一个 WebSocket 连接发送多个请求。 有关使用压缩技术以最大化请求中可传递给服务的音频量的信息,请参阅 数据限制和压缩

WebSocket 接口将最大帧大小限制为 4 MB。 客户机可以将最大帧大小设置为小于 4 MB。 如果设置帧大小不现实,那么客户机可以将最大消息大小设置为小于 4 MB,并将音频数据作为消息序列发送。 有关 WebSocket 框架的更多信息,请参阅 IETF RFC 6455

服务如何通过 WebSocket 连接发送识别结果取决于客户机是否请求临时结果。 有关更多信息,请参阅 服务如何发送识别结果

以下 JavaScript 代码片段将音频数据作为二进制消息 (blob) 发送到服务:

websocket.send(blob);

以下片段接收服务异步返回的识别假设。 结果由客户机的 onMessage 函数进行处理。

function onMessage(evt) {
  console.log(evt.data);
}

您的代码必须准备好处理来自服务的返回码。 有关更多信息,请参阅 WebSocket 返回码

结束识别请求

完成将请求的音频数据发送到服务的操作时,客户机必须通过下列其中一种方式来发出信号,指示结束将二进制音频传输到服务:

  • 发送将 action 参数设置为值 stop 的 JSON 文本消息:

    {action: 'stop'}
    
  • 发送空的二进制消息,其中指定的 blob 为空:

    websocket.send(blob)
    

如果客户没有发出传输完成的信号,连接可能会超时,而服务端不会发送最终结果。 要在多个识别请求之间接收最终结果,客户机必须在发送下一个请求之前,发出信号指示结束前一个请求的传输。 返回第一个请求的最终结果后,服务会向客户机返回另一个 {"state":"listening"} 消息。 此消息指示服务已准备好接收另一个请求。

发送其他请求和修改请求参数

WebSocket 连接保持活动时,客户机可以继续使用该连接来发送对新音频的进一步识别请求。 缺省情况下,对于通过同一连接发送的所有后续请求,服务会继续使用随先前 start 消息一起发送的参数。

为了更改后续请求的参数,客户可以在收到最终识别结果和服务部门发送的新 {"state":"listening"} 邮件后,发送另一封包含新参数的 start 邮件。 客户机可以更改任何参数,但在打开连接时指定的参数(modellanguage_customization_id 等)除外。

以下示例为通过连接发送的后续识别请求,发送包含新参数的 start 消息。 该消息指定的 content-type 与先前示例相同,但它指示服务为转录的词返回置信度度量和时间戳记。

var message = {
  action: 'start',
  content-type: 'audio/l16;rate=22050',
  word_confidence: true,
  timestamps: true
};
websocket.send(JSON.stringify(message));

使连接保持活动

如果发生不活动状态超时或会话超时,服务将终止会话并关闭连接:

  • 如果客户机正在发送音频,但服务检测不到任何语音,那么会发生不活动状态超时。 缺省情况下,不活动状态超时为 30 秒。 可以使用 inactivity_timeout 参数指定其他值,包括 -1,这表示将超时设置为无穷大。 有关更多信息,请参阅不活动状态超时
  • 如果服务在 30 秒内未从客户机收到任何数据或未发送中间结果,那么会发生会话超时。 您不能更改此超时的长度,但可以通过在发生超时之前向服务发送任何音频数据(包括仅含有静默的数据)来延长会话。 此外,还必须将 inactivity_timeout 设置为 -1。 但会根据发送到服务的任何数据的持续时间向您收费,包括发送用于延长会话的静默。 有关更多信息,请参阅会话超时

WebSocket 客户机和服务器还可以通过定期交换少量数据来交换 Ping/Pong 帧以避免读取超时。 许多 WebSocket 堆栈都会交换 Ping/Pong 帧,但有些不交换。 要确定您的实现是否使用了 Ping/Pong 帧,请检查其功能列表。 您无法以编程方式确定或管理 Ping/Pong 帧。

如果 WebSocket 堆栈未实现 Ping/Pong 帧,并且要发送长音频文件,那么连接可能会遇到读取超时。 要避免此类超时,请连续将音频流式传输到服务,或向服务请求中间结果。 这两种方法中的任一种都可以确保缺少 Ping/Pong 帧不会导致连接关闭。

有关乒乓球桌的更多信息,请参阅IETF RFC 6455 的 5.5.2 Ping5.5.3 Pong部分

关闭连接

客户机完成与服务的交互时,可以关闭 WebSocket 连接。 连接关闭后,客户机就无法再使用该连接来发送请求或接收结果。 仅在客户收到请求的所有结果后关闭连接。 如果客户没有明确关闭连接,连接最终将超时并关闭。

以下 JavaScript 代码片段关闭打开的连接:

websocket.close();

服务如何发送识别结果

服务如何向客户机发送语音识别结果取决于客户机是否请求临时结果。 在对请求的 JSON 响应中,最终结果标记为 "final": true,临时结果标记为 "final": false。 有关更多信息,请参阅中间结果

在以下示例中,结果显示服务对同时提交了临时结果和未提交临时结果的相同输入音频的响应。 音频播放“1 2 ……暂停 ……3 4”的短语,其中“2”和“3”之间有一秒的暂停 暂停足够长的时间来表示单独的话语。 发声是输入音频的一个组成部分,它会引发响应,通常是由于长时间的沉默。 有关更多信息,请参阅 了解语音识别结果

如果结果包含多个最终结果,请将最终结果的 transcript 元素连接在一起,以组合成音频的完整转录。 有关更多信息,请参阅 result_index 字段

没有临时结果的示例请求

客户机通过将 interim_results 参数设置为 false 或从请求中省略参数 (参数的缺省参数为 false) 来禁用中间结果。 客户机仅在发送 stop 消息后才会在响应中接收单个 JSON 对象。

响应对象可以包含音频的单独发声的多个最终结果。 直到服务接收到 stop 消息以指示请求的音频传输已完成后,该服务才会发送单个响应对象。 无论您使用的是前代模型还是下一代模型,服务响应的结构和格式都是相同的。

{
  "result_index": 0,
  "results": [
    {
      "alternatives": [
        {
          "confidence": 0.99,
          "transcript": "one two "
        }
      ],
      "final": true
    },
    {
      "alternatives": [
        {
          "confidence": 0.99,
          "transcript": "three four "
        }
      ],
      "final": true
    }
  ]
}

具有临时结果的示例请求

客户机请求临时结果,如下所示:

  • 对于先前生成的模型, 通过将 interim_results 参数设置为 true
  • 对于下一代模型, 通过将 interim_resultslow_latency 参数设置为 true。 要使用下一代模型接收临时结果,该模型必须支持低延迟,并且必须将 interim_resultslow_latency 参数都设置为 true
    • 有关哪些下一代模型支持低延迟的更多信息,请参阅 支持的下一代模型
    • 有关 interim_resultslow_latency 参数与下一代模型 (包括演示不同参数组合的示例) 的交互的更多信息,请参阅 请求临时结果和低延迟

客户机接收多个 JSON 对象作为响应。 服务针对每个临时结果以及音频生成的每个最终结果返回单独的响应对象。 服务针对每个最终结果至少发送一个临时结果。

服务会在响应可用时立即发送响应。 它不会等待 stop 消息发送其结果,但仍需要 stop 消息来指示请求的传输结束。 无论您使用的是前代模型还是下一代模型,服务响应的结构和格式都是相同的。

{
  "result_index": 0,
  "results": [
    {
      "alternatives": [
        {
          "transcript": "one "
        }
      ],
      "final": false
    }
  ]
}{
  "result_index": 0,
  "results": [
    {
      "alternatives": [
        {
          "transcript": "one two "
        }
      ],
      "final": false
    }
  ]
}{
  "result_index": 0,
  "results": [
    {
      "alternatives": [
        {
          "confidence": 0.99,
          "transcript": "one two "
        }
      ],
      "final": true
    }
  ]
}{
  "result_index": 1,
  "results": [
    {
      "alternatives": [
        {
          "transcript": "three "
        }
      ],
      "final": false
    }
  ]
}{
  "result_index": 1,
  "results": [
    {
      "alternatives": [
        {
          "transcript": "three four "
        }
      ],
      "final": false
    }
  ]
}{
  "result_index": 1,
  "results": [
    {
      "alternatives": [
        {
          "confidence": 0.99,
          "transcript": "three four "
        }
      ],
      "final": true
    }
  ]
}

示例 WebSocket 交换

以下示例显示客户机与 Speech to Text 服务之间通过单个 WebSocket 连接进行的一系列交换。 这些示例侧重于消息和数据的交换。 它们不会显示打开和关闭连接。 (这些示例基于先前生成的模型,因此每个响应的最终抄本都包含一个 confidence 字段。)

第一个示例交换

在第一个交换中,客户机发送包含字符串 Name the Mayflower 的音频。 客户机发送包含单个 PCM (audio/l16) 音频数据块的二进制消息,并指示必需的采样率。 客户机并不等待来自服务的 {"state":"listening"} 响应,而是直接开始发送音频数据,然后发出信号指示结束请求。 立即发送数据可缩短等待时间,因为一旦服务准备好处理识别请求,音频将立即可供服务使用。

  • 客户机发送:

    {
      "action": "start",
      "content-type": "audio/l16;rate=22050"
    }
    <binary audio data>
    {
      "action": "stop"
    }
    
  • 服务响应:

    {"state": "listening"}
    {"results": [{"alternatives": [{"transcript": "name the mayflower ",
                 "confidence": 0.91}], "final": true}], "result_index": 0}
    {"state":"listening"}
    

第二个示例交换

在第二个交换中,客户机发送包含字符串 Second audio transcript 的音频。 客户机在单个二进制消息中发送音频,并使用在第一个请求中指定的相同参数。

  • 客户机发送:

    <binary audio data>
    {
      "action": "stop"
    }
    
  • 服务响应:

    {"results": [{"alternatives": [{"transcript": "second audio transcript ",
                 "confidence": 0.99}], "final": true}], "result_index": 0}
    {"state":"listening"}
    

第三个示例交换

在第三个交换中,客户机再次发送包含字符串 Name the Mayflower 的音频。 它发送一个二进制信息,其中包含一个PCM音频数据块。 但是,这一次,客户机将发送新的 start 消息,该消息请求来自服务的临时结果。

  • 客户机发送:

    {
      "action": "start",
      "content-type": "audio/l16;rate=22050",
      "interim_results": true
    }
    <binary audio data>
    {
      "action": "stop"
    }
    
  • 服务响应:

    {"results": [{"alternatives": [{"transcript": "name "}],
                 "final": false}], "result_index": 0}
    {"results": [{"alternatives": [{"transcript": "name may "}],
                 "final": false}], "result_index": 0}
    {"results": [{"alternatives": [{"transcript": "name may flour "}],
                 "final": false}], "result_index": 0}
    {"results": [{"alternatives": [{"transcript": "name the mayflower ",
                 "confidence": 0.91}], "final": true}], "result_index": 0}
    {"state":"listening"}
    

WebSocket 返回码

服务可以通过 WebSocket 连接向客户机发送以下返回码:

  • 1000 指示连接正常关闭,这意味着已实现建立连接的目的。
  • 1002 指示由于协议错误,服务正在关闭连接。
  • 1006 指示连接异常关闭。
  • 1009 指示帧大小超过 4 MB 限制。
  • 1011 指示服务正在终止连接,因为遇到了阻止服务执行请求的意外状况。

如果套接字由于错误而关闭,那么在套接字关闭之前,客户机会收到格式为 {"error":"{message}"} 的参考消息。 使用 onerror 事件处理程序进行相应响应。 有关 WebSocket 返回代码的更多信息,请参阅 IETF RFC 6455

SDK 的 WebSocket 实现可以返回不同的或其他响应代码。 有关更多信息,请参阅 API 和 SDK 参考