LibreChat/api/server/services/WebSocket/WebSocketServer.js

70 lines
2.1 KiB
JavaScript

const { WebSocketServer } = require('ws');
const fs = require('fs');
const path = require('path');
module.exports.WebSocketService = class {
constructor(server) {
this.wss = new WebSocketServer({ server, path: '/ws' });
this.log('Server initialized');
this.clientAudioBuffers = new Map();
this.setupHandlers();
}
log(msg) {
console.log(`[WSS ${new Date().toISOString()}] ${msg}`);
}
setupHandlers() {
this.wss.on('connection', (ws) => {
const clientId = Date.now().toString();
this.clientAudioBuffers.set(clientId, []);
this.log(`Client connected: ${clientId}`);
ws.on('message', async (raw) => {
let message;
try {
message = JSON.parse(raw);
} catch {
return;
}
if (message.type === 'audio-chunk') {
if (!this.clientAudioBuffers.has(clientId)) {
this.clientAudioBuffers.set(clientId, []);
}
this.clientAudioBuffers.get(clientId).push(message.data);
}
if (message.type === 'request-response') {
const filePath = path.join(__dirname, './assets/response.mp3');
const audioFile = fs.readFileSync(filePath);
ws.send(JSON.stringify({ type: 'audio-response', data: audioFile.toString('base64') }));
}
if (message.type === 'call-ended') {
const allChunks = this.clientAudioBuffers.get(clientId);
this.writeAudioFile(clientId, allChunks);
this.clientAudioBuffers.delete(clientId);
}
});
ws.on('close', () => {
this.log(`Client disconnected: ${clientId}`);
this.clientAudioBuffers.delete(clientId);
});
});
}
writeAudioFile(clientId, base64Chunks) {
if (!base64Chunks || base64Chunks.length === 0) {
return;
}
const filePath = path.join(__dirname, `recorded_${clientId}.webm`);
const buffer = Buffer.concat(
base64Chunks.map((chunk) => Buffer.from(chunk.split(',')[1], 'base64')),
);
fs.writeFileSync(filePath, buffer);
this.log(`Saved audio to ${filePath}`);
}
};