Compare commits

..

2 Commits

Author SHA1 Message Date
bvandeusen 027fbec606 Merge pull request 'Release v26.04.14.3 — Live amplitude mic pulse' (#34) from dev into main 2026-04-15 02:54:42 +00:00
bvandeusen 730dbfaf7b feat(voice): pulse mic button with live amplitude
The mic button now scales and glows proportional to the silence
detector's RMS amplitude instead of sitting static. Gives obvious
feedback that audio is actually being picked up — silence still
breathes via a 0.1 floor, loud input caps at ~1.18x scale so it
doesn't punch through the input bar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 22:46:37 -04:00
+21 -1
View File
@@ -114,6 +114,18 @@ const transcribingVoice = ref(false)
const recorder = useVoiceRecorder()
const silenceDetector = useSilenceDetector()
// Live mic pulse. `silenceDetector.amplitude` is 0..1 RMS; we floor at 0.1
// so the button still breathes on silence and cap the scale growth so loud
// input doesn't punch through the input bar.
const micStyle = computed(() => {
if (!recorder.recording.value) return {}
const pulse = 0.1 + Math.min(silenceDetector.amplitude.value, 1) * 0.9
return {
transform: `scale(${1 + pulse * 0.18})`,
boxShadow: `0 0 ${6 + pulse * 14}px ${2 + pulse * 4}px rgba(239, 68, 68, ${0.2 + pulse * 0.3})`,
}
})
async function toggleVoice() {
if (transcribingVoice.value) return
if (recorder.recording.value) {
@@ -235,6 +247,7 @@ defineExpose({ focus, prefill })
v-if="voiceEnabled"
class="btn-icon btn-mic"
:class="{ 'mic-recording': recorder.recording.value, 'mic-transcribing': transcribingVoice }"
:style="micStyle"
@click.prevent="toggleVoice"
:disabled="transcribingVoice || !store.chatReady"
:title="recorder.recording.value ? 'Click to stop (or wait for silence)' : 'Click to speak'"
@@ -343,7 +356,14 @@ defineExpose({ focus, prefill })
.btn-icon:hover { opacity: 1; }
.btn-icon:disabled { opacity: 0.3; cursor: default; }
.btn-mic.mic-recording { opacity: 1; color: #ef4444; }
.btn-mic.mic-recording {
opacity: 1;
color: #ef4444;
border-radius: 50%;
/* Smooth between amplitude samples (~100ms) so the pulse feels continuous
rather than stepping. */
transition: transform 0.12s ease-out, box-shadow 0.12s ease-out;
}
.btn-mic.mic-transcribing { opacity: 0.5; }
.note-picker-wrapper { position: relative; }