Skip to content

Commit d6c2dd5

Browse files
authored
v2.0 node (#261)
1 parent 1889e9c commit d6c2dd5

File tree

14 files changed

+949
-766
lines changed

14 files changed

+949
-766
lines changed

.github/workflows/nodejs-codestyle.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ jobs:
2727
with:
2828
node-version: lts/*
2929

30-
- name: Pre-build dependencies
31-
run: npm install yarn
32-
3330
- name: Run Binding Linter
3431
run: yarn && yarn lint
3532
working-directory: binding/nodejs

.github/workflows/nodejs-demos.yml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
matrix:
3131
os: [ubuntu-latest, windows-latest, macos-latest]
32-
node-version: [14.x, 16.x, 18.x, 20.x]
32+
node-version: [16.x, 18.x, 20.x]
3333

3434
steps:
3535
- uses: actions/checkout@v3
@@ -39,8 +39,11 @@ jobs:
3939
with:
4040
node-version: ${{ matrix.node-version }}
4141

42-
- name: Pre-build dependencies
43-
run: npm install yarn
42+
# ************** REMOVE AFTER RELEASE ********************
43+
- name: Build Node.js SDK
44+
run: yarn && yarn build
45+
working-directory: binding/nodejs
46+
# ********************************************************
4447

4548
- name: Install dependencies
4649
run: yarn install
@@ -58,8 +61,11 @@ jobs:
5861
steps:
5962
- uses: actions/checkout@v3
6063

61-
- name: Pre-build dependencies
62-
run: npm install --global yarn
64+
# ************** REMOVE AFTER RELEASE ********************
65+
- name: Build Node.js SDK
66+
run: yarn && yarn build
67+
working-directory: binding/nodejs
68+
# ********************************************************
6369

6470
- name: Install dependencies
6571
run: yarn install

.github/workflows/nodejs-perf.yml

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ jobs:
3232
os: [ubuntu-latest, windows-latest, macos-latest]
3333
include:
3434
- os: ubuntu-latest
35-
init_performance_threshold_sec: 2.1
36-
proc_performance_threshold_sec: 0.5
35+
init_performance_threshold_sec: 3.0
36+
proc_performance_threshold_sec: 0.75
3737
- os: windows-latest
38-
init_performance_threshold_sec: 2.5
38+
init_performance_threshold_sec: 3.0
3939
proc_performance_threshold_sec: 0.8
4040
- os: macos-latest
41-
init_performance_threshold_sec: 2.3
42-
proc_performance_threshold_sec: 0.8
41+
init_performance_threshold_sec: 3.5
42+
proc_performance_threshold_sec: 4.0
4343

4444
steps:
4545
- uses: actions/checkout@v3
@@ -49,9 +49,6 @@ jobs:
4949
with:
5050
node-version: lts/*
5151

52-
- name: Pre-build dependencies
53-
run: npm install yarn
54-
5552
- name: Install dependencies
5653
run: yarn install
5754

@@ -67,27 +64,24 @@ jobs:
6764
machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64, jetson]
6865
include:
6966
- machine: rpi3-32
70-
init_performance_threshold_sec: 7.5
71-
proc_performance_threshold_sec: 3.0
67+
init_performance_threshold_sec: 9.0
68+
proc_performance_threshold_sec: 8.5
7269
- machine: rpi3-64
73-
init_performance_threshold_sec: 8.5
74-
proc_performance_threshold_sec: 3.0
70+
init_performance_threshold_sec: 9.0
71+
proc_performance_threshold_sec: 7.0
7572
- machine: rpi4-32
76-
init_performance_threshold_sec: 5.7
77-
proc_performance_threshold_sec: 2.0
73+
init_performance_threshold_sec: 6.2
74+
proc_performance_threshold_sec: 4.0
7875
- machine: rpi4-64
79-
init_performance_threshold_sec: 5.1
80-
proc_performance_threshold_sec: 1.9
76+
init_performance_threshold_sec: 5.5
77+
proc_performance_threshold_sec: 3.5
8178
- machine: jetson
82-
init_performance_threshold_sec: 5.0
83-
proc_performance_threshold_sec: 2.0
79+
init_performance_threshold_sec: 5.5
80+
proc_performance_threshold_sec: 4.3
8481

8582
steps:
8683
- uses: actions/checkout@v3
8784

88-
- name: Pre-build dependencies
89-
run: npm install --global yarn
90-
9185
- name: Install dependencies
9286
run: yarn install
9387

.github/workflows/nodejs.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
matrix:
3131
os: [ubuntu-latest, windows-latest, macos-latest]
32-
node-version: [14.x, 16.x, 18.x, 20.x]
32+
node-version: [16.x, 18.x, 20.x]
3333

3434
steps:
3535
- uses: actions/checkout@v3
@@ -39,9 +39,6 @@ jobs:
3939
with:
4040
node-version: ${{ matrix.node-version }}
4141

42-
- name: Pre-build dependencies
43-
run: npm install yarn
44-
4542
- name: Install dependencies
4643
run: yarn install
4744

@@ -58,9 +55,6 @@ jobs:
5855
steps:
5956
- uses: actions/checkout@v3
6057

61-
- name: Pre-build dependencies
62-
run: npm install --global yarn
63-
6458
- name: Install dependencies
6559
run: yarn install
6660

binding/nodejs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Cheetah is an on-device streaming speech-to-text engine. Cheetah is:
1515

1616
## Compatibility
1717

18-
- Node.js 12+
18+
- Node.js 16+
1919
- Runs on Linux (x86_64), macOS (x86_64, arm64), Windows (x86_64), Raspberry Pi (4, 3), and NVIDIA Jetson Nano.
2020

2121
## Installation

binding/nodejs/copy.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2022 Picovoice Inc.
2+
// Copyright 2022-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.
@@ -10,7 +10,7 @@
1010
//
1111
"use strict";
1212

13-
const mkdirp = require("mkdirp");
13+
const { mkdirp } = require("mkdirp");
1414
const ncp = require("ncp").ncp;
1515

1616
console.log("Copying library files...");

binding/nodejs/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@picovoice/cheetah-node",
3-
"version": "1.1.1",
3+
"version": "2.0.0",
44
"description": "Picovoice Cheetah Node.js binding",
55
"main": "dist/index.js",
66
"types": "dist/types/index.d.ts",
@@ -39,13 +39,13 @@
3939
"homepage": "https://picovoice.ai/products/cheetah/",
4040
"devDependencies": {
4141
"@types/jest": "^27.4.1",
42-
"@types/node": "^17.0.21",
42+
"@types/node": "^18.11.9",
4343
"@typescript-eslint/eslint-plugin": "^5.19.0",
4444
"@typescript-eslint/parser": "^5.19.0",
4545
"eslint": "^8.13.0",
4646
"eslint-plugin-jest": "^27.1.6",
4747
"jest": "^27.5.1",
48-
"mkdirp": "^1.0.4",
48+
"mkdirp": "^3.0.1",
4949
"ncp": "^2.0.0",
5050
"npm-run-all": "^4.1.5",
5151
"prettier": "^2.6.2",
@@ -54,7 +54,7 @@
5454
"wavefile": "^11.0.0"
5555
},
5656
"engines": {
57-
"node": ">=12.0.0"
57+
"node": ">=16.0.0"
5858
},
5959
"cpu": [
6060
"!ia32",

binding/nodejs/src/cheetah.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,28 @@ export default class Cheetah {
9797
}
9898

9999
const pvCheetah = require(libraryPath); // eslint-disable-line
100+
this._pvCheetah = pvCheetah;
100101

101102
let cheetahHandleAndStatus: CheetahHandleAndStatus | null = null;
102103
try {
104+
pvCheetah.set_sdk("nodejs");
105+
103106
cheetahHandleAndStatus = pvCheetah.init(
104107
accessKey,
105108
modelPath,
106109
endpointDurationSec,
107110
enableAutomaticPunctuation
108111
);
109112
} catch (err: any) {
110-
pvStatusToException(<PvStatus>err.code, err);
113+
pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err);
111114
}
112115

113116
const status = cheetahHandleAndStatus!.status;
114117
if (status !== PvStatus.SUCCESS) {
115-
pvStatusToException(status, 'Cheetah failed to initialize');
118+
this.handlePvStatus(status, 'Cheetah failed to initialize');
116119
}
117120

118121
this._handle = cheetahHandleAndStatus!.handle;
119-
this._pvCheetah = pvCheetah;
120122
this._sampleRate = pvCheetah.sample_rate();
121123
this._frameLength = pvCheetah.frame_length();
122124
this._version = pvCheetah.version();
@@ -178,12 +180,12 @@ export default class Cheetah {
178180
try {
179181
partialTranscriptAndStatus = this._pvCheetah.process(this._handle, pcm);
180182
} catch (err: any) {
181-
pvStatusToException(<PvStatus>err.code, err);
183+
pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err);
182184
}
183185

184186
const status = partialTranscriptAndStatus!.status;
185187
if (status !== PvStatus.SUCCESS) {
186-
pvStatusToException(status, 'Cheetah failed to process the audio frame');
188+
this.handlePvStatus(status, 'Cheetah failed to process the audio frame');
187189
}
188190

189191
return [
@@ -210,12 +212,12 @@ export default class Cheetah {
210212
try {
211213
transcriptAndStatus = this._pvCheetah.flush(this._handle);
212214
} catch (err: any) {
213-
pvStatusToException(<PvStatus>err.code, err);
215+
pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err);
214216
}
215217

216218
const status = transcriptAndStatus!.status;
217219
if (status !== PvStatus.SUCCESS) {
218-
pvStatusToException(status, 'Cheetah failed to process the audio frame');
220+
this.handlePvStatus(status, 'Cheetah failed to flush');
219221
}
220222

221223
return transcriptAndStatus!.transcript;
@@ -240,4 +242,13 @@ export default class Cheetah {
240242
console.warn('Cheetah is not initialized');
241243
}
242244
}
245+
246+
private handlePvStatus(status: PvStatus, message: string): void {
247+
const errorObject = this._pvCheetah.get_error_stack();
248+
if (errorObject.status === PvStatus.SUCCESS) {
249+
pvStatusToException(status, message, errorObject.message_stack);
250+
} else {
251+
pvStatusToException(status, "Unable to get Cheetah error state");
252+
}
253+
}
243254
}

binding/nodejs/src/errors.ts

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,50 +12,82 @@
1212

1313
import PvStatus from './pv_status_t';
1414

15-
export class CheetahError extends Error {}
15+
export class CheetahError extends Error {
16+
private readonly _message: string;
17+
private readonly _messageStack: string[];
18+
19+
constructor(message: string, messageStack: string[] = []) {
20+
super(CheetahError.errorToString(message, messageStack));
21+
this._message = message;
22+
this._messageStack = messageStack;
23+
}
24+
25+
get message(): string {
26+
return this._message;
27+
}
28+
29+
get messageStack(): string[] {
30+
return this._messageStack;
31+
}
32+
33+
private static errorToString(
34+
initial: string,
35+
messageStack: string[]
36+
): string {
37+
let msg = initial;
38+
39+
if (messageStack.length > 0) {
40+
msg += `: ${messageStack.reduce((acc, value, index) =>
41+
acc + '\n [' + index + '] ' + value, '')}`;
42+
}
43+
44+
return msg;
45+
}
46+
}
1647

1748
export class CheetahOutOfMemoryError extends CheetahError {}
18-
export class CheetahIoError extends CheetahError {}
49+
export class CheetahIOError extends CheetahError {}
1950
export class CheetahInvalidArgumentError extends CheetahError {}
2051
export class CheetahStopIterationError extends CheetahError {}
2152
export class CheetahKeyError extends CheetahError {}
2253
export class CheetahInvalidStateError extends CheetahError {}
2354
export class CheetahRuntimeError extends CheetahError {}
2455
export class CheetahActivationError extends CheetahError {}
25-
export class CheetahActivationLimitReached extends CheetahError {}
26-
export class CheetahActivationThrottled extends CheetahError {}
27-
export class CheetahActivationRefused extends CheetahError {}
56+
export class CheetahActivationLimitReachedError extends CheetahError {}
57+
export class CheetahActivationThrottledError extends CheetahError {}
58+
export class CheetahActivationRefusedError extends CheetahError {}
2859

2960
export function pvStatusToException(
3061
pvStatus: PvStatus,
31-
errorMessage: string
62+
errorMessage: string,
63+
messageStack: string[] = []
3264
): CheetahError {
3365
switch (pvStatus) {
3466
case PvStatus.OUT_OF_MEMORY:
35-
throw new CheetahOutOfMemoryError(errorMessage);
67+
throw new CheetahOutOfMemoryError(errorMessage, messageStack);
3668
case PvStatus.IO_ERROR:
37-
throw new CheetahIoError(errorMessage);
69+
throw new CheetahIOError(errorMessage, messageStack);
3870
case PvStatus.INVALID_ARGUMENT:
39-
throw new CheetahInvalidArgumentError(errorMessage);
71+
throw new CheetahInvalidArgumentError(errorMessage, messageStack);
4072
case PvStatus.STOP_ITERATION:
41-
throw new CheetahStopIterationError(errorMessage);
73+
throw new CheetahStopIterationError(errorMessage, messageStack);
4274
case PvStatus.KEY_ERROR:
43-
throw new CheetahKeyError(errorMessage);
75+
throw new CheetahKeyError(errorMessage, messageStack);
4476
case PvStatus.INVALID_STATE:
45-
throw new CheetahInvalidStateError(errorMessage);
77+
throw new CheetahInvalidStateError(errorMessage, messageStack);
4678
case PvStatus.RUNTIME_ERROR:
47-
throw new CheetahRuntimeError(errorMessage);
79+
throw new CheetahRuntimeError(errorMessage, messageStack);
4880
case PvStatus.ACTIVATION_ERROR:
49-
throw new CheetahActivationError(errorMessage);
81+
throw new CheetahActivationError(errorMessage, messageStack);
5082
case PvStatus.ACTIVATION_LIMIT_REACHED:
51-
throw new CheetahActivationLimitReached(errorMessage);
83+
throw new CheetahActivationLimitReachedError(errorMessage, messageStack);
5284
case PvStatus.ACTIVATION_THROTTLED:
53-
throw new CheetahActivationThrottled(errorMessage);
85+
throw new CheetahActivationThrottledError(errorMessage, messageStack);
5486
case PvStatus.ACTIVATION_REFUSED:
55-
throw new CheetahActivationRefused(errorMessage);
87+
throw new CheetahActivationRefusedError(errorMessage, messageStack);
5688
default:
5789
// eslint-disable-next-line no-console
5890
console.warn(`Unmapped error code: ${pvStatus}`);
59-
throw new CheetahError(errorMessage);
91+
throw new CheetahError(errorMessage, messageStack);
6092
}
6193
}

0 commit comments

Comments
 (0)