如何优雅地结束 Google Speech-to-Text 流识别并取回待处理的文本结果?

2023-11-23

我希望能够结束 Google 语音转文本流(创建于streamingRecognize),并获取待处理的 SR(语音识别)结果。

简而言之,相关的 Node.js 代码:

// create SR stream
const stream = speechClient.streamingRecognize(request);

// observe data event
const dataPromise = new Promise(resolve => stream.on('data', resolve));

// observe error event
const errorPromise = new Promise((resolve, reject) => stream.on('error', reject));

// observe finish event
const finishPromise = new Promise(resolve => stream.on('finish', resolve));

// send the audio
stream.write(audioChunk);

// for testing purposes only, give the SR stream 2 seconds to absorb the audio
await new Promise(resolve => setTimeout(resolve, 2000));

// end the SR stream gracefully, by observing the completion callback
const endPromise = util.promisify(callback => stream.end(callback))();

// a 5 seconds test timeout
const timeoutPromise = new Promise(resolve => setTimeout(resolve, 5000)); 

// finishPromise wins the race here
await Promise.race([
  dataPromise, errorPromise, finishPromise, endPromise, timeoutPromise]);

// endPromise wins the race here
await Promise.race([
  dataPromise, errorPromise, endPromise, timeoutPromise]);

// timeoutPromise wins the race here
await Promise.race([dataPromise, errorPromise, timeoutPromise]);

// I don't see any data or error events, dataPromise and errorPromise don't get settled

我的经历是 SR 流成功结束,但我没有收到任何数据事件或错误事件。两者都不dataPromise nor errorPromise得到解决或拒绝。

如何发出音频结束信号、关闭 SR 流并仍然获得待处理的 SR 结果?

我需要坚持streamingRecognize API因为我正在流式传输的音频是实时的,即使它可能会突然停止。

澄清一下,只要我继续传输音频,它就可以工作,我确实会收到实时 SR 结果。但是,当我发送最终音频块并像上面那样结束流时,我不会得到我期望的最终结果。

为了得到最终结果,我实际上必须再保持流静默几秒钟,这可能会增加 ST 费用。我觉得一定有更好的方法来获得它们。

Updated:看来,结束一场战争的唯一合适时机streamingRecognize溪流即将来临data活动地点StreamingRecognitionResult.is_final is true。此外,我们预计将继续传输音频,直到data事件被触发,以获得任何结果,最终的或临时的。

这对我来说看起来像是一个错误,提交了一个issue.

Updated:现在看来已经得到证实as a bug。在修复之前,我正在寻找潜在的解决方法。

Updated:以供将来参考,这是清单当前和之前跟踪的问题涉及streamingRecognize.

我希望这对于那些使用的人来说是一个常见问题streamingRecognize,很惊讶以前没有报道过。正在提交as a bug to issuetracker.google.com,还有。


我的错——毫不奇怪,这变成了我的代码中一个模糊的竞争条件。

我已经整理了一个独立的示例,可以按预期工作(gist)。它帮助我追踪问题。希望它可以帮助其他人和我未来的自己:

// A simple streamingRecognize workflow,
// tested with Node v15.0.1, by @noseratio

import fs from 'fs';
import path from "path";
import url from 'url'; 
import util from "util";
import timers from 'timers/promises';
import speech from '@google-cloud/speech';

export {}

// need a 16-bit, 16KHz raw PCM audio 
const filename = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "sample.raw");
const encoding = 'LINEAR16';
const sampleRateHertz = 16000;
const languageCode = 'en-US';

const request = {
  config: {
    encoding: encoding,
    sampleRateHertz: sampleRateHertz,
    languageCode: languageCode,
  },
  interimResults: false // If you want interim results, set this to true
};

// init SpeechClient
const client = new speech.v1p1beta1.SpeechClient();
await client.initialize();

// Stream the audio to the Google Cloud Speech API
const stream = client.streamingRecognize(request);

// log all data
stream.on('data', data => {
  const result = data.results[0];
  console.log(`SR results, final: ${result.isFinal}, text: ${result.alternatives[0].transcript}`);
});

