Files
DPM/backend/vendor/s2s-cloud/demo/mictest.html
T

76 lines
3.2 KiB
HTML
Raw Normal View History

<!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>