UNPKG

@p0llen/speaker-detector-client

Version:

React client for interfacing with the [speaker-detector](https://pypi.org/project/speaker-detector) Python backend. Supports real-time speaker identification, meeting transcription, and speaker enrollment.

116 lines (113 loc) 3.88 kB
import React from "react"; import useMicCheck from "../hooks/useMicCheck"; /** * MicStatus centralizes ALL status messaging: * - microphone availability/health (from useMicCheck) * - detection engine state (passed in as props from SpeakerStatus) * * SpeakerStatus must *not* render any status text. * It should pass raw engine state into this component. */ var MicStatus = _ref => { var { backendOnline, // boolean | null status, // engine status string from useSpeakerDetection listeningMode, // "off" | "single" | "multi" isSpeaking, // boolean title = "🎤 Microphone & Detection Status" } = _ref; var { micStatus, // "pending" | "ok" | "silent" | "none" | "blocked" | "error" micStatusLabel, // human label derived from micStatus devices, selectedDeviceId, setSelectedDeviceId, checkMic } = useMicCheck(); var combinedStatusLabel = () => { // 1) Hard stop if backend is down if (backendOnline === false) return "🔌 Backend unreachable — detection unavailable"; // 2) Mic problems take precedence (single source of truth for mic UX) switch (micStatus) { case "blocked": return "🚫 Mic access blocked by browser — allow microphone to continue"; case "none": return "❌ No microphone detected (unplugged or missing device)"; case "silent": return "⚠️ Mic detected but no signal (muted/virtual/very low input)"; case "pending": return "⏳ Checking microphone…"; case "error": return "⚠️ Microphone check failed — retry or choose another input"; // "ok" falls through to engine checks below default: break; } // 3) Engine state (only shown when mic is "ok") var s = (status || "").trim(); if (listeningMode === "off" || s === "disabled") { return "🔇 Detection disabled"; } if (s === "pending") { return "⏳ Engine awaiting detection data…"; } if (s === "listening") { return isSpeaking ? "🎙 Voice detected" : "🕵️ Engine listening…"; } if (backendOnline === null) { return "🔎 Checking backend…"; } return "ℹ️ Ready"; }; return /*#__PURE__*/React.createElement("div", { className: "mic-status-panel" }, /*#__PURE__*/React.createElement("h4", { className: "speaker-heading" }, title), /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement("strong", null, "Status:"), " ", combinedStatusLabel(), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("span", { style: { fontSize: 12, color: "#9aa" } }, "Mic: ", micStatusLabel)), /*#__PURE__*/React.createElement("div", { style: { marginTop: 8 } }, /*#__PURE__*/React.createElement("label", null, "Input device:\xA0", /*#__PURE__*/React.createElement("select", { value: selectedDeviceId || "", onChange: e => { var id = e.target.value; setSelectedDeviceId(id); setTimeout(() => checkMic(id), 0); }, style: { background: "#222", color: "#fff", borderRadius: 4, padding: 4 } }, devices.length === 0 ? /*#__PURE__*/React.createElement("option", { value: "" }, "(no audio inputs)") : devices.map(d => /*#__PURE__*/React.createElement("option", { key: d.deviceId, value: d.deviceId }, d.label || "Device ".concat(d.deviceId.slice(0, 6)))))), /*#__PURE__*/React.createElement("button", { onClick: () => checkMic(selectedDeviceId || undefined), style: { marginLeft: 8, background: "#2a2a2a", color: "#fff", border: "1px solid #555", borderRadius: 6, padding: "4px 8px", cursor: "pointer" }, title: "Re-run microphone check" }, "\uD83D\uDD01 Recheck"))); }; export default MicStatus;