const { RTCAudioSource } = require('wrtc').nonstandard; const ffmpeg = require('fluent-ffmpeg') class AudioSourceService extends RTCAudioSource { constructor() { super(); this.command = null // 存储音频源 this.cache = Buffer.alloc(0) } // 创建通道 createTrack() { const track = super.createTrack() return track } // 获取音频源 start() { if (this.command !== null) this.stop() this.command = ffmpeg("plughw:1,0") .inputFormat("alsa") .audioChannels(1) .audioFrequency(48000) .audioCodec("pcm_s16le") .outputFormat("s16le") .on("start", () => { console.log("Audio start !"); }) .on("error", function (err) { console.log('Audio processing an error occurred: ' + err.message); // 退出进程 process.exit(1) }) this.ffstream = this.command.pipe(); this.ffstream.on("data", (buffer) => { // console.log("Audio buffer length", buffer.length); this.cache = Buffer.concat([this.cache, buffer]); }); const processData = () => { while (this.cache.length > 960) { const buffer = this.cache.slice(0, 960); this.cache = this.cache.slice(960); const samples = new Int16Array(new Uint8Array(buffer).buffer); this.onData({ bitsPerSample: 16, sampleRate: 48000, channelCount: 1, numberOfFrames: samples.length, type: "data", samples, }); } if (this.command !== null) { setTimeout(() => processData(), 10); } }; processData(); } // 停止获取 stop() { console.log("audio source stop"); if (this.command != null) { this.command.kill("SIGHUP") this.command = null } } } module.exports = AudioSourceService