Bläddra i källkod

fix(nls): 加音轨状态日志(定位「采集电平恒为 0」)

用户回报的电平日志:峰值=0.0000 RMS=0.0000(连续 20 秒全 0)——
说明 getUserMedia 给了流、回调也在触发,但**流里的采样全是 0**,即典型"设备/系统级静音"
(系统静音键、Windows 麦克风隐私开关、选错输入设备、被别的程序独占),
而不是协议或组帧问题(组帧路径已在 verify-nls-browser-path.mjs 里证明可用)。

新增诊断:采集开始时打**音轨自身状态**
  [nls] 音轨:label=… muted=… enabled=… state=… deviceId=… 声道=…
并在 1.5s 后、以及 mute/unmute 事件时各打一条 —— muted=true 就是"被静音"的直接证据。

验证:vue-tsc 无错、build 通过、内联脚本 6/6、NLS 44/44、浏览器路径 4/4。

Co-Authored-By: Claude Code <noreply@anthropic.com>
gongtianxiao 1 månad sedan
förälder
incheckning
1700080a69
1 ändrade filer med 20 tillägg och 0 borttagningar
  1. 20 0
      src/asr/nls.ts

+ 20 - 0
src/asr/nls.ts

@@ -114,6 +114,26 @@ export default class NlsAsr extends BaseEvent {
       `[nls] 开始采集:AudioContext=${this.audioContext.state} 采样率=${sampleRate}Hz ` +
         `processor 缓冲=${this.processor.bufferSize}`
     );
+    // 音轨自己的状态 —— 分辨「系统/硬件把麦克风静音了」与「接线有问题」的关键证据:
+    //   muted=true 表示轨道被静音(系统静音键、隐私开关、别的程序独占…),
+    //   这时 getUserMedia 照样成功、回调照样触发,但采样全是 0。
+    const track = this.stream.getAudioTracks?.()[0];
+    if (track) {
+      const settings = typeof track.getSettings === "function" ? track.getSettings() : {};
+      console.log(
+        `[nls] 音轨:label=${JSON.stringify(track.label)} muted=${track.muted} enabled=${track.enabled} ` +
+          `state=${track.readyState} deviceId=${String(settings.deviceId || "").slice(0, 8)}… ` +
+          `声道=${settings.channelCount ?? "?"}`
+      );
+      const reportTrackState = (tag: string) => {
+        console.log(`[nls] ${tag}音轨状态:muted=${track.muted} enabled=${track.enabled} state=${track.readyState}`);
+      };
+      window.setTimeout(() => reportTrackState("1.5s 后"), 1500);
+      track.addEventListener?.("mute", () => reportTrackState("被静音时(mute 事件)"));
+      track.addEventListener?.("unmute", () => reportTrackState("解除静音时(unmute 事件)"));
+    } else {
+      console.warn("[nls] ⚠️ 流里没有音轨(getUserMedia 拿到的不是音频流?)");
+    }
     this.processor.onaudioprocess = (event: AudioProcessingEvent) => {
       if (!this.processing || !this.stream || !this.stream.active) return;
       const channel = event.inputBuffer.getChannelData(0);