admin管理员组文章数量:1313769
I'm developing an application using Twilio's Programmable Voice API and WebSockets to stream media for an outbound call. The call is initiated, and real-time AI processing is done via a WebSocket connection. However, I'm facing an issue where the call does not end automatically when the conversation concludes. Instead, it remains active until I manually hang up the call.
Expected Behavior
- The call should terminate automatically when a predefined condition is met (e.g., after a closing phrase).
- The WebSocket should close when the call is completed.
Current Implementation
I have implemented the call handling using Twilio's API and Media Streams. Below is a simplified version of my implementation:
Call Initiation
import os
import json
import asyncio
import re
import logging
from dotenv import load_dotenv
from fastapi import FastAPI, WebSocket
from fastapi.websockets import WebSocketDisconnect, WebSocketState
from twilio.rest import Client
import websockets
import uvicorn
from twilio.twiml.voice_response import VoiceResponse, Connect, Hangup
load_dotenv()
TWILIO_ACCOUNT_SID = os.getenv("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = os.getenv("TWILIO_AUTH_TOKEN")
PHONE_NUMBER_FROM = os.getenv("PHONE_NUMBER_FROM")
DOMAIN = os.getenv("DOMAIN", "")
PORT = int(os.getenv("PORT", 6060))
twilio_client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)
app = FastAPI()
async def make_call(phone_number: str):
response = VoiceResponse()
connect = Connect()
connect.stream(url=f"wss://{DOMAIN}/media-stream", timeout="10", maxLength="1800")
response.append(connect)
response.append(Hangup())
try:
call = await asyncio.to_thread(
twilio_client.calls.create,
from_=PHONE_NUMBER_FROM,
to=phone_number,
twiml=str(response)
)
return call.sid
except Exception as e:
logging.error(f"Failed to initiate call: {e}")
raise
WebSocket Handling for Media Stream
@app.websocket("/media-stream")
async def handle_media_stream(websocket: WebSocket):
await websocket.accept()
logging.info("WebSocket connected")
try:
async with websockets.connect("wss://api.example/ai-processing") as ai_ws:
await handle_conversation(websocket, ai_ws)
except Exception as e:
logging.error(f"WebSocket error: {e}")
await websocket.close(code=1011)
async def handle_conversation(websocket: WebSocket, ai_ws):
async def receive_from_twilio():
try:
async for message in websocket.iter_text():
data = json.loads(message)
if data.get("event") == "media" and ai_ws.open:
await ai_ws.send(json.dumps({"type": "input_audio_buffer.append", "audio": data["media"]["payload"]}))
except WebSocketDisconnect:
logging.info("Twilio WebSocket disconnected")
async def send_to_twilio():
try:
async for ai_message in ai_ws:
response = json.loads(ai_message)
if response.get("type") == "response.audio.delta":
audio_payload = base64.b64encode(base64.b64decode(response["delta"])).decode("utf-8")
await websocket.send_json({
"event": "media",
"streamSid": "12345",
"media": {"payload": audio_payload}
})
elif response.get("type") == "function_call" and response["function"]["name"] == "end_call":
await end_call()
except Exception as e:
logging.error(f"Error in send_to_twilio: {e}")
await asyncio.gather(receive_from_twilio(), send_to_twilio())
Function to End the Call
async def end_call():
global active_call_sid
if active_call_sid:
try:
logging.info(f"Ending call {active_call_sid}")
await asyncio.to_thread(
twilio_client.calls(active_call_sid).update,
status="completed"
)
logging.info(f"Call {active_call_sid} ended successfully")
active_call_sid = None
except Exception as e:
logging.error(f"Error ending call: {e}")
active_call_sid = None
Open ai tool
from typing import Dict, Any
end_call_tool_definition = {
"type": "function",
"name": "end_call",
"description": "Ends the current interview call after saying goodbye.",
"parameters": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "The reason for ending the call (e.g., 'interview_complete', 'user_request')"
}
},
"required": ["reason"]
}
}
async def end_call_tool(active_call_sid: str, twilio_client) -> Dict[str, Any]:
"""
Tool to terminate the Twilio call
"""
try:
if active_call_sid:
await twilio_client.calls(active_call_sid).update(status="completed")
return {
"status": "success",
"message": f"Call {active_call_sid} terminated successfully"
}
except Exception as e:
return {
"status": "error",
"message": f"Failed to terminate call: {str(e)}"
}
Issue
- The call does not end even after executing the
end_call
function. - The WebSocket connection remains open, and Twilio does not disconnect the media stream.
- The function to terminate the call (
end_call
) logs successful execution, but the call remains active until I manually hang up.
What I Have Tried
- Verified that
end_call
executes and logs a success message. - Ensured
active_call_sid
is correctly assigned. - Checked Twilio logs for any API errors related to call termination.
- Tried using
<Hangup/>
in TwiML, but the issue persists. - Ensured proper WebSocket closure after call termination.
- Also tried tools in the open ai .
Used this code as it is
本文标签: openai apiTwilio Outbound Call with WebSocket Media Stream Not Ending AutomaticallyStack Overflow
版权声明:本文标题:openai api - Twilio Outbound Call with WebSocket Media Stream Not Ending Automatically - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741929617a2405497.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论