fix: transcription getUserMedia called before enumerateDevices

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>
This commit is contained in:
kcar 2026-05-21 19:32:43 +00:00
parent 83f17c9ab6
commit 0345258247

View File

@ -28,26 +28,17 @@ export class TranscriptionService {
console.log('🎙️ Starting transcription service...');
try {
// Get default audio device if none selected
if (!this.selectedDeviceId) {
console.log('No device selected, getting default device...');
const devices = await navigator.mediaDevices.enumerateDevices();
const audioDevice = devices.find(device => device.kind === 'audioinput');
if (audioDevice) {
this.selectedDeviceId = audioDevice.deviceId;
console.log('Found default audio device:', audioDevice.label);
}
}
logger.info('transcription-service', '🔊 Requesting microphone access...');
if (!this.selectedDeviceId) {
logger.error('transcription-service', '⚠️ No audio device available');
return;
}
// Call getUserMedia directly — this triggers the browser permission prompt.
// The old code called enumerateDevices() first to find a device ID, but
// without microphone permission deviceId is always "" (empty string, falsy),
// causing an early return that never prompted the user for permission.
const audioConstraints: MediaTrackConstraints = this.selectedDeviceId
? { deviceId: { exact: this.selectedDeviceId } }
: { echoCancellation: true, noiseSuppression: true };
logger.info('transcription-service', '🔊 Accessing user media...');
this.stream = await navigator.mediaDevices.getUserMedia({
audio: { deviceId: this.selectedDeviceId },
});
this.stream = await navigator.mediaDevices.getUserMedia({ audio: audioConstraints });
console.log('Got audio stream');
const uuid = crypto.randomUUID();