Skip to content

Commit b428dc3

Browse files
authored
Merge pull request #42 from Picovoice/user-media-check
2 parents c36a027 + ae68ad1 commit b428dc3

File tree

5 files changed

+55
-23
lines changed

5 files changed

+55
-23
lines changed

demo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"author": "Picovoice Inc",
1818
"license": "Apache-2.0",
1919
"dependencies": {
20-
"@picovoice/web-voice-processor": "^4.0.3",
20+
"@picovoice/web-voice-processor": "^4.0.4",
2121
"http-server": "^14.0.0",
2222
"wavefile": "^11.0.0"
2323
}

demo/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
# yarn lockfile v1
33

44

5-
"@picovoice/web-voice-processor@^4.0.3":
6-
version "4.0.3"
7-
resolved "https://registry.yarnpkg.com/@picovoice/web-voice-processor/-/web-voice-processor-4.0.3.tgz#728b1e61ae027f2679796fda27040209ebeadf5b"
8-
integrity sha512-4hUKRNMfdqIx74VPi8mwkow8yyLM1NsMWi+Ak2uxK213A+26R5Xr9ms99hkOuPrBMHCGl+Ffuo9QXmkGBjsbnQ==
5+
"@picovoice/web-voice-processor@^4.0.4":
6+
version "4.0.4"
7+
resolved "https://registry.yarnpkg.com/@picovoice/web-voice-processor/-/web-voice-processor-4.0.4.tgz#12140c9a0120e0db9dda80bcf00d7f827f1a8c99"
8+
integrity sha512-WZ4PPXU0i/yPzIjd+jbx9VSMF6Shbyf2BXt2U7a6MASJ2KWeG9+zDx6nteDF10cyG3T78G+4EB24tLsdyLVmWw==
99

1010
ansi-styles@^4.1.0:
1111
version "4.3.0"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@picovoice/web-voice-processor",
3-
"version": "4.0.3",
3+
"version": "4.0.4",
44
"description": "Real-time audio processing for voice, in web browsers",
55
"entry": "src/index.ts",
66
"module": "dist/esm/index.js",

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import './polyfill/audioworklet_polyfill';
22

33
import { WvpMessageEvent, WebVoiceProcessorOptions } from './types';
44

5-
import { WebVoiceProcessor} from './web_voice_processor';
5+
import { WebVoiceProcessor, WvpError } from './web_voice_processor';
66
import { browserCompatibilityCheck } from './utils';
77

88
import { VuMeterEngine } from './engines/vu_meter_engine';
@@ -18,6 +18,7 @@ ResamplerWorker.setWasm(resamplerWasm);
1818
export {
1919
ResamplerWorker,
2020
VuMeterEngine,
21+
WvpError,
2122
WebVoiceProcessor,
2223
WebVoiceProcessorOptions,
2324
WvpMessageEvent,

src/web_voice_processor.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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

2121
import { 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

Comments
 (0)