@p0llen/speaker-detector-client
Version:
React components and hooks for live speaker detection and mic analysis.
69 lines (68 loc) • 2.82 kB
JavaScript
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
/**
* useMicCheck hook (cleaned version)
* - Enumerates available input devices
* - Manages selection with localStorage persistence
* - Does NOT access or analyze microphone streams
*/
import { useCallback, useEffect, useRef, useState } from "react";
var STORAGE_KEY = "mic-test-device-id";
export default function useMicCheck() {
var [micStatus, setMicStatus] = useState("pending");
var [devices, setDevices] = useState([]);
var [selectedDeviceId, _setSelectedDeviceId] = useState(() => localStorage.getItem(STORAGE_KEY) || "");
var lastIdsRef = useRef([]);
var setSelectedDeviceId = useCallback(id => {
_setSelectedDeviceId(id);
if (id) localStorage.setItem(STORAGE_KEY, id);else localStorage.removeItem(STORAGE_KEY);
}, []);
var refreshDeviceList = useCallback(/*#__PURE__*/_asyncToGenerator(function* () {
try {
var all = yield navigator.mediaDevices.enumerateDevices();
// Keep all audioinputs, including 'default'/'communications'. Some browsers
// only expose those until after getUserMedia permission is granted.
var audioInputs = all.filter(d => d.kind === "audioinput");
setDevices(audioInputs);
var ids = audioInputs.map(d => d.deviceId);
var before = new Set(lastIdsRef.current);
var newlyAdded = ids.filter(id => !before.has(id));
lastIdsRef.current = ids;
if (!selectedDeviceId && ids.length > 0) {
setSelectedDeviceId(ids[0]);
} else if (newlyAdded.length > 0) {
setSelectedDeviceId(newlyAdded[0]);
} else if (selectedDeviceId && !ids.includes(selectedDeviceId)) {
setSelectedDeviceId(ids[0] || "");
}
setMicStatus(audioInputs.length > 0 ? "ok" : "none");
} catch (err) {
setDevices([]);
setMicStatus("error");
}
}), [selectedDeviceId, setSelectedDeviceId]);
useEffect(() => {
var _navigator$mediaDevic;
refreshDeviceList();
var onChange = () => {
refreshDeviceList();
};
(_navigator$mediaDevic = navigator.mediaDevices) === null || _navigator$mediaDevic === void 0 || _navigator$mediaDevic.addEventListener("devicechange", onChange);
return () => {
var _navigator$mediaDevic2;
(_navigator$mediaDevic2 = navigator.mediaDevices) === null || _navigator$mediaDevic2 === void 0 || _navigator$mediaDevic2.removeEventListener("devicechange", onChange);
};
}, [refreshDeviceList]);
return {
micStatus,
micStatusLabel: {
pending: "⏳ Checking mic devices...",
ok: "🎤 Mic devices found",
none: "❌ No microphones detected",
error: "⚠️ Failed to access microphone"
}[micStatus] || "❔",
devices,
selectedDeviceId,
setSelectedDeviceId,
refreshDeviceList
};
}