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

Python中Twilio通话流发送TTS媒体事件无声音问题排查

问题排查与解决方案

1. gTTS生成格式错误,后续处理失效

gTTS默认输出的是MP3文件,你把它存成.wav后缀并不会改变实际格式,后续用audioop处理MP3数据必然出错。必须先将MP3转成Twilio要求的原始音频格式(8kHz、单声道、16位PCM)。

解决方法:用pydub库完成格式转换:

from pydub import AudioSegment

speak = 'Hallo Welt'
tts = gTTS(text=speak, lang='de')
temp_mp3 = 'temp_audio.mp3'
tts.save(temp_mp3)

# 转成8kHz、单声道、16位PCM的WAV
audio = AudioSegment.from_mp3(temp_mp3)
audio = audio.set_frame_rate(8000).set_channels(1).set_sample_width(2)
temp_wav = 'temp_audio.wav'
audio.export(temp_wav, format='wav')

# 读取原始PCM数据(跳过44字节的WAV文件头)
with open(temp_wav, 'rb') as f:
    audio_data = f.read()[44:]

os.remove(temp_mp3)
os.remove(temp_wav)

2. 音频编码需匹配Twilio要求

Twilio媒体流要求的audio/x-mulaw是基于8kHz单声道16位PCM的编码,用上面的方法得到正确源数据后,再转μ-law:

import audioop

audio_data = audioop.lin2ulaw(audio_data, 2)
payload = base64.b64encode(audio_data).decode('utf-8')

3. 媒体事件格式与StreamSid验证

  • streamSid必须是当前活跃通话流的正确SID,要从Twilio触发的初始start事件中获取,不能硬编码或使用无效值。
  • 检查媒体事件JSON的拼写:event字段值为media,streamSid大小写正确,没有多余或缺失的字段。

4. 确认WebSocket连接状态

发送媒体前要确保WebSocket处于活跃状态,避免连接断开导致发送失败:

if ws.readyState == 1:  # 1代表OPEN状态
    ws.send(json.dumps(media_response))
else:
    print("WebSocket连接已断开")

完整修正代码示例

import gTTS
import os
import audioop
import base64
import json
from pydub import AudioSegment

# 从Twilio的start事件中获取正确的streamSid
sid = "your_active_stream_sid"

speak = 'Hallo Welt'
tts = gTTS(text=speak, lang='de')
temp_mp3 = 'temp_audio.mp3'
tts.save(temp_mp3)

# 转换音频格式
audio = AudioSegment.from_mp3(temp_mp3)
audio = audio.set_frame_rate(8000).set_channels(1).set_sample_width(2)
temp_wav = 'temp_audio.wav'
audio.export(temp_wav, format='wav')

# 读取原始PCM数据
with open(temp_wav, 'rb') as f:
    audio_data = f.read()[44:]

# 清理临时文件
os.remove(temp_mp3)
os.remove(temp_wav)

# 转μ-law编码并生成payload
audio_data = audioop.lin2ulaw(audio_data, 2)
payload = base64.b64encode(audio_data).decode('utf-8')

# 构造并发送媒体事件
media_response = {
    'event': 'media',
    'streamSid': sid,
    'media': {
        'payload': payload,
        'type': 'audio/x-mulaw',
    }
}

if ws.readyState == 1:
    ws.send(json.dumps(media_response))
else:
    print("WebSocket连接已断开")

额外注意事项

  • 安装依赖:pip install gTTS pydub,同时要确保系统安装了ffmpeg并配置好环境变量(pydub依赖ffmpeg处理音频转换)。
  • 测试时可先用已知正确的μ-law音频文件验证Twilio播放逻辑,排除TTS转换环节的问题后再整合完整流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:27:59