voiceCal / fastapi_websocket_server.py
Peter Michael Gits
feat: Implement WebRTC integration following unmute.sh pattern
af83599
#!/usr/bin/env python3
"""
FastAPI WebSocket server for VoiceCal WebRTC integration
Runs alongside Streamlit to provide WebSocket endpoints
"""
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
import asyncio
import logging
import sys
import os
import uvicorn
from datetime import datetime
# Add current directory to path for imports
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# Import our WebRTC handler
try:
from webrtc.server.websocket_handler import webrtc_handler
logging.info("βœ… WebRTC handler imported successfully")
except ImportError as e:
logging.warning(f"⚠️ WebRTC handler not available: {e}")
webrtc_handler = None
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Create FastAPI app
app = FastAPI(title="VoiceCal WebSocket Server", version="1.0.0")
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
async def health_check():
"""Health check endpoint"""
return {
"status": "healthy",
"service": "VoiceCal WebSocket Server",
"timestamp": datetime.now().isoformat(),
"webrtc_handler": "available" if webrtc_handler else "unavailable"
}
@app.websocket("/ws/webrtc/{client_id}")
async def websocket_webrtc_endpoint(websocket: WebSocket, client_id: str):
"""WebRTC WebSocket endpoint following unmute.sh pattern"""
if not webrtc_handler:
await websocket.close(code=1003, reason="WebRTC handler not available")
return
logger.info(f"πŸ”Œ WebRTC WebSocket connection request from client {client_id}")
try:
# Accept connection and initialize with WebRTC handler
await webrtc_handler.connect(websocket, client_id)
logger.info(f"βœ… WebRTC client {client_id} connected and initialized")
# Handle WebSocket messages
while True:
try:
data = await websocket.receive_text()
message_data = json.loads(data)
logger.info(f"πŸ“₯ Received message from {client_id}: {message_data.get('type', 'unknown')}")
# Pass message to WebRTC handler for processing
await webrtc_handler.handle_message(client_id, message_data)
except WebSocketDisconnect:
logger.info(f"πŸ”Œ WebRTC client {client_id} disconnected normally")
break
except Exception as e:
logger.error(f"❌ Error handling message from {client_id}: {e}")
break
except Exception as e:
logger.error(f"❌ WebRTC WebSocket error for {client_id}: {e}")
finally:
# Clean up connection
if webrtc_handler:
await webrtc_handler.disconnect(client_id)
logger.info(f"🧹 Cleaned up WebRTC connection for {client_id}")
# Import json for message parsing
import json
if __name__ == "__main__":
# Run FastAPI server on port 8001 (different from Streamlit's 7860)
logger.info("πŸš€ Starting VoiceCal WebSocket server on port 8001...")
uvicorn.run(
app,
host="0.0.0.0",
port=8001,
log_level="info"
)