#!/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" )