将Discord音频流传输至Google Cloud Speech API的超时问题排查
解决Google Cloud Speech API音频超时错误的方案
1. 严格匹配音频配置参数
Google Speech API流式识别对音频格式要求严苛,需确保Discord音频与API配置完全对齐:
- Discord返回的PCM为48kHz、16位有符号小端、单声道
- 在API请求的
config中添加audioChannelCount: 1,同时确认sampleRateHertz: 48000和encoding: 'LINEAR16'参数准确
2. 用管道(pipe)替代手动数据写入
手动监听data事件调用write易引发背压问题,导致数据延迟。改用pipe可自动处理流速匹配,保障实时传输:
connection.receiver.speaking.on('start', (userId) => { const audioStream = connection.receiver.subscribe(userId, { mode: 'pcm' }); const request = { config: { encoding: 'LINEAR16', sampleRateHertz: 48000, languageCode: 'es-ES', audioChannelCount: 1, // 新增单声道配置 enableAutomaticPunctuation: true, // 可选:开启自动标点 }, interimResults: false, }; const recognizeStream = client.streamingRecognize(request) .on('data', (data) => { const transcription = data.results[0].alternatives[0].transcript; console.log(`Transcripción: ${transcription}`); }) .on('error', (err) => { console.error('转写错误:', err); recognizeStream.end(); // 出错时及时关闭流 }); // 用pipe替代手动write audioStream.pipe(recognizeStream); audioStream.on('end', () => { recognizeStream.end(); }); });
3. 处理用户停止说话的事件
用户停止说话时,speaking会触发stop事件,需主动关闭对应流,避免API因长时间无音频输入超时:
// 存储活跃转写流,键为userId const activeStreams = new Map<string, { audioStream: any; recognizeStream: any }>(); connection.receiver.speaking.on('start', (userId) => { // 清理用户之前的活跃流(若存在) if (activeStreams.has(userId)) { const { audioStream, recognizeStream } = activeStreams.get(userId)!; audioStream.destroy(); recognizeStream.end(); activeStreams.delete(userId); } const audioStream = connection.receiver.subscribe(userId, { mode: 'pcm' }); const request = { /* 同上述config配置 */ }; const recognizeStream = client.streamingRecognize(request) .on('data', (data) => { /* 处理转写结果 */ }) .on('error', (err) => { /* 处理错误 */ }); audioStream.pipe(recognizeStream); activeStreams.set(userId, { audioStream, recognizeStream }); }); // 监听用户停止说话事件 connection.receiver.speaking.on('stop', (userId) => { if (activeStreams.has(userId)) { const { audioStream, recognizeStream } = activeStreams.get(userId)!; // 延迟1秒关闭,避免短暂静音导致流提前结束(可选) setTimeout(() => { audioStream.destroy(); recognizeStream.end(); activeStreams.delete(userId); }, 1000); } });
4. 添加静音数据填充(可选)
若用户说话间隙较长,Discord不会发送音频数据,可定期向API发送静音PCM数据避免超时:
connection.receiver.speaking.on('start', (userId) => { const audioStream = connection.receiver.subscribe(userId, { mode: 'pcm' }); const request = { /* 同上述config配置 */ }; const recognizeStream = client.streamingRecognize(request) .on('data', (data) => { /* 处理转写结果 */ }) .on('error', (err) => { /* 处理错误 */ }); audioStream.pipe(recognizeStream); // 每500ms发送10ms的静音数据 const silenceInterval = setInterval(() => { // 48kHz 16位单声道,10ms静音数据为 48000*0.01*2=960字节 const silenceBuffer = Buffer.alloc(960, 0); if (connection.receiver.speaking.has(userId)) { recognizeStream.write(silenceBuffer); } else { clearInterval(silenceInterval); } }, 500); audioStream.on('end', () => { clearInterval(silenceInterval); recognizeStream.end(); }); });
5. 优化音频流订阅配置
- 添加
debug: true到subscribe配置,查看音频流日志排查传输问题 - 确保使用
mode: 'pcm',避免使用opus模式(需额外解码)
额外排查点
- 检查机器人网络延迟:若服务器与Google API延迟过高,会导致音频传输不及时,可尝试部署在靠近Google数据中心的服务器
- 确认Google Cloud Speech API配额充足:配额不足可能引发请求限制,导致超时类错误
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

