如何将<Dial>音频流传输至WebSocket,实现通话全量实时转录?
Twilio Dial转接场景下双方通话实时转录解决方案
启用被叫方媒体流
默认<Dial>不会自动转发被叫方的音频流,需要在<Dial>的子元素(如<Number>或<Client>)中添加stream="start"属性,触发Twilio向你的WebSocket端点发送被叫方的媒体流。示例TwiML:<Response> <!-- 启动主叫方媒体流 --> <Start> <Stream url="wss://你的WebSocket服务器地址/stream" /> </Start> <!-- 转接并启动被叫方媒体流 --> <Dial> <Number stream="start">+1234567890</Number> </Dial> </Response>区分WebSocket中的双方流
Twilio在发送媒体流的初始start事件时,会携带participant(如caller/callee)和streamSid字段,每个参与者对应唯一的streamSid。你的WebSocket服务需要基于这些标识,为双方分别创建独立的语音识别会话,避免音频混流。多路流处理示例(Node.js)
用streamSid作为键维护不同的语音识别实例,确保双方音频被单独处理:const { SpeechClient } = require('@google-cloud/speech'); const speechClient = new SpeechClient(); const activeStreams = new Map(); // 存储streamSid到识别流的映射 ws.on('message', (rawData) => { const message = JSON.parse(rawData); switch (message.event) { case 'start': const { streamSid, participant } = message.start; // 配置语音识别参数(匹配Twilio音频格式:8kHz PCMU) const request = { config: { encoding: 'MULAW', sampleRateHertz: 8000, languageCode: 'zh-CN', }, interimResults: true, }; const recognizeStream = speechClient.streamingRecognize(request) .on('data', (res) => { const transcript = res.results[0].alternatives[0].transcript; console.log(`[${participant}] ${transcript}`); }); activeStreams.set(streamSid, recognizeStream); break; case 'media': const { streamSid: mediaStreamSid, media: { payload } } = message; const targetStream = activeStreams.get(mediaStreamSid); if (targetStream) { targetStream.write(Buffer.from(payload, 'base64')); } break; case 'stop': const { streamSid: stopStreamSid } = message.stop; const stopStream = activeStreams.get(stopStreamSid); if (stopStream) { stopStream.end(); activeStreams.delete(stopStreamSid); } break; } });常见问题排查
- 确认Twilio控制台中媒体流功能已启用,WebSocket端点可正常访问
- 检查TwiML中
stream="start"属性是否正确添加到<Number>/<Client>标签中 - 通过Twilio调试日志(控制台→监控→事件)验证被叫方的媒体流请求是否已发送
- 确保WebSocket服务器支持并发连接,能同时处理多个流的音频数据
内容的提问来源于stack exchange,提问作者Pritam Barhate
相关产品推荐
相关产品推荐

