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

Twilio Media Streams+ElevenLabs+OpenAI(Python):呼叫可接通、转录正常,但主叫方听不到声音

Twilio Media Streams+ElevenLabs+OpenAI(Python):呼叫可接通、转录正常,但主叫方听不到声音

兄弟我之前也踩过一模一样的坑!你说的这个场景我太熟悉了——用Twilio Media Streams搭实时AI语音助手,Quart+Hypercorn跑Python服务,转录正常、GPT回复也能生成,但主叫端就是听不到ElevenLabs输出的音频,完全静音对吧?我当时折腾了快一下午,总结了几个最可能的问题点,你挨个排查试试:

1. 最常见的坑:ElevenLabs音频格式和Twilio要求不匹配

Twilio Media Streams对音频格式有严格要求:必须是G.711 μ-law(PCMU)、8kHz采样率、单声道、8位量化的原始音频流。但ElevenLabs默认返回的要么是MP3,要么是16位线性PCM,这俩Twilio都不认!

解决办法:调用ElevenLabs API时,一定要指定output_format为pcm_8000(注意这个是16位线性PCM,还得转成PCMU),然后把返回的音频数据转换成Twilio需要的PCMU格式。比如我当时用的代码片段:

# 调用ElevenLabs获取流式音频
import requests

# 用requests直接调API更灵活,方便处理流式数据
resp = requests.post(
    f"https://api.elevenlabs.io/v1/text-to-speech/{你的语音ID}",
    headers={"xi-api-key": 你的ElevenLabs密钥},
    json={
        "text": gpt生成的回复内容,
        "model_id": "eleven_monolingual_v1",
        "voice_settings": {"stability": 0.6, "similarity_boost": 0.8}
    },
    params={"output_format": "pcm_8000"},  # 关键:指定8kHz 16位线性PCM
    stream=True
)

# 把16位线性PCM转成Twilio需要的PCMU格式
import struct

def linear16_to_pcmu(sample):
    if sample == 0:
        return 0xff
    sign = (sample >> 8) & 0x80
    magnitude = abs(sample)
    if magnitude > 32635:
        magnitude = 32635
    exponent = 0
    temp = magnitude >> 7
    while temp > 0:
        exponent += 1
        temp >>= 1
    exponent = min(exponent, 7)
    mantissa = (magnitude >> (exponent + 3)) & 0x0f
    return ~(sign | (exponent << 4) | mantissa) & 0xff

# 逐块处理音频流
for chunk in resp.iter_content(chunk_size=320):  # 320字节对应40ms音频(16位PCM,8kHz)
    if chunk:
        # 把字节转成16位整数数组
        samples = struct.unpack(f">{len(chunk)//2}h", chunk)
        # 转成PCMU字节
        pcmu_chunk = bytes([linear16_to_pcmu(s) for s in samples])
        # 接下来就是把这个pcmu_chunk发给Twilio

2. WebSocket消息格式不对,Twilio不认

你是不是直接把音频字节发过去了?Twilio要求必须把音频包装成指定的JSON结构,还要用base64编码payload!正确的WebSocket消息应该是这样的:

import json
import base64

# 包装成Twilio要求的Media事件
media_msg = json.dumps({
    "event": "media",
    "media": {
        "payload": base64.b64encode(pcmu_chunk).decode("utf-8")
    },
    "streamSid": 你的Twilio流ID  # 这个必须和Twilio连接时给的streamSid一致
})

# 通过Quart的WebSocket发送
await websocket.send(media_msg)

我当时就是忘了base64编码,直接发原始字节,Twilio根本不处理,自然没声音。

3. 音频发送太滞后或未流式处理

如果你等ElevenLabs把整个音频生成完再一次性发给Twilio,可能Twilio的流已经超时或者主叫端已经听不到了。一定要用流式处理:一边接收ElevenLabs的音频块,一边立刻转码、包装、发送给Twilio,这样声音才会实时出来。

4. 最后可以用Twilio日志排查

去Twilio控制台的「调试日志」里看Media Stream相关的事件,如果Twilio收到了你发的media事件,说明连接和消息格式没问题,那肯定是音频格式的问题;如果没收到media事件,那就是你的WebSocket发送逻辑有问题,比如没拿到正确的streamSid,或者Quart的WebSocket有阻塞。

我当时就是卡在前两个问题上,转对格式+包装正确的JSON后,声音立刻就出来了!你挨个试一遍,应该能解决。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 12:35:26