Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions src/static/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,52 @@ body {
gap: 5px;
}

.volume-control {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
}

.volume-control label {
font-size: 0.8em;
color: #666;
min-width: 80px;
}

#input-volume {
-webkit-appearance: none;
width: 100%;
height: 4px;
background: #ddd;
border-radius: 2px;
outline: none;
opacity: 0.7;
transition: opacity 0.2s;
}

#input-volume:hover {
opacity: 1;
}

#input-volume::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 16px;
height: 16px;
background: #4285f4;
border-radius: 50%;
cursor: pointer;
}

#input-volume::-moz-range-thumb {
width: 16px;
height: 16px;
background: #4285f4;
border-radius: 50%;
cursor: pointer;
}

.visualizer-container label {
font-size: 0.8em;
color: #666;
Expand Down Expand Up @@ -611,3 +657,58 @@ body {
color: #666;
font-size: 12px;
}

/* Add these styles after the #screen-button styles */

#prevent-sleep-button,
#use-back-camera-button {
background: #4285f4;
color: white;
border: none;
padding: 8px;
border-radius: 50%;
cursor: pointer;
margin-left: 8px;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}

#prevent-sleep-button:hover,
#use-back-camera-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

#prevent-sleep-button:active,
#use-back-camera-button:active {
transform: translateY(1px);
}

#prevent-sleep-button::after,
#use-back-camera-button::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: rgba(255, 255, 255, 0.2);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: width 0.3s ease, height 0.3s ease;
}

#prevent-sleep-button:active::after,
#use-back-camera-button:active::after {
width: 200px;
height: 200px;
}

#prevent-sleep-button.active {
background: #ea4335;
}

#use-back-camera-button.active {
background: #ea4335;
}
1 change: 1 addition & 0 deletions src/static/icons
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

17 changes: 16 additions & 1 deletion src/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<title>Gemini 2.0 Flash Multimodal Live API Client</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<link rel="stylesheet" href="css/style.css">
<link rel="manifest" href="manifest.json">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Gemini Client">
<link rel="apple-touch-icon" href="icons/icon-192x192.png">
</head>
<body>
<div id="app">
Expand Down Expand Up @@ -60,8 +65,18 @@
<button id="screen-button">
<span id="screen-icon" class="material-symbols-outlined">screen_share</span>
</button>
<button id="prevent-sleep-button">
<span id="prevent-sleep-icon" class="material-symbols-outlined">bedtime</span>
</button>
<button id="use-back-camera-button">
<span id="back-camera-icon" class="material-symbols-outlined">flip_camera_ios</span>
</button>
<div class="audio-visualizers">
<div class="visualizer-container">
<div class="volume-control">
<label>Input Volume</label>
<input type="range" id="input-volume" min="0" max="1" step="0.01" value="1">
</div>
<label>Input Audio</label>
<div id="input-audio-visualizer"></div>
</div>
Expand All @@ -86,4 +101,4 @@
</div>
<script src="js/main.js" type="module"></script>
</body>
</html>
</html>
32 changes: 30 additions & 2 deletions src/static/js/audio/audio-recorder.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export class AudioRecorder {
this.source = null;
this.processor = null;
this.onAudioData = null;
this.gainNode = null;
this.volume = 1.0;

// Bind methods to preserve context
this.start = this.start.bind(this);
Expand Down Expand Up @@ -62,8 +64,13 @@ export class AudioRecorder {
}
};

// Create gain node and set initial volume
this.gainNode = this.audioContext.createGain();
this.gainNode.gain.value = this.volume;

// Connect audio nodes
this.source.connect(this.processor);
this.source.connect(this.gainNode);
this.gainNode.connect(this.processor);
this.processor.connect(this.audioContext.destination);
this.isRecording = true;
} catch (error) {
Expand Down Expand Up @@ -142,4 +149,25 @@ export class AudioRecorder {
);
}
}
}

/**
* @method setVolume
* @description Sets the recording volume level
* @param {number} volume - Volume level between 0 (mute) and 1 (max)
*/
setVolume(volume) {
if (this.gainNode) {
// Ensure volume is clamped between 0 and 1
const clampedVolume = Math.max(0, Math.min(1, volume));
this.gainNode.gain.value = clampedVolume;

// When volume is 0, disconnect the source to prevent any audio passing through
if (clampedVolume === 0) {
this.source.disconnect(this.gainNode);
} else if (!this.source.isConnected) {
// Reconnect if volume is restored
this.source.connect(this.gainNode);
}
}
}
}
2 changes: 1 addition & 1 deletion src/static/js/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const CONFIG = {
},
// You can change the system instruction to your liking
SYSTEM_INSTRUCTION: {
TEXT: 'You are my helpful assistant. You can see and hear me, and respond with voice and text. If you are asked about things you do not know, you can use the google search tool to find the answer.',
TEXT: 'You are my helpful assistant. Your name is Amy and you can call me Kyle. You have a humorous character and like joking sometimes.You can see and hear me, and respond with voice and text. If you are asked about things you do not know, you can use the google search tool to find the answer.',
},
// Default audio settings
AUDIO: {
Expand Down
Loading