| |
| """ |
| 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 |
|
|
| |
| sys.path.append(os.path.dirname(os.path.abspath(__file__))) |
|
|
| |
| 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 |
|
|
| |
| logging.basicConfig(level=logging.INFO) |
| logger = logging.getLogger(__name__) |
|
|
| |
| app = FastAPI(title="VoiceCal WebSocket Server", version="1.0.0") |
|
|
| |
| 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: |
| |
| await webrtc_handler.connect(websocket, client_id) |
| |
| logger.info(f"β
WebRTC client {client_id} connected and initialized") |
| |
| |
| 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')}") |
| |
| |
| 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: |
| |
| if webrtc_handler: |
| await webrtc_handler.disconnect(client_id) |
| logger.info(f"π§Ή Cleaned up WebRTC connection for {client_id}") |
|
|
| |
| import json |
|
|
| if __name__ == "__main__": |
| |
| logger.info("π Starting VoiceCal WebSocket server on port 8001...") |
| uvicorn.run( |
| app, |
| host="0.0.0.0", |
| port=8001, |
| log_level="info" |
| ) |