const WebSocket = require('ws'); const { spawn } = require('child_process'); const path = require('path'); const PORT = 8000; const AAC_FILE_PATH = path.join(__dirname, 'audio.aac'); // 创建 WebSocket 服务器 const wss = new WebSocket.Server({ port: PORT }, () => { console.log(`WebSocket server started on port ${PORT}`); }); function sendAudioStream(ws, filePath) { const ffmpeg = spawn('ffmpeg', [ '-i', filePath, // 输入文件 '-f', 'adts', // 输出格式 '-acodec', 'copy', // 复制编码 '-vn', // 不输出视频 '-' // 输出到标准输出 ]); // const sampleRate = 44100; // 采样率 const sampleRate = 16000; // 采样率 // const frameDuration = frameSize / sampleRate; // 每帧的持续时间,单位为毫秒 const frameSize = 4096; //frameSize fixed 1024=>4096 // AAC 帧大小 let buffer = Buffer.alloc(0); let frameTime = 0; ffmpeg.stdout.on('data', (chunk) => { buffer = Buffer.concat([buffer, chunk]); while (buffer.length >= frameSize) { const frame = buffer.slice(0, frameSize); buffer = buffer.slice(frameSize); // setTimeout(() => { // if (ws.readyState === WebSocket.OPEN) { ws.send(frame); // } // }, frameTime); // frameTime += frameDuration; } }); ffmpeg.stderr.on('data', (data) => { console.error(`ffmpeg error: ${data}`); }); ffmpeg.on('close', (code) => { console.log(`ffmpeg process exited with code ${code}`); if (ws.readyState === WebSocket.OPEN) { sendAudioStream(ws, filePath); // 重启 ffmpeg 以实现循环推流 } }); ws.on('close', () => { ffmpeg.kill(); }); } wss.on('connection', (ws) => { console.log('Client connected'); sendAudioStream(ws, AAC_FILE_PATH); ws.on('close', () => { console.log('Client disconnected'); }); }); wss.on('error', (err) => { console.error('WebSocket server error:', err); });