/** * Performance Metrics Component * * Developer-focused dashboard showing: * - Real-time inference speed (tokens/sec, RTF) * - Progressive update latency * - Window state (growing vs sliding) * - Memory usage */ import { useState, useEffect } from 'react'; export default function PerformanceMetrics({ latency, rtf, audioDuration, windowState, device, updateInterval, isProcessingFile, fileDuration, transcribedDuration, }) { const [memoryUsage, setMemoryUsage] = useState(null); const [wasProcessingFile, setWasProcessingFile] = useState(false); // Track if we were processing a file (to keep labels after completion) useEffect(() => { if (isProcessingFile) { setWasProcessingFile(true); } }, [isProcessingFile]); useEffect(() => { // Monitor memory usage if available if (performance.memory) { const interval = setInterval(() => { const memory = performance.memory; setMemoryUsage({ used: (memory.usedJSHeapSize / 1024 / 1024).toFixed(1), total: (memory.totalJSHeapSize / 1024 / 1024).toFixed(1), limit: (memory.jsHeapSizeLimit / 1024 / 1024).toFixed(1), }); }, 1000); return () => clearInterval(interval); } }, []); const formatDuration = (seconds) => { if (seconds === null || seconds === undefined) return null; if (seconds < 60) { return seconds.toFixed(1); } const minutes = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${minutes}m ${secs}s`; }; const MetricCard = ({ label, value, unit, color = 'gray', formatTime = false }) => { const displayValue = formatTime ? formatDuration(value) : (value !== null && value !== undefined ? value.toFixed(2) : null); const displayUnit = formatTime ? '' : unit; return (
{label}
{displayValue !== null ? displayValue : 'β€”'} {displayUnit && {displayUnit}}
); }; const getRTFColor = (rtf) => { if (rtf === null || rtf === undefined) return 'gray'; // Higher RTF is better (means faster than real-time) if (rtf > 5) return 'green'; // Excellent (5x+ real-time) if (rtf > 1) return 'yellow'; // Good (faster than real-time) return 'red'; // Slow (slower than real-time) }; const getLatencyColor = (latency) => { if (latency === null || latency === undefined) return 'cyan'; // Lower latency is better if (latency < 0.5) return 'green'; // Excellent (<500ms) if (latency < 1.0) return 'yellow'; // Good (<1s) return 'red'; // Slow (>1s) }; const getWindowStateIcon = (state) => { if (state === 'growing') return 'πŸ“ˆ'; if (state === 'sliding') return '↔️'; return '⏸️'; }; return (

πŸ“Š Performance Metrics

{/* Metrics Grid */}
{/* Additional Info */}
{/* Window State */}
Window State
{getWindowStateIcon(windowState)} {windowState || 'idle'}
{windowState === 'growing' && 'Building context (0-15s)'} {windowState === 'sliding' && 'Sliding window (>15s)'} {!windowState && 'Not recording'}
{/* Device */}
Acceleration
{device === 'webgpu-hybrid' && 'πŸš€ WebGPU Hybrid'} {device === 'webgpu' && 'πŸš€ WebGPU'} {device === 'wasm' && 'βš™οΈ WebAssembly'} {device === 'cpu' && 'πŸ–₯️ CPU'} {!device && 'β€”'}
{device === 'webgpu-hybrid' && 'GPU encoder + WASM decoder'} {device === 'webgpu' && 'Hardware accelerated'} {device === 'wasm' && 'Software optimized'} {device === 'cpu' && 'Fallback mode'}
{/* Memory (if available) */} {memoryUsage && (
Memory Usage
{memoryUsage.used} MB
of {memoryUsage.total} MB allocated
)}
{/* RTF Explanation */} {rtf !== null && rtf !== undefined && (
Real-time Factor (RTF): How many times faster than real-time. {rtf > 1 && ` βœ“ ${rtf.toFixed(1)}x faster than real-time`} {rtf <= 1 && ' ⚠️ Slower than real-time'} {' (Higher is better)'}
)}
{/* Technical Info */}

Model: Parakeet TDT 0.6B v3 (ONNX) | Sample Rate: 16kHz

Progressive updates every 500ms | Smart window management (15s max)

); }