"""Web server for displaying transcriptions in a browser (for OBS browser source).""" import asyncio from fastapi import FastAPI, WebSocket from fastapi.responses import HTMLResponse from typing import List, Optional import json from datetime import datetime class TranscriptionWebServer: """Web server for displaying transcriptions.""" def __init__(self, host: str = "127.0.0.1", port: int = 8080, show_timestamps: bool = True, fade_after_seconds: int = 10): """ Initialize web server. Args: host: Server host address port: Server port show_timestamps: Whether to show timestamps in transcriptions fade_after_seconds: Time in seconds before transcriptions fade out (0 = never fade) """ self.host = host self.port = port self.show_timestamps = show_timestamps self.fade_after_seconds = fade_after_seconds self.app = FastAPI() self.active_connections: List[WebSocket] = [] self.transcriptions = [] # Store recent transcriptions # Setup routes self._setup_routes() def _setup_routes(self): """Setup FastAPI routes.""" @self.app.get("/", response_class=HTMLResponse) async def get_display(): """Serve the transcription display page.""" return self._get_html() @self.app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): """WebSocket endpoint for real-time updates.""" await websocket.accept() self.active_connections.append(websocket) try: # Send recent transcriptions for trans in self.transcriptions[-20:]: # Last 20 await websocket.send_json(trans) # Keep connection alive while True: # Wait for ping/pong to keep connection alive await websocket.receive_text() except: self.active_connections.remove(websocket) def _get_html(self) -> str: """Generate HTML for transcription display.""" return f"""