71 lines
1.9 KiB
JavaScript
71 lines
1.9 KiB
JavaScript
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);
|
|
});
|