MCPcopy Create free account
hub / github.com/FunAudioLLM/Fun-Audio-Chat / MoshiProcessor

Class MoshiProcessor

web_demo/client/src/audio-processor.ts:20–238  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

18}
19
20class MoshiProcessor extends AudioWorkletProcessor {
21 constructor() {
22 super();
23 console.log("Audio Queue Processor initialized", currentFrame, sampleRate);
24
25 // ============ 缓冲区配置 ============
26 const frameSize = asSamples(40); // 每帧 80ms
27
28 // 初始缓冲:收集多少数据后开始播放(越大越平滑,但延迟越高)
29 // 建议 240-320ms (3-4帧),可以容忍 2-3 个帧的网络抖动
30 this.initialBufferSamples = 12 * frameSize; // 240ms
31
32 // 启动后的额外等待时间
33 this.startupDelaySamples = asSamples(40); // 40ms
34
35 // Buffer underrun 后的最小恢复缓冲
36 this.minRecoveryBuffer = asSamples(40); // 80ms
37
38 // 状态初始化
39 this.initState();
40
41 // 消息处理
42 this.port.onmessage = (event) => {
43 if (event.data.type === "reset") {
44 console.log("[AudioProcessor] Reset state");
45 this.initState();
46 return;
47 }
48
49 // 将音频帧加入队列
50 const frame = event.data.frame;
51 this.audioQueue.push(frame);
52 this.totalQueuedSamples += frame.length;
53
54 // 检查是否可以开始播放
55 if (!this.isPlaying && this.totalQueuedSamples >= this.initialBufferSamples) {
56 this.startPlayback();
57 }
58
59 // 日志(前20个包)
60 if (this.packetCount < 20) {
61 console.log(
62 this.timestamp(),
63 `[Queue] Packet #${this.packetCount++}`,
64 `queued: ${asMs(this.totalQueuedSamples)}ms`,
65 `frame: ${asMs(frame.length)}ms`
66 );
67 }
68
69 // 发送状态给主线程
70 this.port.postMessage({
71 totalAudioPlayed: this.totalAudioPlayed,
72 actualAudioPlayed: this.actualAudioPlayed,
73 delay: event.data.micDuration - this.playbackPosition,
74 minDelay: this.minDelay,
75 maxDelay: this.maxDelay,
76 queueSize: this.totalQueuedSamples,
77 });

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected