Node.js迁移Google Speech-To-Text v2音频流无响应问题求助
问题排查与修复方案
核心问题分析
你的代码存在几个关键问题导致Google Speech-To-Text V2无响应:
- 配置拼写错误:
recognitionConfig里的audoDecodingConfig是笔误,正确字段名是audioDecodingConfig,这个错误会导致API无法识别解码配置。 - 未指定Twilio音频格式:Twilio Stream传输的是PCMU(G.711 μ-law)编码、8kHz采样率的单声道音频,必须在配置中明确声明,否则Google API无法正确解码音频数据。
- 使用私有API方法:
client._streamingRecognize()是内部私有方法,应该使用官方公开的client.streamingRecognize()来创建识别流。 - 音频数据未正确解码:Twilio传来的
msg.media.payload是Base64编码的原始音频,需要先解码为Buffer再传入识别流。
修复后的完整代码
const speech = require('@google-cloud/speech').v2; const fs = require('fs'); const express = require('express'); const bodyParser = require('body-parser'); const WebSocket = require('ws'); const https = require('https'); const client = new speech.SpeechClient({ keyFilename: './googlecreds.json', apiEndpoint: 'eu-speech.googleapis.com' }); const recognizerName = "projects/12345678910/locations/eu/recognizers/name"; // 修正配置:明确Twilio音频格式 const recognitionConfig = { audioDecodingConfig: { encoding: 'PCMU', sampleRateHertz: 8000, audioChannelCount: 1 }, }; const streamingConfig = { config: recognitionConfig, }; const configRequest = { recognizer: recognizerName, streamingConfig: streamingConfig, }; const app = express(); app.use(bodyParser.urlencoded({ extended: true })); // Load your key and certificate const privateKey = fs.readFileSync('location', 'utf8'); const certificate = fs.readFileSync('location', 'utf8'); const ca = fs.readFileSync('location', 'utf8'); const credentials = { key: privateKey, cert: certificate, ca: ca }; const server = https.createServer(credentials, app); const wss = new WebSocket.Server({ server: server, path: '/stream', }); wss.on("connection", function connection(ws) { let recognizeStream = null; ws.on("message", function incoming(message) { try { const msg = JSON.parse(message); switch (msg.event) { case "start": // 使用公开的streamingRecognize方法 const stream = client.streamingRecognize(); recognizeStream = stream[0]; recognizeStream.on('data', response => { if (response.results && response.results.length > 0) { const transcript = response.results[0].alternatives[0].transcript; console.log('转写结果:', transcript); } }) .on('error', err => { console.error('识别流错误:', err); }) .on('end', () => { console.log('识别流已结束'); }); // 发送配置请求 stream[1].write(configRequest); break; case "media": if (!recognizeStream) break; // 将Base64解码为Buffer后传入 const audioBuffer = Buffer.from(msg.media.payload, 'base64'); recognizeStream.write({audio: audioBuffer}); break; case "stop": if (recognizeStream) { recognizeStream.end(); recognizeStream = null; } break; } } catch (err) { console.error('消息处理错误:', err); } }); ws.on('close', () => { if (recognizeStream) { recognizeStream.end(); } }); }); app.post('/voice', (req, res) => { const twiml = ` <Response> <Say>talk now</Say> <Connect> <Stream url="wss://my.domain.com/stream"/> </Connect> <Pause length="60"/> </Response> `; res.type('text/xml'); res.send(twiml); }); const port = process.env.PORT || 8080; server.listen(port, '0.0.0.0', () => { console.log(`Server running on port ${port}`); });
额外排查建议
- 检查Google Cloud控制台的Speech-To-Text API是否已启用,并且服务账号拥有
roles/speech.recognitionUser权限。 - 在识别流的
error事件中打印完整错误对象(而非仅message),便于排查API返回的具体问题。 - 可以先录制一段Twilio的音频数据,用本地脚本测试转写是否正常,排除WebSocket传输环节的问题。
内容的提问来源于stack exchange,提问作者overeqq
相关产品推荐
相关产品推荐

