77 @click =" toggleChatMode"
88 >
99 <div class =" w-5 h-5 flex items-center justify-center" >
10- <div v-if =" !showButtonSpinner " class =" flex justify-evenly items-center gap-[0.1rem]" >
11- <AudioLines :showAnimation =" showAnimation " :isRecording =" isAudioChatMode " />
10+ <div v-if =" microphoneButtonMode === 'listen' || microphoneButtonMode === 'off' " class =" flex justify-evenly items-center gap-[0.1rem]" >
11+ <AudioLines :showAnimation =" showAudioWavesAnimation " :isRecording =" microphoneButtonMode === ' listen ' " />
1212 </div >
13- <div v-else-if =" showStopGenerationMessage " class =" flex items-center justify-center gap-2 text-white text-sm" >
13+ <div v-else-if =" microphoneButtonMode === 'generating' " class =" flex items-center justify-center gap-2 text-white text-sm" >
1414 <span class =" w-3 h-3 bg-white rounded-sm" />
1515 {{ $t('Stop') }}
1616 </div >
2222
2323
2424<script setup lang="ts">
25- import { computed , onBeforeUnmount , ref , watch } from ' vue' ;
25+ import { computed , onMounted , onBeforeUnmount , ref , watch } from ' vue' ;
2626import debounce from ' lodash/debounce' ;
2727import { requestMicAndStartVAD , stopUserMedia , getRecorder , CALIBRATION_DURATION } from ' ./voiceActivityDetection' ;
2828import { Spinner } from ' @/afcl'
29- import { useAdminforth } from ' @/adminforth' ;
3029import { storeToRefs } from ' pinia' ;
3130import { useAgentStore } from ' ../composables/useAgentStore' ;
3231import { useAgentAudio } from ' ../composables/useAgentAudio' ;
3332import AudioLines from ' ./AudioLines.vue' ;
3433
35- const adminforth = useAdminforth ();
3634const agentStore = useAgentStore ();
3735const agentAudio = useAgentAudio ();
3836const { sendAudioToServerAndHandleResponse } = agentAudio ;
3937const { stopGenerationAndAudio } = agentAudio ;
40- const { isStreamingResponse } = storeToRefs (agentAudio );
41-
42- agentStore .registerOnBeforeChatCloseCallback (async () => {
43- if (agentStore .isAudioChatMode ) {
44- onStopRecording ();
45- agentStore .setIsAudioChatMode (false );
46- }
47- });
48-
49- const showAnimation = ref (false );
50- const showButtonSpinner = ref (false );
51- const showStopGenerationMessage = ref (false );
38+ const { stopCurrentAudioPlayback } = agentAudio ;
39+ const { agentAudioMode } = storeToRefs (agentAudio );
40+ const microphoneButtonMode = ref <' off' | ' calibrating' | ' listen' | ' transcribing' | ' generating' >(' off' );
41+ const showAudioWavesAnimation = ref (false );
5242const hideAnimationDebounced = debounce (() => {
53- showAnimation .value = false ;
43+ showAudioWavesAnimation .value = false ;
5444}, 100 );
5545const sendUserRecordDebounced = debounce (() => {
5646 sendRecordForTranscription ();
57- }, 1000 );
47+ }, 500 );
5848
5949const isAudioChatMode = computed (() => agentStore .isAudioChatMode );
6050
61- watch (isStreamingResponse , (newVal ) => {
62- if (! newVal ) {
63- showStopGenerationMessage .value = false ;
64- showButtonSpinner .value = false ;
51+ onMounted (() => {
52+ agentStore .registerOnBeforeChatCloseCallback (async () => {
53+ if (agentStore .isAudioChatMode ) {
54+ onStopRecording ();
55+ agentStore .setIsAudioChatMode (false );
56+ }
57+ });
58+ });
59+
60+ watch (agentAudioMode , (newVal ) => {
61+ if (newVal === ' streaming' ) {
62+ stopCurrentAudioPlayback (true );
63+ microphoneButtonMode .value = ' generating' ;
64+ } else if (newVal === ' transcribing' ) {
65+ microphoneButtonMode .value = ' transcribing' ;
66+ } else if (newVal === ' fetchingAudio' ) {
67+ // Generation is done, waiting for audio to be ready
68+ } else if (newVal === ' playingAgentResponse' ) {
69+ // Audio is playing
6570 } else {
66- showButtonSpinner .value = true ;
67- showStopGenerationMessage .value = true ;
71+ if (isAudioChatMode .value ) {
72+ microphoneButtonMode .value = ' listen' ;
73+ } else {
74+ microphoneButtonMode .value = ' off' ;
75+ }
6876 }
6977})
7078
@@ -79,34 +87,31 @@ function toggleChatMode() {
7987}
8088
8189async function onStartRecording() {
82- showButtonSpinner .value = true ;
90+ microphoneButtonMode .value = ' calibrating ' ;
8391 await requestMicAndStartVAD (saidSomething , stopRecording , onAnySound );
8492 setTimeout (() => {
85- showButtonSpinner .value = false ;
93+ microphoneButtonMode .value = ' listen ' ;
8694 agentAudio .playBeep (1000 );
87- // Play a sound to indicate that recording has started
8895 }, CALIBRATION_DURATION );
8996}
9097
9198function onStopRecording() {
9299 agentAudio .playBeep (600 );
93100 stopUserMedia ();
94- showAnimation .value = false ;
95- // Play a sound to indicate that recording has stopped
101+ showAudioWavesAnimation .value = false ;
96102}
97103
98104function resetAll() {
99105 stopGenerationAndAudio ();
100- showAnimation .value = false ;
101- showButtonSpinner .value = false ;
102- showStopGenerationMessage .value = false ;
106+ microphoneButtonMode .value = ' off' ;
107+ showAudioWavesAnimation .value = false ;
103108 hideAnimationDebounced .cancel ();
104109 sendUserRecordDebounced .cancel ();
105110}
106111
107112
108113function saidSomething() {
109- showAnimation .value = true ;
114+ showAudioWavesAnimation .value = true ;
110115 hideAnimationDebounced ();
111116 sendUserRecordDebounced ();
112117}
@@ -118,23 +123,15 @@ function stopRecording() {
118123
119124function onAnySound(amplitude : number ) {
120125 if (amplitude < 0.01 ) {
121- showAnimation .value = false ;
126+ showAudioWavesAnimation .value = false ;
122127 return ;
123128 }
124- showAnimation .value = true ;
129+ showAudioWavesAnimation .value = true ;
125130 hideAnimationDebounced .cancel ();
126131}
127132
128- onBeforeUnmount (() => {
129- stopUserMedia ();
130- agentStore .setIsAudioChatMode (false );
131- onStopRecording ();
132- hideAnimationDebounced .cancel ();
133- sendUserRecordDebounced .cancel ();
134- });
135-
136133async function sendRecordForTranscription() {
137- showAnimation .value = false ;
134+ showAudioWavesAnimation .value = false ;
138135 const recordBlob = await getRecorder ();
139136 if (recordBlob ) {
140137 onStopRecording ();
@@ -147,6 +144,13 @@ async function sendRecordForTranscription() {
147144 }
148145}
149146
147+ onBeforeUnmount (() => {
148+ stopUserMedia ();
149+ agentStore .setIsAudioChatMode (false );
150+ onStopRecording ();
151+ hideAnimationDebounced .cancel ();
152+ sendUserRecordDebounced .cancel ();
153+ });
150154
151155
152156 </script >
0 commit comments