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>
This commit is contained in:
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user