Add microphone noise suppression toggle

This commit is contained in:
codex
2026-06-11 01:34:07 +02:00
parent 218ff57151
commit 6764f6c4a0
3 changed files with 68 additions and 11 deletions
+30 -4
View File
@@ -27,6 +27,7 @@ const shareButton = document.querySelector("#share-button");
const announceButton = document.querySelector("#announce-button");
const selfMicVolumeInput = document.querySelector("#self-mic-volume");
const selfMicMeter = document.querySelector("#self-mic-meter");
const noiseSuppressionInput = document.querySelector("#noise-suppression");
const announcementDialog = document.querySelector("#announcement-dialog");
const announcementForm = document.querySelector("#announcement-form");
const announcementInput = document.querySelector("#announcement-input");
@@ -38,6 +39,7 @@ const clientIdStorageKey = "kkkmeet.clientId";
const cameraStorageKey = "kkkmeet.cameraDeviceId";
const micStorageKey = "kkkmeet.micDeviceId";
const micVolumeStorageKey = "kkkmeet.selfMicVolume";
const noiseSuppressionStorageKey = "kkkmeet.noiseSuppression";
const watchHeightStorageKey = "kkkmeet.watchPanelHeight";
const watchCollapsedStorageKey = "kkkmeet.watchPanelCollapsed";
const rtcConfig = {
@@ -672,7 +674,7 @@ function mediaConstraints() {
const micDeviceId = localStorage.getItem(micStorageKey);
return {
audio: micDeviceId ? { deviceId: { exact: micDeviceId } } : true,
audio: audioConstraints(micDeviceId),
video: {
width: { ideal: 1280 },
height: { ideal: 720 },
@@ -681,6 +683,17 @@ function mediaConstraints() {
};
}
function savedNoiseSuppression() {
return localStorage.getItem(noiseSuppressionStorageKey) !== "false";
}
function audioConstraints(deviceId = "") {
return {
noiseSuppression: savedNoiseSuppression(),
...(deviceId ? { deviceId: { exact: deviceId } } : {})
};
}
async function ensureLocalStream() {
if (localStream) return localStream;
@@ -819,10 +832,12 @@ function outboundAudioTrack() {
}
async function replaceLocalTrack(kind, deviceId) {
if (!deviceId) return;
if (kind !== "audio" && !deviceId) return;
if (!localStream) {
localStorage.setItem(kind === "video" ? cameraStorageKey : micStorageKey, deviceId);
if (deviceId) {
localStorage.setItem(kind === "video" ? cameraStorageKey : micStorageKey, deviceId);
}
return;
}
@@ -830,7 +845,7 @@ async function replaceLocalTrack(kind, deviceId) {
const wasEnabled = oldTrack?.enabled ?? true;
const constraints = kind === "video"
? { video: { deviceId: { exact: deviceId }, width: { ideal: 1280 }, height: { ideal: 720 } } }
: { audio: { deviceId: { exact: deviceId } } };
: { audio: audioConstraints(deviceId) };
const stream = await navigator.mediaDevices.getUserMedia(constraints);
const newTrack = stream.getTracks()[0];
newTrack.enabled = wasEnabled;
@@ -1414,6 +1429,16 @@ selfMicVolumeInput.addEventListener("input", () => {
setSelfMicVolume(selfMicVolumeInput.value);
});
noiseSuppressionInput.addEventListener("change", () => {
localStorage.setItem(noiseSuppressionStorageKey, String(noiseSuppressionInput.checked));
replaceLocalTrack("audio", micSelect.value).catch((error) => {
console.error(error);
noiseSuppressionInput.checked = !noiseSuppressionInput.checked;
localStorage.setItem(noiseSuppressionStorageKey, String(noiseSuppressionInput.checked));
setStatus("Could not change noise suppression.");
});
});
cameraSelect.addEventListener("change", () => {
replaceLocalTrack("video", cameraSelect.value).catch((error) => {
console.error(error);
@@ -1474,6 +1499,7 @@ shareButton.addEventListener("click", async () => {
selfMicVolumeInput.value = String(savedSelfMicVolume());
selfMicMeter.value = 0;
noiseSuppressionInput.checked = savedNoiseSuppression();
const savedName = localStorage.getItem(nameStorageKey);
if (savedName) {
+8 -2
View File
@@ -113,10 +113,16 @@
<button id="announce-button" type="button">Announce</button>
<div class="self-mic-control" aria-label="Local microphone volume">
<label>
<span>Mic</span>
<span>Capture volume</span>
<input id="self-mic-volume" type="range" min="0" max="200" step="1" />
</label>
<meter id="self-mic-meter" min="0" max="1" low="0.15" high="0.65" optimum="0.45"></meter>
<div class="self-mic-level">
<meter id="self-mic-meter" min="0" max="1" low="0.15" high="0.65" optimum="0.45"></meter>
<label class="noise-suppression-toggle">
<input id="noise-suppression" type="checkbox" />
<span>Noise suppression</span>
</label>
</div>
</div>
</div>
</div>
+30 -5
View File
@@ -609,10 +609,10 @@ button[aria-pressed="false"] {
.self-mic-control {
display: grid;
grid-template-columns: minmax(120px, 160px) 56px;
grid-template-columns: minmax(120px, 160px) minmax(88px, 112px);
align-items: end;
gap: 8px;
min-width: 190px;
min-width: 238px;
}
.self-mic-control label {
@@ -624,18 +624,43 @@ button[aria-pressed="false"] {
font-weight: 650;
}
.self-mic-control input {
.self-mic-control input[type="range"] {
width: 100%;
height: 18px;
padding: 0;
}
.self-mic-control meter {
width: 56px;
.self-mic-level {
display: grid;
grid-template-rows: 18px 14px;
gap: 5px;
}
.self-mic-level meter {
width: 100%;
height: 18px;
align-self: end;
}
.noise-suppression-toggle {
display: flex;
align-items: center;
gap: 5px;
min-width: 0;
color: #aeb7c3;
font-size: 10px;
font-weight: 650;
white-space: nowrap;
}
.noise-suppression-toggle input {
width: 12px;
height: 12px;
margin: 0;
padding: 0;
flex: 0 0 auto;
}
.self-preview {
position: relative;
overflow: hidden;