You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure文本转语音音频流回传Twilio无响应问题排查

问题分析与解决方案

一、音频回传无声音的问题排查

1. TwiML指令顺序错误

你的TwiML代码中,<Connect>之后直接跟着<Say>指令,这会导致Twilio建立WebSocket连接后,立即执行<Say>并结束通话。TwiML按顺序执行,<Connect>不会阻塞后续指令,当WebSocket连接建立后,Twilio会继续处理<Say>,播放完成后直接断开通话,此时回传音频时通话已终止,自然听不到声音。

修复方法:移除后续的<Say>指令,确保通话在WebSocket连接期间保持活跃:

const response = new VoiceResponse();
const connect = response.connect();
const stream = connect.stream({
  url: "wss://<my_websocket_address>",
});
res.type("text/xml");
res.send(response.toString());

2. TTS返回值错误,未传递正确Base64字符串

textToSpeech函数返回的是PassThrough流对象,但WebSocket回传的JSON要求payload是Base64字符串,而非流对象,这会导致Twilio无法解析音频数据。

修复方法:修改textToSpeech直接返回Base64字符串:

const textToSpeech = async (text) => {
  return new Promise((resolve, reject) => {
    const speechConfig = sdk.SpeechConfig.fromSubscription(
      constants.subscriptionkey,
      constants.region
    );
    speechConfig.speechSynthesisLanguage = "en-US";
    speechConfig.speechSynthesisVoiceName = "en-US-AvaMultilingualNeural";
    speechConfig.speechSynthesisOutputFormat = sdk.SpeechSynthesisOutputFormat.Raw8Khz8BitMonoMULaw;

    const synthesizer = new sdk.SpeechSynthesizer(speechConfig, null);

    synthesizer.speakTextAsync(
      text,
      (result) => {
        const { audioData } = result;
        synthesizer.close();
        const base64Audio = Buffer.from(audioData).toString("base64");
        console.log("TTS DONE");
        resolve(base64Audio);
      },
      (error) => {
        synthesizer.close();
        reject(error);
      }
    ); 
  });
};

回传代码直接使用返回的字符串:

let payload = await tts.textToSpeech("Hello, how can i help you?")
var json = {
  "event": "media",
  "streamSid": "<从Twilio的start事件中获取的streamSid>",
  "media": {
    "payload": payload
  }
}
this.connection.send(JSON.stringify(json))

3. StreamSid硬编码,未使用实际会话的StreamSid

你代码中的streamSid是固定值,但每个通话的StreamSid是唯一的,由Twilio在WebSocket连接建立时发送的start事件提供。硬编码会导致Twilio无法关联你的media事件到正确通话流。

修复方法:监听WebSocket的start事件,动态获取并保存StreamSid:

// WebSocket消息监听示例
connection.on('message', (message) => {
  const data = JSON.parse(message);
  if (data.event === 'start') {
    this.currentStreamSid = data.streamSid; // 保存当前会话的streamSid
  }
});

// 回传时使用动态获取的streamSid
var json = {
  "event": "media",
  "streamSid": this.currentStreamSid,
  "media": {
    "payload": payload
  }
}
this.connection.send(JSON.stringify(json))

4. 未正确序列化JSON对象

直接将JSON对象传给connection.send()会导致格式错误,WebSocket的send方法需要接收字符串类型数据。

修复方法:使用JSON.stringify()将对象转为字符串后发送,如上述代码所示。

二、Twilio控制台查看WebSocket消息的方法

可以通过Twilio Debugger查看WebSocket相关事件和消息:

  1. 登录Twilio控制台,进入Monitor -> Debugger。
  2. 筛选Media Stream相关事件,即可查看WebSocket连接建立、收发消息的详情,包括你发送的media事件和Twilio的响应。
  3. 也可在具体通话记录详情页(Monitor -> Calls,点击对应通话)查看该通话关联的Media Stream日志。

内容的提问来源于stack exchange,提问作者Swapnil Pandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:43:18