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;