Files
park-desktop/backend/vendor/s2s-cloud/demo/mictest.html
T
Pine b681eac2df feat: 大屏后端(FastAPI+MQTT+sim_engine)
- REST :10085 / MQTT 控制 / SSE 回退 / AI+语音
- 数据源规划:接核心服务端 + 算力引擎真实数据
2026-08-23 22:35:05 +08:00

76 lines
3.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>麦克风诊断</title>
<style>
body { font-family: system-ui, -apple-system, "PingFang SC", sans-serif; max-width: 560px;
margin: 0 auto; padding: 16px; background: #14161a; color: #e6e8eb; }
h1 { font-size: 18px; }
button { padding: 10px 18px; border-radius: 8px; border: none; background: #1f6feb;
color: #fff; font-size: 14px; cursor: pointer; }
pre { background: #1c1f24; padding: 12px; border-radius: 8px; overflow-x: auto; font-size: 13px; }
.ok { color: #3fb950; } .bad { color: #f85149; }
.meter { height: 18px; width: 100%; background: #1c1f24; border-radius: 4px; margin: 6px 0; overflow: hidden; }
.meter > div { height: 100%; width: 0%; background: #3fb950; transition: width 60ms linear; }
</style>
</head>
<body>
<h1>🎤 麦克风诊断页(只请求麦克风)</h1>
<p>在 <b>你刚才打开主页面的那个浏览器窗口</b> 打开本页,点下面按钮。</p>
<button id="go">请求麦克风并测试</button>
<pre id="out">等待操作…</pre>
<div class="meter"><div id="bar"></div></div>
<script>
const out = document.getElementById("out");
const bar = document.getElementById("bar");
const log = (s, cls = "") => { out.innerHTML += (cls ? `<span class="${cls}">` : "") + s.replace(/</g, "&lt;") + (cls ? "</span>" : "") + "\n"; };
document.getElementById("go").onclick = async () => {
out.innerHTML = "";
log("1) 环境检查…");
log(" secureContext = " + window.isSecureContext + " (必须是 true)");
log(" navigator.mediaDevices = " + (navigator.mediaDevices ? "存在" : "不存在"));
log("2) 枚举设备…");
try {
const devs = await navigator.mediaDevices.enumerateDevices();
for (const d of devs) log(" [" + d.kind + "] " + (d.label || "(无标签=权限未授予)"));
if (!devs.some(d => d.kind === "audioinput"))
log(" ⚠️ 系统里没发现任何麦克风设备(驱动/虚拟声卡问题)", "bad");
} catch (e) { log(" 枚举失败: " + e.name + ": " + e.message, "bad"); }
log("3) getUserMedia…");
let stream;
try {
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
log(" ✅ 麦克风授权成功", "ok");
} catch (e) {
log(" ❌ " + e.name + ": " + e.message, "bad");
log(" (NotAllowedError=权限被拒;NotFoundError=无设备;NotReadableError=被其他应用占用)");
return;
}
log("4) 电平检测(说话时绿条应跳动)…");
const ctx = new AudioContext();
const src = ctx.createMediaStreamSource(stream);
const an = ctx.createAnalyser(); an.fftSize = 256;
src.connect(an);
const buf = new Uint8Array(an.frequencyBinCount);
let peak = 0;
setInterval(() => {
an.getByteTimeDomainData(buf);
let sum = 0;
for (let i = 0; i < buf.length; i++) sum += Math.abs(buf[i] - 128);
const rms = sum / buf.length;
if (rms > peak) peak = rms;
bar.style.width = Math.min(100, (rms / 40) * 100) + "%";
}, 80);
setTimeout(() => log(" 请对着麦克风说话,看上面的绿条。当前峰值=" + peak.toFixed(1) + "/127(≥10 说明有声音进)"), 2000);
};
</script>
</body>
</html>