// log all errors
stream.on('error', error => {
  console.warn(`SR error: ${error.message}`);
});

// observe data event
const dataPromise = new Promise(resolve => stream.once('data', resolve));

// observe error event
const errorPromise = new Promise((resolve, reject) => stream.once('error', reject));

// observe finish event
const finishPromise = new Promise(resolve => stream.once('finish', resolve));

// observe close event
const closePromise = new Promise(resolve => stream.once('close', resolve));

// we could just pipe it: 
// fs.createReadStream(filename).pipe(stream);
// but we want to simulate the web socket data

// read RAW audio as Buffer
const data = await fs.promises.readFile(filename, null);

// simulate multiple audio chunks
console.log("Writting...");
const chunkSize = 4096;
for (let i = 0; i < data.length; i += chunkSize) {
  stream.write(data.slice(i, i + chunkSize));
  await timers.setTimeout(50);
}
console.log("Done writing.");

console.log("Before ending...");
await util.promisify(c => stream.end(c))();
console.log("After ending.");

// race for events
await Promise.race([
  errorPromise.catch(() => console.log("error")), 
  dataPromise.then(() => console.log("data")),
  closePromise.then(() => console.log("close")),
  finishPromise.then(() => console.log("finish"))
]);

console.log("Destroying...");
stream.destroy();
console.log("Final timeout...");
await timers.setTimeout(1000);
console.log("Exiting.");

输出:



Writting...
Done writing.
Before ending...
SR results, final: true, text:  this is a test I'm testing voice recognition This Is the End
After ending.
data
finish
Destroying...
Final timeout...
close
Exiting.
  

