Javascript 谷歌云语音文本转换不';t在某些设备上正确转录流式音频

Javascript 谷歌云语音文本转换不';t在某些设备上正确转录流式音频,javascript,node.js,reactjs,google-cloud-platform,speech-recognition,Javascript,Node.js,Reactjs,Google Cloud Platform,Speech Recognition,在过去的几周里,我使用实时流音频实现了谷歌云语音到文本API。虽然一开始一切看起来都很好,但最近我在更多的设备上测试了该产品,发现在某些iDevices方面存在一些真正奇怪的异常情况。 首先,以下是相关的代码片段: 前端(反应组件) 助手(下采样缓冲) 后端(语音客户端/转录功能,将数据发送到GCloud) 现在,在我测试的设备中,行为变化很大。我最初是在iMac 2017上开发的,使用Google Chrome作为浏览器。工作起来很有魅力。然后,在iPhone11Pro和iPadAIR4上进行

在过去的几周里,我使用实时流音频实现了谷歌云语音到文本API。虽然一开始一切看起来都很好,但最近我在更多的设备上测试了该产品,发现在某些iDevices方面存在一些真正奇怪的异常情况。 首先,以下是相关的代码片段:

前端(反应组件)

助手(下采样缓冲)

后端(语音客户端/转录功能,将数据发送到GCloud)

现在,在我测试的设备中,行为变化很大。我最初是在iMac 2017上开发的,使用Google Chrome作为浏览器。工作起来很有魅力。然后,在iPhone11Pro和iPadAIR4上进行测试,包括Safari和全屏web应用程序。再一次,它像一个符咒

后来我用iPad Pro 12.9“2017进行了尝试。突然,谷歌云有时根本不返回抄本,有时它返回的内容只使用了非常多的幻想,听起来像是实际的语音文本。在iPad 5和iPhone 6 Plus上也有同样的行为

我真的不知道该怎么办。至少到目前为止,我读到的是iPhone 6s(不幸的是,我对iPad一无所知)硬件采样率从44.1khz更改为48khz。所以我想,可能就是这样,在代码中的任何地方都使用采样率,但没有成功。此外,我注意到我的iMac和Google Chrome一样也在44.1khz上运行,就像“旧的”一样“转录不起作用的iPad。同样,新款iPad的运行频率为48khz,在这里一切正常。所以这不可能

我还注意到:当我将一些AirPod连接到“坏”的设备并将它们用作音频输入时,一切都会恢复正常所以这一定与这些设备的内部麦克风的处理有关。我不知道具体是什么

谁能把我引向正确的方向?在音频和麦克风方面,这几代设备之间发生了哪些变化

更新1:我现在实现了一个快速功能,它使用节点wav将流式PCM数据从前端写入后端的文件。我想,我现在离得越来越近了——在语音识别变得疯狂的设备上,我听起来像一只花栗鼠(音调极高)。我还注意到,二进制音频数据的传输速度比一切正常的设备慢。因此,这可能与采样/比特率、编码等有关。不幸的是,我不是一个音频专家,所以不知道下一步该怎么做


更新2:在经历了大量的试验结束错误后,我发现如果我在Google Cloud
RecognitizeConfig
中将采样率设置为9500到10000左右,一切都会正常工作。当我将其设置为节点wav文件输出的采样率时,听起来也不错。如果我再次将“传出”采样率重置为GCloud至16000,并将前端的音频输入从44100降至约25000,而不是16000(请参阅“麦克风处理”功能中的“前端(反应组件)”),它也可以工作。因此,在样本率差异中似乎存在某种~0.6的因素。然而,我仍然不知道这种行为是从何而来的:在工作的iMac上的Chrome和在“坏”的iPad上的Safari都有一个
audioContext.sampleRate
44100。因此,当我在代码中将它们的样本减少到16000时,我认为两者都应该工作,而只有iMac工作。iPad内部的采样率似乎有所不同?

经过大量的尝试和错误,我发现了问题(以及解决方案)。 似乎“较老”的iDevice机型(如2017款iPad Pro)有一些奇怪的特性,自动将麦克风采样率调整为播放音频的速率。即使这些设备的硬件采样率设置为44.1khz,但一旦播放某些音频,采样率就会改变。这可以通过以下方式观察到:

const audioCtx = new webkitAudioContext();
console.log(`Current sample rate: ${audioCtx.sampleRate}`); // 44100
const audio = new Audio();
audio.src = 'some_audio.mp3';
await audio.play();
console.log(`Current sample rate: ${audioCtx.sampleRate}`); // Sample rate of the played audio
const left = e.inputBuffer.getChannelData(0);
const left16 = Helpers.downsampleBuffer(left, this.audioCtx.sampleRate, 16000);
在我的例子中,在打开语音转录套接字之前,我播放了一些从谷歌文本到语音的合成语音。这些声音文件的采样率为24khz——正好是Google Cloud接收到我的音频输入的采样率

因此,解决方案是——无论如何我都应该这样做——将所有内容的采样率降低到16khz(参见问题中的帮助函数),但不是从硬编码的44.1khz,而是从音频上下文的当前采样率。因此,我将microhoneprocess()函数更改为:

const audioCtx = new webkitAudioContext();
console.log(`Current sample rate: ${audioCtx.sampleRate}`); // 44100
const audio = new Audio();
audio.src = 'some_audio.mp3';
await audio.play();
console.log(`Current sample rate: ${audioCtx.sampleRate}`); // Sample rate of the played audio
const left = e.inputBuffer.getChannelData(0);
const left16 = Helpers.downsampleBuffer(left, this.audioCtx.sampleRate, 16000);
结论:不要相信Safari在页面加载时的采样率。它可能会改变

const audioCtx = new webkitAudioContext();
console.log(`Current sample rate: ${audioCtx.sampleRate}`); // 44100
const audio = new Audio();
audio.src = 'some_audio.mp3';
await audio.play();
console.log(`Current sample rate: ${audioCtx.sampleRate}`); // Sample rate of the played audio
const left = e.inputBuffer.getChannelData(0);
const left16 = Helpers.downsampleBuffer(left, this.audioCtx.sampleRate, 16000);