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

基于Twilio的Python Flask应用实现边听边说及中断重述功能求助

解决Twilio中同时实现语音播报与持续监听的方案

Twilio的TwiML确实是线性执行,但可以通过两种方式实现你要的“播报时监听打断”需求:

方案一:利用<Gather>嵌套<Say>实现原生打断支持

Twilio的<Gather>标签允许嵌套<Say>,结合默认开启的interruptible参数,就能在播报文本的同时监听用户语音输入,用户一说话就会立即停止播报并触发action回调。

Flask代码示例

from flask import Flask, request
from twilio.twiml.voice_response import VoiceResponse, Gather, Say

app = Flask(__name__)

# 初始路由:处理来电或启动对话
@app.route("/voice", methods=['GET', 'POST'])
def voice():
    # 这里假设已经获取到用户之前的语音转写文本(实际可从数据库/会话中读取)
    user_transcript = "你刚才说的是:明天一起去爬山"
    
    response = VoiceResponse()
    # 创建Gather,同时监听语音输入,打断后跳转到handle_interruption路由
    gather = Gather(
        input='speech',
        action='/handle_interruption',
        speech_model='phone_call',  # 适合通话场景的语音模型
        timeout=10  # 播报结束后等待用户输入的超时时间
    )
    # 在Gather中嵌套Say,实现播报+监听并行
    gather.say(user_transcript, voice='alice')
    response.append(gather)
    
    # 如果用户没打断,播报完成后回到监听状态
    response.redirect('/voice')
    
    return str(response)

# 处理用户打断的路由
@app.route("/handle_interruption", methods=['GET', 'POST'])
def handle_interruption():
    # 获取用户打断时的语音转写结果
    interruption_text = request.values.get('SpeechResult', '')
    
    response = VoiceResponse()
    if interruption_text:
        # 处理用户的打断内容,比如转写后准备后续重述
        response.say(f"你打断说的是:{interruption_text}")
    
    # 回到持续监听状态
    response.redirect('/voice')
    
    return str(response)

if __name__ == "__main__":
    app.run(debug=True)

核心逻辑说明

  • <Gather>嵌套<Say>后,Twilio会在播报的同时启动语音监听。
  • 用户说话时,interruptible=True会立即终止播报,将转写结果发送到action指定的路由。
  • 播报完成后,Gather会继续监听用户输入,超时后自动重定向回到监听状态。

方案二:使用Media Stream API实现自定义实时控制

如果需要更精细的控制(比如自定义语音检测阈值、实时处理音频数据),可以用Twilio Media Stream API,通过WebSocket实时获取用户音频流,同时控制TTS播放。

核心步骤与代码示例

  1. 启动Media Stream的TwiML路由
@app.route("/start_stream", methods=['GET', 'POST'])
def start_stream():
    response = VoiceResponse()
    # 指向你的WebSocket处理端点(需使用HTTPS/WSS)
    response.stream(url='wss://your-server-domain/stream_handler')
    return str(response)
  1. 用Flask-SocketIO处理WebSocket连接
from flask_socketio import SocketIO, emit
import webrtcvad  # 用于语音活动检测

socketio = SocketIO(app, cors_allowed_origins="*")
vad = webrtcvad.Vad(3)  # 3代表高灵敏度

@socketio.on('connect')
def on_stream_connect():
    print("媒体流连接成功")
    # 发送TTS播报指令到Twilio(需结合Twilio TTS API或自定义TTS服务)
    emit('play_tts', {'text': '你刚才说的是:周末去海边'})

@socketio.on('media')
def on_media_receive(data):
    # 解析Twilio发送的音频 payload(PCM格式)
    audio_payload = bytearray.fromhex(data['media']['payload'])
    # 用webrtcvad检测是否有语音活动,适配Twilio的8kHz采样率
    is_speaking = vad.is_speech(audio_payload, 8000)
    
    if is_speaking:
        # 立即停止TTS播报
        emit('stop_tts')
        # 调用语音转写API处理用户输入(比如Twilio Speech-to-Text)
        transcribed_text = transcribe_audio(audio_payload)
        print(f"用户打断内容:{transcribed_text}")

def transcribe_audio(audio_data):
    # 实现语音转写逻辑,可调用Twilio或第三方语音服务
    return "我不想听你重述了"

if __name__ == "__main__":
    socketio.run(app, debug=True)

核心逻辑说明

  • 通过Media Stream获取实时音频流,用语音活动检测库(如webrtcvad)判断用户是否说话。
  • 检测到语音后,立即停止当前TTS播报,处理用户的新输入。
  • 这种方式灵活性更高,但需要处理WebSocket通信、音频解析和第三方服务集成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:13:39