From 2d1355fc27832360d48c13d2e1431a8776e36bf4 Mon Sep 17 00:00:00 2001 From: Mahmoud Zalt Date: Fri, 24 May 2024 22:11:37 +0200 Subject: [PATCH] improve audio playbacks transition for smooth interruptions --- src/core/AiAssistantEngine.ts | 5 +++++ src/core/AudioPlayer.ts | 21 ++++++++++++++++++--- src/core/AudioRecorder.ts | 4 ++-- src/core/SpeechRecognizer.ts | 4 ++-- src/core/User.ts | 2 +- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/core/AiAssistantEngine.ts b/src/core/AiAssistantEngine.ts index 5b42752..5adf836 100644 --- a/src/core/AiAssistantEngine.ts +++ b/src/core/AiAssistantEngine.ts @@ -99,6 +99,9 @@ class AiAssistantEngine extends EventEmitter { startProcessing = async (): Promise => { Logger.log('F: startProcessing'); + // Lower the volume of any currently playing audio + this.audioPlayer.setVolume(0.5); + // Reset the assistant before starting processing this._resetEngine(); @@ -252,6 +255,8 @@ class AiAssistantEngine extends EventEmitter { } // ----[ Step 4: Play AI Audio Reply ]---- + // Stop any currently playing audio + this.audioPlayer.stopCurrentSound(); // Handle audio response if available as a Stream if (response.data.shouldStreamAudioReply) { this._handleAudioStreamResponse(response.data.outputTextReply); diff --git a/src/core/AudioPlayer.ts b/src/core/AudioPlayer.ts index 9f29bba..f44eac7 100644 --- a/src/core/AudioPlayer.ts +++ b/src/core/AudioPlayer.ts @@ -1,6 +1,6 @@ // src/core/AudioPlayer.ts -import { Howl } from 'howler'; +import { Howl, Howler } from 'howler'; import config from './config'; import Logger from './Logger'; @@ -11,6 +11,7 @@ interface SoundCallback { class AudioPlayer { private readonly startSound: Howl; private readonly endSound: Howl; + private currentSound: Howl | null = null; constructor() { // Specify volume at 50% for start and end tones (0.5 = 50%) @@ -82,7 +83,7 @@ class AudioPlayer { ): void => { Logger.log('F: playAiReplyFromUrl'); // Play AI reply at 100% volume (1.0 = 100%) - this.playSound(audioFileUrl, callback, 1.0); + this.currentSound = this.playSound(audioFileUrl, callback, 1.0); }; playStartTone = (): void => { @@ -93,6 +94,19 @@ class AudioPlayer { this.endSound.play(); }; + setVolume = (volume: number): void => { + if (this.currentSound) { + this.currentSound.volume(volume); + } + }; + + stopCurrentSound = (): void => { + if (this.currentSound) { + this.currentSound.stop(); + this.currentSound = null; + } + }; + private initializeSound = (soundFileUrl: string, volume = 1.0): Howl => { return new Howl({ src: [soundFileUrl], @@ -108,7 +122,7 @@ class AudioPlayer { soundFileUrl: string, callback?: SoundCallback, volume?: number, - ): void => { + ): Howl => { Logger.log('F: playSound'); const sound = new Howl({ src: [soundFileUrl], @@ -123,6 +137,7 @@ class AudioPlayer { }); sound.play(); + return sound; }; } diff --git a/src/core/AudioRecorder.ts b/src/core/AudioRecorder.ts index 100dfc2..3d77585 100644 --- a/src/core/AudioRecorder.ts +++ b/src/core/AudioRecorder.ts @@ -22,13 +22,13 @@ class AudioRecorder { this.handleStop = this.handleStop.bind(this); } - public async test_startRecording(): Promise { + async test_startRecording(): Promise { return new Promise((resolve, reject) => { reject(new Error('TEST Error starting recording...')); }); } - public async startRecording(): Promise { + async startRecording(): Promise { Logger.log('F: startRecording'); try { if ( diff --git a/src/core/SpeechRecognizer.ts b/src/core/SpeechRecognizer.ts index 9e61cd6..f2f75c8 100644 --- a/src/core/SpeechRecognizer.ts +++ b/src/core/SpeechRecognizer.ts @@ -69,13 +69,13 @@ class SpeechRecognizer { this.isInitialized = true; } - public async test_startListening(): Promise { + async test_startListening(): Promise { return new Promise((resolve, reject) => { reject(new Error('TEST Error starting listening...')); }); } - public async startListening(): Promise { + async startListening(): Promise { Logger.log('F: startListening'); if (!this.isInitialized) { diff --git a/src/core/User.ts b/src/core/User.ts index 32b2ba6..eb76595 100644 --- a/src/core/User.ts +++ b/src/core/User.ts @@ -15,7 +15,7 @@ class User { this.generatedUserId = this._generateEndUserId(); } - public getEndUserDetails(): EndUserDetails { + getEndUserDetails(): EndUserDetails { return { endUserAgent: navigator.userAgent, generatedEndUserId: this.generatedUserId,