Complete Refactor

This commit is contained in:
2025-03-30 01:28:07 -04:00
parent 158afc78c7
commit 46be33b10a
28 changed files with 723 additions and 3081 deletions

View File

@@ -0,0 +1,105 @@
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f4;
color: #333;
margin: 0;
padding: 0;
}
header {
background: #4c84ff;
color: #fff;
padding: 10px 0;
text-align: center;
}
h1 {
margin: 0;
font-size: 2.5rem;
}
.container {
width: 80%;
margin: auto;
overflow: hidden;
}
.conversation {
background: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
max-height: 400px;
overflow-y: auto;
}
.message {
padding: 10px;
margin: 10px 0;
border-radius: 5px;
}
.user {
background: #e3f2fd;
text-align: right;
}
.ai {
background: #f1f1f1;
text-align: left;
}
.controls {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
button {
padding: 10px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #3367d6;
color: #fff;
}
.visualizer-container {
height: 150px;
background: #000;
border-radius: 5px;
margin-top: 20px;
}
.visualizer-label {
color: rgba(255, 255, 255, 0.7);
text-align: center;
padding: 10px;
}
.status-indicator {
display: flex;
align-items: center;
margin-top: 10px;
}
.status-dot {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: #ccc;
margin-right: 10px;
}
.status-dot.active {
background-color: #4CAF50;
}
.status-text {
font-size: 0.9em;
color: #666;
}

31
Backend/static/index.html Normal file
View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSM Conversation Bot</title>
<link rel="stylesheet" href="css/styles.css">
<script src="https://cdn.socket.io/4.6.0/socket.io.min.js"></script>
<script src="js/client.js" defer></script>
</head>
<body>
<header>
<h1>CSM Conversation Bot</h1>
<p>Talk to the AI and get responses in real-time!</p>
</header>
<main>
<div id="conversation" class="conversation"></div>
<div class="controls">
<button id="startButton">Start Conversation</button>
<button id="stopButton">Stop Conversation</button>
</div>
<div class="status-indicator">
<div id="statusDot" class="status-dot"></div>
<div id="statusText">Disconnected</div>
</div>
</main>
<footer>
<p>Powered by CSM and Llama 3.2</p>
</footer>
</body>
</html>

131
Backend/static/js/client.js Normal file
View File

@@ -0,0 +1,131 @@
// This file contains the client-side JavaScript code that handles audio streaming and communication with the server.
const SERVER_URL = window.location.hostname === 'localhost' ?
'http://localhost:5000' : window.location.origin;
const elements = {
conversation: document.getElementById('conversation'),
streamButton: document.getElementById('streamButton'),
clearButton: document.getElementById('clearButton'),
speakerSelection: document.getElementById('speakerSelect'),
statusDot: document.getElementById('statusDot'),
statusText: document.getElementById('statusText'),
};
const state = {
socket: null,
isStreaming: false,
currentSpeaker: 0,
};
// Initialize the application
function initializeApp() {
setupSocketConnection();
setupEventListeners();
}
// Setup Socket.IO connection
function setupSocketConnection() {
state.socket = io(SERVER_URL);
state.socket.on('connect', () => {
updateConnectionStatus(true);
});
state.socket.on('disconnect', () => {
updateConnectionStatus(false);
});
state.socket.on('audio_response', handleAudioResponse);
state.socket.on('transcription', handleTranscription);
}
// Setup event listeners
function setupEventListeners() {
elements.streamButton.addEventListener('click', toggleStreaming);
elements.clearButton.addEventListener('click', clearConversation);
elements.speakerSelection.addEventListener('change', (event) => {
state.currentSpeaker = event.target.value;
});
}
// Update connection status UI
function updateConnectionStatus(isConnected) {
elements.statusDot.classList.toggle('active', isConnected);
elements.statusText.textContent = isConnected ? 'Connected' : 'Disconnected';
}
// Toggle streaming state
function toggleStreaming() {
if (state.isStreaming) {
stopStreaming();
} else {
startStreaming();
}
}
// Start streaming audio to the server
function startStreaming() {
if (state.isStreaming) return;
navigator.mediaDevices.getUserMedia({ audio: true })
.then(stream => {
const mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start();
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
sendAudioChunk(event.data);
}
};
mediaRecorder.onstop = () => {
state.isStreaming = false;
elements.streamButton.innerHTML = 'Start Conversation';
};
state.isStreaming = true;
elements.streamButton.innerHTML = 'Stop Conversation';
})
.catch(err => {
console.error('Error accessing microphone:', err);
});
}
// Stop streaming audio
function stopStreaming() {
if (!state.isStreaming) return;
// Logic to stop the media recorder would go here
}
// Send audio chunk to server
function sendAudioChunk(audioData) {
const reader = new FileReader();
reader.onloadend = () => {
const arrayBuffer = reader.result;
state.socket.emit('audio_chunk', { audio: arrayBuffer, speaker: state.currentSpeaker });
};
reader.readAsArrayBuffer(audioData);
}
// Handle audio response from server
function handleAudioResponse(data) {
const audioElement = new Audio(URL.createObjectURL(new Blob([data.audio])));
audioElement.play();
}
// Handle transcription response from server
function handleTranscription(data) {
const messageElement = document.createElement('div');
messageElement.textContent = `AI: ${data.transcription}`;
elements.conversation.appendChild(messageElement);
}
// Clear conversation history
function clearConversation() {
elements.conversation.innerHTML = '';
}
// Initialize the application when DOM is fully loaded
document.addEventListener('DOMContentLoaded', initializeApp);