adding chat
This commit is contained in:
192
web/chat-server.js
Normal file
192
web/chat-server.js
Normal file
@ -0,0 +1,192 @@
|
||||
// server.js
|
||||
if (require('dotenv')) {
|
||||
const envFile = process.env.NODE_ENV === 'development' ? '.env.development' : '.env';
|
||||
require('dotenv').config({ path: envFile });
|
||||
}
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const WebSocket = require('ws');
|
||||
const storage = require('node-persist');
|
||||
const request = require('request');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const app = express();
|
||||
app.use(bodyParser.json());
|
||||
|
||||
const PORT_HTTP = process.env.SERVER_PORT_HTTP || 3000;
|
||||
const PORT_WS = process.env.SERVER_PORT_WS || 8080;
|
||||
const TTS_API_URL = process.env.TTS_API_URL;
|
||||
|
||||
let language = "en";
|
||||
let storeRecordings = false;
|
||||
let queueCounter = 0;
|
||||
|
||||
const sessions = new Map();
|
||||
const users = new Map(); // Store users with their usernames and session IDs
|
||||
|
||||
storage.init().then(() => {
|
||||
storage.getItem('language').then((value) => {
|
||||
if (value !== undefined) language = value;
|
||||
else storage.setItem('language', language);
|
||||
});
|
||||
storage.getItem('storeRecordings').then((value) => {
|
||||
if (value !== undefined) storeRecordings = value;
|
||||
else storage.setItem('storeRecordings', storeRecordings);
|
||||
});
|
||||
});
|
||||
|
||||
// WebSocket Server
|
||||
const wss = new WebSocket.Server({ port: PORT_WS });
|
||||
wss.on('connection', (ws) => {
|
||||
ws.sessionId = Math.random().toString(36).substring(2);
|
||||
sessions.set(ws.sessionId, { language: 'en' });
|
||||
|
||||
ws.send(JSON.stringify({ sessionId: ws.sessionId, language, storeRecordings }));
|
||||
|
||||
ws.on('message', (message) => {
|
||||
try {
|
||||
const data = JSON.parse(message);
|
||||
|
||||
if (data.type === 'join') {
|
||||
const { username } = data;
|
||||
users.set(ws.sessionId, { username, sessionId: ws.sessionId });
|
||||
broadcastUserList();
|
||||
} else if (data.type === 'audio') {
|
||||
handleAudioData(ws, data.audio);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to parse message', err);
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
users.delete(ws.sessionId);
|
||||
sessions.delete(ws.sessionId);
|
||||
broadcastUserList();
|
||||
});
|
||||
});
|
||||
|
||||
function handleAudioData(ws, data) {
|
||||
const sessionData = sessions.get(ws.sessionId);
|
||||
let language = sessionData.language || 'en';
|
||||
let task = sessionData.task || 'transcribe';
|
||||
|
||||
const formData = {
|
||||
task,
|
||||
language,
|
||||
vad_filter: 'true',
|
||||
output: 'json',
|
||||
audio_file: {
|
||||
value: data,
|
||||
options: { filename: 'audio.ogg', contentType: 'audio/ogg' }
|
||||
}
|
||||
};
|
||||
|
||||
if (language === 'auto' || language === '') {
|
||||
detectLanguage(ws, formData);
|
||||
} else {
|
||||
transcribeAudio(ws, formData, sessionData);
|
||||
}
|
||||
}
|
||||
|
||||
function detectLanguage(ws, formData) {
|
||||
request.post({ url: TTS_API_URL.replace('/asr', '/detect-language'), formData }, (err, httpResponse, body) => {
|
||||
if (err) return console.error('Language detection failed:', err);
|
||||
const result = JSON.parse(body);
|
||||
if (result && result.language_code) {
|
||||
const language = result.language_code;
|
||||
const sessionData = sessions.get(ws.sessionId);
|
||||
sessionData.language = language;
|
||||
ws.send(JSON.stringify({ languageDetected: result.detected_language }));
|
||||
transcribeAudio(ws, formData, sessionData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function transcribeAudio(ws, formData, sessionData) {
|
||||
const start = new Date().getTime();
|
||||
queueCounter++;
|
||||
|
||||
request.post({ url: TTS_API_URL, formData }, (err, httpResponse, body) => {
|
||||
queueCounter--;
|
||||
if (err) return console.error('Transcription failed:', err);
|
||||
|
||||
const duration = new Date().getTime() - start;
|
||||
ws.send(JSON.stringify({
|
||||
queueCounter,
|
||||
duration,
|
||||
language: sessionData.language,
|
||||
text: body
|
||||
}));
|
||||
});
|
||||
|
||||
if (storeRecordings) {
|
||||
const timestamp = Date.now();
|
||||
fs.mkdir('rec', { recursive: true }, (err) => {
|
||||
if (err) throw err;
|
||||
});
|
||||
fs.writeFile(`rec/audio${timestamp}.ogg`, formData.audio_file.value, (err) => {
|
||||
if (err) console.log(err);
|
||||
else console.log('Audio data saved to rec/audio' + timestamp + '.ogg');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function broadcastUserList() {
|
||||
const userList = Array.from(users.values()).map(user => ({ username: user.username, sessionId: user.sessionId }));
|
||||
wss.clients.forEach(client => {
|
||||
if (client.readyState === WebSocket.OPEN) {
|
||||
client.send(JSON.stringify({ type: 'userList', users: userList }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// HTTP Server
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'chat-client.html'));
|
||||
});
|
||||
|
||||
app.post('/log', (req, res) => {
|
||||
console.log(`[LOG ${new Date().toISOString()}] ${req.body.message}`);
|
||||
res.status(200).send('OK');
|
||||
});
|
||||
|
||||
app.get('/wsurl', (req, res) => {
|
||||
res.status(200).send(process.env.WS_URL);
|
||||
});
|
||||
|
||||
app.get('/settings', (req, res) => {
|
||||
if (req.query.language) {
|
||||
language = req.query.language;
|
||||
storage.setItem('language', language);
|
||||
}
|
||||
if (req.query.storeRecordings) {
|
||||
storeRecordings = req.query.storeRecordings;
|
||||
storage.setItem('storeRecordings', storeRecordings);
|
||||
}
|
||||
res.status(200).send({ language, storeRecordings });
|
||||
});
|
||||
|
||||
app.post('/settings', (req, res) => {
|
||||
const { sessionId, language, storeRecordings, task } = req.body;
|
||||
const sessionData = sessions.get(sessionId);
|
||||
if (language) sessionData.language = language;
|
||||
if (storeRecordings) sessionData.storeRecordings = storeRecordings;
|
||||
if (task) sessionData.task = task;
|
||||
res.status(200).send('OK');
|
||||
});
|
||||
|
||||
app.post('/upload', (req, res) => {
|
||||
const timestamp = Date.now();
|
||||
fs.mkdir('rec', { recursive: true }, (err) => {
|
||||
if (err) return res.status(500).send('ERROR');
|
||||
const file = fs.createWriteStream(`rec/audio_slice_${timestamp}.ogg`);
|
||||
req.pipe(file);
|
||||
file.on('finish', () => res.status(200).send('OK'));
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(PORT_HTTP, () => {
|
||||
console.log(`Server listening on port ${PORT_HTTP}`);
|
||||
});
|
Reference in New Issue
Block a user