Files
Pine 7f25c8f6bb refactor(backend): 启动环境初始化与资源项目化(零跨项目依赖)
- main.py:uv run main.py 一键启动——读取 backend/.env、TORCH_HOME/NLTK_DATA 指向项目内缓存、certifi SSL + NO_PROXY 网络直连、默认开启 s2s,启动横幅
- vendor/:补丁后 s2s 云化栈移入项目(backend/vendor/s2s-cloud),pyproject sources 改相对路径
- .gitignore:忽略 .torch-cache / nltk_data 缓存
- AGENTS.md:进程管理铁律(AI 不启动/重启服务,由用户操作)
2026-08-18 01:37:57 +08:00

56 lines
1.9 KiB
HTML

<!doctype html>
<html lang="zh">
<head><meta charset="utf-8"><title>worklet 输出测试</title></head>
<body>
<pre id="out">running...</pre>
<script>
const out = document.getElementById("out");
function log(s) { out.textContent += s + "\n"; }
(async () => {
try {
const ctx = new AudioContext();
if (ctx.state === "suspended") await ctx.resume();
log("ctx state: " + ctx.state);
await ctx.audioWorklet.addModule("worklets/audio-playback.js?v=t3");
const node = new AudioWorkletNode(ctx, "audio-playback", {
numberOfInputs: 0, numberOfOutputs: 1, outputChannelCount: [1],
});
const cap = ctx.createAnalyser();
cap.fftSize = 2048;
node.connect(cap);
cap.connect(ctx.destination); // keep the graph running
const sr = 16000, n = sr; // 1s @16k
const samples = new Float32Array(n);
for (let i = 0; i < n; i++) samples[i] = 0.5 * Math.sin(2 * Math.PI * 440 * i / sr);
const chunk = 1280;
let pushed = 0;
for (let i = 0; i < n; i += chunk) {
node.port.postMessage({ kind: "audio", samples: samples.slice(i, i + chunk) });
pushed++;
}
log("pushed chunks: " + pushed);
await new Promise(r => setTimeout(r, 2500));
const buf = new Uint8Array(cap.frequencyBinCount);
cap.getByteTimeDomainData(buf);
let sum = 0;
for (let i = 0; i < buf.length; i++) sum += Math.abs(buf[i] - 128);
const rms = sum / buf.length; // 0..127 scale
log("output RMS = " + rms.toFixed(2) + (rms > 5 ? " ✅ 有声音输出" : " ❌ 输出静音"));
// 也测一下统计回传
const stats = await new Promise(res => {
const timer = setTimeout(() => res("no-stats"), 3000);
node.port.onmessage = e => { clearTimeout(timer); res(JSON.stringify(e.data)); };
node.port.postMessage({ kind: "config", inputRate: 16000, muted: false });
});
log("stats from worklet: " + stats);
} catch (e) {
log("ERROR: " + e.message);
}
})();
</script>
</body>
</html>