向Twilio双向流发送Media音频播放出现噪音的问题排查求助
Google TTS转Twilio双向流播放出现静电噪音问题排查
TLDR:从Google TTS API获取mulaw/8000Hz格式音频,通过Twilio Media消息发送到双向流后,呼叫者仅听到刺耳的静电噪音,核心疑问如下:
- 我遗漏了什么?还有哪些未尝试的排查方案?
- 如何本地测试要发送给Twilio的mulaw/8000Hz字节是否可播放?为何Twilio对音频的判定与ffmpeg、sox或Audacity不一致?
- Twilio要求使用哪种base64编码类型(标准、标准无填充、URL安全、URL安全无填充)?
针对常见疑问的验证结果
- 疑问:Twilio规定发送的音频需为audio/x-mulaw编码、8000Hz采样率,是否符合要求?
答案:是。请求Google TTS时已明确指定mulaw编码和8000Hz采样率;将返回的base64字符串解码后保存到本地,ffprobe和soxi均确认音频参数符合要求。 - 疑问:Google生成的mulaw音频附带WAV头,是否已移除头信息再发送给Twilio?
答案:是。解码Google返回的base64字符串后,截取前44字节(WAV头大小),仅对剩余原始音频字节重新进行base64编码后发送;截取后的字节保存到本地,可作为mulaw/8000Hz原始数据导入Audacity并正常播放。 - 疑问:是否正确对mulaw/8000Hz字节进行base64编码?
答案:本地验证正确。将发送给Twilio的标准base64字符串解码后,导入Audacity可正常播放;已尝试所有常见base64编码类型(标准、标准无填充、URL安全、URL安全无填充),均未解决问题。 - 疑问:是否正确格式化发送给Twilio的Media消息?
答案:是。消息格式与Twilio官方示例完全一致。 - 疑问:发送给Twilio的Media消息是否为WS Text消息?
答案:是。 - 疑问:是否在发送Media消息后发送了Mark消息?
答案:是。
相关Rust代码
// Rust代码逻辑与Google TTS官方命令行示例一致 let audio_config = AudioConfig { audio_encoding: Some(AudioConfigAudioEncoding::MULAW), sample_rate_hertz: Some(8_000), ..Default::default() }; // Google TTS API其他配置逻辑... let payload = synthesize_response.audio_content.unwrap(); println!("{payload}"); // `payload` 是带WAV头的mulaw/800Hz音频的base64编码字符串 // Base64解码payload let mut enc = Cursor::new(payload); let mut decoder = read::DecoderReader::new(&mut enc, &engine::general_purpose::STANDARD); let mut body = Vec::new(); decoder.read_to_end(&mut body).unwrap(); // `body` 为原始字节流;写入本地文件后,ffprobe和soxi可识别为mulaw/8000Hz音频,`play`命令可正常播放 // 移除Google返回音频中的WAV头 let trimmed = &body[44..]; // `trimmed` 为无头的mulaw/8000Hz原始音频;写入本地文件后,可作为mulaw编码、8000Hz音频导入Audacity正常播放 // 对无头原始音频重新进行base64编码 let re_encoded: String = engine::general_purpose::STANDARD.encode(trimmed); // 构造发送给Twilio的Media消息 let outbound_media_meta = OutboundMediaMeta { payload: re_encoded, }; let outbound_media = TwilioOutbound::Media { media: outbound_media_meta, stream_sid: stream_sid.clone(), }; let json = serde_json::to_string(&outbound_media).unwrap(); println!("{json}"); // 验证JSON格式符合Twilio Media消息要求(包含`"event": "media"`字段) let message = Message::Text(json); sender.send(message).await.unwrap();
内容的提问来源于stack exchange,提问作者wayeast
相关产品推荐
相关产品推荐

