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

如何停止Twilio WebSocket已发送的音频播放?(Python)

解决方案

一、修复停止媒体流的404错误

Twilio的Call Streams REST资源是只读的,无法通过update方法修改状态,所以你调用stop_media_stream时会返回404。正确的停止流方式是通过WebSocket发送<Stop>事件,而非REST API。

修改你的取消任务函数,添加WebSocket停止事件的发送:

async def cancel_tasks(call_sid, stream_sid, twilio_ws): 
    global listen_task,send_to_tts,send_stream_task
    # 取消正在运行的任务
    if call_sid in send_stream_task:
        if send_stream_task[call_sid].cancel():
            print("\n\nsend stream cancelled correctly\n\n")
    if call_sid in listen_task:
        if listen_task[call_sid].cancel():
            print("Stream Sid: ",stream_sid)
            print("\n\nlisten cancelled correctly\n\n")
    if call_sid in send_to_tts:
        if send_to_tts[call_sid].cancel():
            print("\n\nsend to TTS cancelled correctly\n\n") 
    
    # 通过WebSocket发送停止流事件
    if twilio_ws and twilio_ws.open:
        stop_message = json.dumps({
            'event': 'stop',
            'streamSid': stream_sid
        })
        await twilio_ws.send_text(stop_message)
        print("\n\nStream stopped via WebSocket\n\n")

二、解决已发送音频持续播放的问题

Twilio会缓存已接收的媒体包,即使停止流,缓存的音频仍会播放。可以通过以下几种方式解决:

1. 控制音频块大小,减少缓存量

将Eleven Labs返回的音频流拆分为更小的块发送(比如每块200ms以内),这样取消任务时,Twilio缓存的音频量极少,播放残留时间可忽略。

修改你的stream函数,调整音频块的处理逻辑:

async def stream(audio_stream, twilio_ws, stream_sid, call_sid):
    global send_stream_task
    print(f"\n\nNew streamSID: {stream_sid}\n\n")
    # 定义每块音频的字节数(16kHz单声道PCM,每200ms对应6400字节)
    chunk_size = 6400
    buffer = b""
    async for chunk in audio_stream:
        if chunk:
            buffer += chunk
            # 当缓冲区达到指定大小,发送并清空
            while len(buffer) >= chunk_size:
                audio_chunk = buffer[:chunk_size]
                buffer = buffer[chunk_size:]
                b64_audio = base64.b64encode(audio_chunk).decode('utf-8')
                message = json.dumps({
                    'event': 'media',
                    'streamSid': stream_sid,
                    'media': {'payload': b64_audio}
                })
                send_stream_task[call_sid] = asyncio.create_task(twilio_ws.send_text(message))
                await send_stream_task[call_sid]
    # 发送剩余的缓冲区音频
    if buffer:
        b64_audio = base64.b64encode(buffer).decode('utf-8')
        message = json.dumps({
            'event': 'media',
            'streamSid': stream_sid,
            'media': {'payload': b64_audio}
        })
        await twilio_ws.send_text(message)

2. 发送静音音频覆盖缓存

取消任务并停止流后,立刻发送一段静音的媒体包,Twilio会优先播放静音,覆盖缓存中的剩余音频:

async def send_silence(twilio_ws, stream_sid, duration_ms=500):
    # 生成静音音频(16kHz单声道PCM,静音样本为0)
    sample_rate = 16000
    samples = int(sample_rate * duration_ms / 1000)
    silence = b"\x00\x00" * samples
    b64_silence = base64.b64encode(silence).decode('utf-8')
    message = json.dumps({
        'event': 'media',
        'streamSid': stream_sid,
        'media': {'payload': b64_silence}
    })
    await twilio_ws.send_text(message)

# 在cancel_tasks函数末尾添加:
await send_silence(twilio_ws, stream_sid)

3. 重新发起流连接

如果上述方法效果不佳,可以在停止当前流后,重新通过Twilio的XML指令发起新的流连接,旧的缓存会被清空:

# 定义重新发起流的接口
@application.post('/reconnect-stream')
async def reconnect_stream(call_sid: str = Form(...)):
    response = VoiceResponse()
    connect = Connect()
    URL = f"wss://{PUBLIC_URL}/stream"
    STATUS_URL = f"https://{PUBLIC_URL}/status-call"
    connect.stream(url=URL, status_callback=STATUS_URL, status_callback_method='POST', name=str("<name>"))
    response.append(connect)
    return Response(content=str(response), media_type='text/xml')

# 在cancel_tasks后,调用这个接口更新通话的XML
async def restart_call_stream(call_sid):
    account_sid = os.environ['TWILIO_ACCOUNT_SID']
    auth_token = os.environ['TWILIO_AUTH_TOKEN']
    client = Client(account_sid, auth_token)
    client.calls(call_sid).update(
        url=f"https://{PUBLIC_URL}/reconnect-stream?call_sid={call_sid}",
        method="POST"
    )

三、总结

优先采用控制音频块大小的方式,从根源减少缓存量;配合WebSocket发送停止事件和静音包,可快速终止音频播放。如果需要彻底清除缓存,可选择重新发起流连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:59:59