要测试它,需要 16 位/16KHz 原始 PCM 音频文件。任意 WAV 文件无法按原样工作,因为它包含带有元数据的标头。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何优雅地结束 Google Speech-to-Text 流识别并取回待处理的文本结果? 的相关文章

  • ES6 类文字中的 IIFE

    在 ES5 中我们都可以这样做 myClass prototype myMethod function return function 我可以对 ES6 类文字执行同样的操作吗 不 至少现在还没有 ES6 类仅支持声明方法 因此任何不直接为
  • 刷新页面后保留输入值

    我有一个带有输入字段的表单 该输入包含一个下拉菜单 从数据库中读取信息 如果用户输入值 并且当他到达下拉菜单时 他没有找到他想要的内容 他会转到另一个页面将此信息添加到下拉菜单 然后转到第一页继续输入信息 如果他转到另一个页面向下拉菜单添加
  • Strongloop 环回 如何使用路由进行静态服务?

    我想做类似的事情 server js app use client loopback static dirname client using middleware json 但该示例仅适用于根 files loopback static p
  • 如何显示/隐藏jsf组件

    在我的一个 JSF 应用程序中 顶部的标题部分包含 selectOneMenu 底部的内容部分显示过滤器组件 默认情况下 应用程序首先在顶部显示 selectOneMenu 数据 在底部显示相应的 Filter 信息 如果用户选择不同的se
  • 使用 jquery 更改锚文本和图标

    我有一个隐藏或显示 div 的锚标记 但我无法更改它的文本和图标 如何更改文本和图标标签 因为目前它将图标标签解析为常规文本 锚标记 a class collapse info btn i class icon arrow up icon
  • 使用淘汰赛动态显示/隐藏元素

    我有一个表 有四列 即代码 名称 数量和价格 其中 我想动态更改数量列的内容 元素 通常 它应该显示其中显示数量的元素 当用户单击元素时 我想显示该元素 以便用户可以编辑数量 我正在尝试按照 示例2 来实现淘汰赛文档链接 http knoc
  • 如何将OpenLayers多边形坐标转换为纬度和经度?

    我正在使用开放层 https openlayers org en latest examples draw freehand html绘制多边形并保存坐标的技术 这是我的代码 var raster new ol layer Tile sou
  • Google 地图 Javascript v3 折线点击事件

    我正在尝试显示一张地图 其中有多条路线布置为折线 单击多段线时 我想显示特定于该线的数据 将数据与线关联不是问题 但无论单击哪条线 显示的数据都会与最近绘制的线关联 就好像每条新折线都会覆盖最后一条线一样 我有一个数据库 其中包含 gpx
  • 如何获取 Spotify API 的访问令牌?

    我已经研究 Spotify api 和示例源代码几天了 但我仍然不知道如何获取访问令牌来访问用户的播放列表数据 我已经到达了拉起登录窗口 用户登录 然后收到授权码的地步 此时 我尝试做这样的事情 window open https acco
  • JavaScript/jQuery - “$ 未定义 - $function()”错误

    我正在尝试运行 JavaScript jQuery 函数并且Firebug http en wikipedia org wiki Firebug 28software 29得到错误 is not defined function JavaS
  • 如何在socket.io Nodejs服务器上列出房间

    在问题取得进展后如何创建socket io多播组 https stackoverflow com questions 6616922 how to create socket io multicast groups 6624604 6624
  • Flask 和 Reactjs 抛出 JSX 转换错误

    我已经开始将 ReactJS 与 Python Flask 后端结合使用 通过 Flask 渲染模板时 我在 Chrome 控制台中收到以下客户端错误 错误 找不到模块 jstransform visitors es6 templates
  • 如何处理 setTimeout() 的多个实例?

    阻止创建 setTimeout 函数的多个实例 在 JavaScript 中 的最推荐 最佳方法是什么 一个例子 伪代码 function mouseClick moveDiv div 0001 mouseX mouseY function
  • 如何在使用类型分散时将箭头添加到行尾

    如何在 y 不等于 0 且系列类型以线宽 2 分散的情况下正确地将箭头添加到行的每一端 在这里我可以看到箭头已添加但未正确添加 请看这个 部分工作小提琴 http jsfiddle net vnYCX 这是我的 JS 最初的原型是由 sta
  • jQuery 模板插件:如何创建双向绑定?

    我开始使用 jQuery 模板插件 微软创建的 但现在我面临这个问题 模板用于绑定到对象数组的一堆表单 当我更改其中一个表单上的某些内容时 我希望更新绑定的对象 但我不知道如何自动执行该操作 这是一个简单的例子 现实生活中的模板和对象要复杂
  • 使用mockery和sinon模拟类方法

    我正在学习使用带有 sinon 的节点模块模拟进行单元测试 仅使用模拟和普通类 我就可以成功注入模拟 不过 我想注入一个 sinon 存根而不是一个普通的类 但我在这方面遇到了很多麻烦 我试图嘲笑的班级 function LdapAuth
  • 使用 Node.js 访问用 C++ 编写的 SDK

    我有一个用 C 语言编写的 SDK 可以与我的扫描仪设备进行通信 我需要开发一个可以访问扫描仪设备的电子应用程序 我知道有很多库可用于扫描仪 但我想使用这个 SDK 因为它允许我访问设备的完整功能 而且它是由设备制造商提供的 那么 有没有什
  • 如何在react.js中将/n替换为换行符?

    我正在尝试更换每一个 n to a br tag in ReactJS In my note note对象有一个包含多个的字符串 n in it 示例注释 注释 test ntest ntest 我尝试过的ReactJS note note
  • 如何使用 Chart.js 版本 3.2.1 在圆环图中添加文本

    我正在使用 Canvas 在 HTML 中使用 如何使用在圆环图中添加文本 这是我的 javascript 代码和 HTML 代码 我使用了图表js版本3 2 1 所以请给出相同版本 3 的解决方案 var overallStatsCanv
  • 为什么 phantomjs 不能在 MacOS Sierra 中工作?

    我们正在使用phantomjs 1 9 1 macosx phantomjs 2 0 0 macosx哪一个工作得很好OS X 埃尔卡皮坦更新后macOS 塞拉利昂它会引发以下错误 phantomjs 1 9 1 macosx phanto

随机推荐