diff --git a/client/src/pages/meeting-detail.html b/client/src/pages/meeting-detail.html index e600fa4..3253d2d 100644 --- a/client/src/pages/meeting-detail.html +++ b/client/src/pages/meeting-detail.html @@ -421,6 +421,9 @@ return; } + // Debug: Check if we're in a secure context + console.log('isSecureContext:', window.isSecureContext); + // Check for available audio devices first const devices = await navigator.mediaDevices.enumerateDevices(); const audioInputs = devices.filter(d => d.kind === 'audioinput'); @@ -431,40 +434,56 @@ return; } + // Helper to identify alias deviceIds (not real device IDs) + const isAlias = (id) => id === 'default' || id === 'communications'; + // Filter out Stereo Mix (立體聲混音) - it's not a real microphone const realMicrophones = audioInputs.filter(d => !d.label.includes('立體聲混音') && - !d.label.toLowerCase().includes('stereo mix') && - d.deviceId !== 'default' // Skip default which might be Stereo Mix + !d.label.toLowerCase().includes('stereo mix') ); - // Prefer communications device or actual microphone + // Prefer actual device IDs (long strings), not aliases like 'default' or 'communications' + // First try to find a real microphone with actual deviceId let selectedMic = realMicrophones.find(d => - d.deviceId === 'communications' || - d.label.includes('麥克風') || - d.label.toLowerCase().includes('microphone') - ) || realMicrophones[0]; + !isAlias(d.deviceId) && ( + d.label.includes('麥克風') || + d.label.toLowerCase().includes('microphone') + ) + ) || realMicrophones.find(d => !isAlias(d.deviceId)) || realMicrophones[0]; console.log('Real microphones found:', realMicrophones.length); console.log('Selected microphone:', selectedMic); + console.log('Selected deviceId is alias:', selectedMic ? isAlias(selectedMic.deviceId) : 'N/A'); if (!selectedMic) { alert('No real microphone found. Only Stereo Mix detected. Please connect a microphone.'); return; } - // Try with the selected microphone + // Get microphone stream with proper constraints handling try { - mediaStream = await navigator.mediaDevices.getUserMedia({ - audio: { deviceId: { exact: selectedMic.deviceId } } - }); + if (isAlias(selectedMic.deviceId)) { + // For alias deviceIds (default/communications), let the system choose + console.log('Using system default (alias detected)'); + mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true }); + } else { + // For real deviceIds, try exact first, then ideal as fallback + try { + mediaStream = await navigator.mediaDevices.getUserMedia({ + audio: { deviceId: { exact: selectedMic.deviceId } } + }); + } catch (exactErr) { + console.warn('Exact device ID failed, trying ideal:', exactErr); + mediaStream = await navigator.mediaDevices.getUserMedia({ + audio: { deviceId: { ideal: selectedMic.deviceId } } + }); + } + } console.log('Successfully connected to:', selectedMic.label); - } catch (exactErr) { - console.warn('Exact device ID failed, trying preferred:', exactErr); - // Fallback: try with preferred instead of exact - mediaStream = await navigator.mediaDevices.getUserMedia({ - audio: { deviceId: selectedMic.deviceId } - }); + } catch (err) { + console.error('getUserMedia failed:', err.name, err.message); + throw err; // Let outer catch handle the error message } isRecording = true;