11/*
2- Copyright 2018-2022 Picovoice Inc.
2+ Copyright 2018-2023 Picovoice Inc.
33
44 You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
55 file accompanying this source.
@@ -20,6 +20,16 @@ import { PvEngine, WebVoiceProcessorOptions, WvpState } from './types';
2020
2121import { AudioDumpEngine } from './engines/audio_dump_engine' ;
2222
23+ /**
24+ * WebVoiceProcessor Error Class
25+ */
26+ export class WvpError extends Error {
27+ constructor ( name : string , message : string ) {
28+ super ( message ) ;
29+ this . name = name ;
30+ }
31+ }
32+
2333/**
2434 * Obtain microphone permission and audio stream;
2535 * Down sample audio into 16kHz single-channel PCM for speech recognition (via ResamplerWorker).
@@ -167,21 +177,42 @@ export class WebVoiceProcessor {
167177 return new Promise ( ( resolve , reject ) => {
168178 this . _mutex
169179 . runExclusive ( async ( ) => {
170- if ( this . _audioContext === null || this . _state === WvpState . STOPPED || this . isReleased ) {
171- const { audioContext, microphoneStream, recorderNode, resamplerWorker } = await this . setupRecorder ( this . _options ) ;
172- this . _audioContext = audioContext ;
173- this . _microphoneStream = microphoneStream ;
174- this . _recorderNode = recorderNode ;
175- this . _resamplerWorker = resamplerWorker ;
176-
177- recorderNode . port . onmessage = ( event : MessageEvent ) : void => {
178- resamplerWorker . process ( event . data . buffer [ 0 ] ) ;
179- } ;
180- this . _state = WvpState . STARTED ;
181- }
182-
183- if ( this . _audioContext !== null && this . isSuspended ) {
184- await this . _audioContext . resume ( ) ;
180+ try {
181+ if ( this . _audioContext === null || this . _state === WvpState . STOPPED || this . isReleased ) {
182+ const { audioContext, microphoneStream, recorderNode, resamplerWorker } = await this . setupRecorder ( this . _options ) ;
183+ this . _audioContext = audioContext ;
184+ this . _microphoneStream = microphoneStream ;
185+ this . _recorderNode = recorderNode ;
186+ this . _resamplerWorker = resamplerWorker ;
187+
188+ recorderNode . port . onmessage = ( event : MessageEvent ) : void => {
189+ resamplerWorker . process ( event . data . buffer [ 0 ] ) ;
190+ } ;
191+ this . _state = WvpState . STARTED ;
192+ }
193+
194+ if ( this . _audioContext !== null && this . isSuspended ) {
195+ await this . _audioContext . resume ( ) ;
196+ }
197+ } catch ( error : any ) {
198+ if ( error . name === 'SecurityError' || error . name === 'NotAllowedError' ) {
199+ throw new WvpError (
200+ 'PermissionError' ,
201+ 'Failed to record audio: microphone permissions denied.'
202+ ) ;
203+ } else if ( error . name === 'NotFoundError' ) {
204+ throw new WvpError (
205+ 'DeviceMissingError' ,
206+ 'Failed to record audio: audio recording device was not found.'
207+ ) ;
208+ } else if ( error . name === 'NotReadableError' ) {
209+ throw new WvpError (
210+ 'DeviceReadError' ,
211+ 'Failed to record audio: audio recording device is not working correctly.'
212+ ) ;
213+ } else {
214+ throw error ;
215+ }
185216 }
186217 } )
187218 . then ( ( ) => {
0 commit comments