From f017cde9df3e35f5305e9867d00a1a93a2c7d944 Mon Sep 17 00:00:00 2001 From: crosswk Date: Wed, 29 Jul 2026 20:54:46 +0800 Subject: [PATCH] =?UTF-8?q?=E9=BA=A6=E5=85=8B=E9=A3=8E=E5=88=97=E8=A1=A8?= =?UTF-8?q?=EF=BC=9A=E5=A7=8B=E7=BB=88=E5=9C=A8=E6=B4=BB=E8=B7=83=E9=9F=B3?= =?UTF-8?q?=E9=A2=91=E6=B5=81=E4=B8=8B=E6=9E=9A=E4=B8=BE=EF=BC=8C=E9=80=82?= =?UTF-8?q?=E9=85=8D=E6=96=B0=E7=89=88WebView2=E7=9A=84=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=90=8D=E9=9A=90=E8=97=8F=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/services/audio.ts | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/client/src/services/audio.ts b/client/src/services/audio.ts index 80b3979..6550a19 100644 --- a/client/src/services/audio.ts +++ b/client/src/services/audio.ts @@ -134,27 +134,19 @@ registerProcessor('pcm-processor', PCMProcessor); export async function listMicrophones(): Promise { const audioInputs = (list: MediaDeviceInfo[]) => list.filter((d) => d.kind === 'audioinput') - let devices = audioInputs(await navigator.mediaDevices.enumerateDevices()) - - // 未授予麦克风权限时,enumerateDevices() 只会返回一个无名字的通用设备。 - // 先申请一次权限(用完立刻关闭),再重新枚举,才能拿到系统里所有麦克风及其名称。 - const needPermission = devices.length === 0 || devices.every((d) => !d.label) - if (needPermission) { - let stream: MediaStream | null = null - try { - stream = await navigator.mediaDevices.getUserMedia({ audio: true }) - // 关键:必须在音频流仍活跃时枚举,才能拿到设备名字。 - // WebView2 的 --auto-accept-camera-and-microphone-capture 下权限不持久, - // 流一旦停止,enumerateDevices() 的 label 又会变空。 - devices = audioInputs(await navigator.mediaDevices.enumerateDevices()) - } catch { - // 权限被拒或设备不存在:保留已有结果(可能只有通用项) - } finally { - if (stream) stream.getTracks().forEach((t) => t.stop()) - } + // 新版 WebView2 / Chromium 收紧了设备枚举:只有在麦克风流“活跃”时, + // enumerateDevices() 才会返回设备的真实名字(label),否则只有一个无名通用项。 + // 因此这里始终先开一个临时音频流,趁流活跃时枚举,拿到完整列表后立刻关闭。 + let stream: MediaStream | null = null + try { + stream = await navigator.mediaDevices.getUserMedia({ audio: true }) + return audioInputs(await navigator.mediaDevices.enumerateDevices()) + } catch { + // 拿不到权限或没有可用麦克风:退回普通枚举(可能只有通用项) + return audioInputs(await navigator.mediaDevices.enumerateDevices()) + } finally { + if (stream) stream.getTracks().forEach((t) => t.stop()) } - - return devices } function createAudioContext() {