The old startTranscription() called enumerateDevices() first to find a device ID, then getUserMedia. Without microphone permission, enumerateDevices() returns devices with deviceId="" (empty string, falsy). This caused the !this.selectedDeviceId check to bail out early, never calling getUserMedia, never prompting the user for mic permission, and never creating the WebSocket. Result: user clicks Start Recording → isRecording=true → button changes to Stop Recording → but no mic prompt, no WebSocket, no transcription. Fix: call getUserMedia directly (with optional echoCancellation/noiseSuppression if no device pre-selected). getUserMedia triggers the browser permission prompt automatically. Device selection is still honoured via exact deviceId constraint when one has been explicitly chosen. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Description
React 18 + TypeScript + TLDraw 3.6 frontend for Classroom Copilot — whiteboard, transcription panel, timetable, and graph views
Languages
TypeScript
96%
CSS
3.2%
JavaScript
0.5%
Dockerfile
0.2%
HTML
0.1%