Add device controls to the simple chatbot example

This commit is contained in:
mattie ruth backman
2025-07-03 11:12:10 -07:00
committed by Mattie Ruth
parent e04e876f44
commit faf4026cf4
3 changed files with 81 additions and 4 deletions

View File

@@ -27,6 +27,13 @@
</div> </div>
</div> </div>
<div class="device-bar">
<div class="device-controls">
<select id="device-selector"></select>
<button id="mic-toggle-btn">Mute Mic</button>
</div>
</div>
<div class="debug-panel"> <div class="debug-panel">
<h3>Debug Info</h3> <h3>Debug Info</h3>
<div id="debug-log"></div> <div id="debug-log"></div>

View File

@@ -28,7 +28,6 @@ class ChatbotClient {
// Initialize client state // Initialize client state
this.rtviClient = null; this.rtviClient = null;
this.setupDOMElements(); this.setupDOMElements();
this.setupEventListeners();
this.initializeClientAndTransport(); this.initializeClientAndTransport();
} }
@@ -42,6 +41,7 @@ class ChatbotClient {
this.statusSpan = document.getElementById('connection-status'); this.statusSpan = document.getElementById('connection-status');
this.debugLog = document.getElementById('debug-log'); this.debugLog = document.getElementById('debug-log');
this.botVideoContainer = document.getElementById('bot-video-container'); this.botVideoContainer = document.getElementById('bot-video-container');
this.deviceSelector = document.getElementById('device-selector');
// Create an audio element for bot's voice output // Create an audio element for bot's voice output
this.botAudio = document.createElement('audio'); this.botAudio = document.createElement('audio');
@@ -56,12 +56,37 @@ class ChatbotClient {
setupEventListeners() { setupEventListeners() {
this.connectBtn.addEventListener('click', () => this.connect()); this.connectBtn.addEventListener('click', () => this.connect());
this.disconnectBtn.addEventListener('click', () => this.disconnect()); this.disconnectBtn.addEventListener('click', () => this.disconnect());
// Populate device selector
this.rtviClient.getAllMics().then((mics) => {
console.log('Available mics:', mics);
mics.forEach((device) => {
const option = document.createElement('option');
option.value = device.deviceId;
option.textContent = device.label || `Microphone ${device.deviceId}`;
this.deviceSelector.appendChild(option);
});
});
this.deviceSelector.addEventListener('change', (event) => {
const selectedDeviceId = event.target.value;
console.log('Selected device ID:', selectedDeviceId);
this.rtviClient.updateMic(selectedDeviceId);
});
// Handle mic mute/unmute toggle
const micToggleBtn = document.getElementById('mic-toggle-btn');
micToggleBtn.addEventListener('click', () => {
let micEnabled = this.rtviClient.isMicEnabled;
micToggleBtn.textContent = micEnabled ? 'Unmute Mic' : 'Mute Mic';
this.rtviClient.enableMic(!micEnabled);
});
} }
/** /**
* Set up the RTVI client and Daily transport * Set up the RTVI client and Daily transport
*/ */
initializeClientAndTransport() { async initializeClientAndTransport() {
// Initialize the RTVI client with a DailyTransport and our configuration // Initialize the RTVI client with a DailyTransport and our configuration
this.rtviClient = new RTVIClient({ this.rtviClient = new RTVIClient({
transport: new DailyTransport(), transport: new DailyTransport(),
@@ -121,14 +146,22 @@ class ChatbotClient {
onMessageError: (error) => { onMessageError: (error) => {
console.log('Message error:', error); console.log('Message error:', error);
}, },
onMicUpdated: (data) => {
console.log('Mic updated:', data);
this.deviceSelector.value = data.deviceId;
},
onError: (error) => { onError: (error) => {
console.log('Error:', JSON.stringify(error)); console.log('Error:', JSON.stringify(error));
}, },
}, },
}); });
window.client = this; // Expose client globally for debugging
// Set up listeners for media track events // Set up listeners for media track events
this.setupTrackListeners(); this.setupTrackListeners();
await this.rtviClient.initDevices();
this.setupEventListeners();
} }
/** /**

View File

@@ -10,7 +10,8 @@ body {
margin: 0 auto; margin: 0 auto;
} }
.status-bar { .status-bar,
.device-bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@@ -20,7 +21,19 @@ body {
margin-bottom: 20px; margin-bottom: 20px;
} }
.controls button { .controls,
.device-controls {
display: flex;
align-items: center;
gap: 10px; /* Adds spacing between elements */
}
.device-controls {
margin-left: auto;
}
.controls button,
.device-controls button {
padding: 8px 16px; padding: 8px 16px;
margin-left: 10px; margin-left: 10px;
border: none; border: none;
@@ -28,6 +41,27 @@ body {
cursor: pointer; cursor: pointer;
} }
#bot-selector,
#device-selector {
padding: 8px 16px;
padding-right: 40px;
border: none;
border-radius: 4px;
background-color: #6c757d; /* Gray background */
color: white; /* White text */
cursor: pointer;
appearance: none; /* Removes default browser styling for dropdowns */
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E"); /* Custom arrow */
background-repeat: no-repeat;
background-position: right 8px center; /* Position the arrow */
}
#bot-selector:focus,
#device-selector:focus {
outline: none;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); /* Add a subtle focus effect */
}
#connect-btn { #connect-btn {
background-color: #4caf50; background-color: #4caf50;
color: white; color: white;
@@ -38,6 +72,9 @@ body {
color: white; color: white;
} }
#mic-toggle-btn {
}
button:disabled { button:disabled {
opacity: 0.5; opacity: 0.5;
cursor: not-allowed; cursor: not-allowed;