Skip to content

Commit

Permalink
v2.0 node (#261)
Browse files Browse the repository at this point in the history
  • Loading branch information
ksyeo1010 authored Nov 24, 2023
1 parent 1889e9c commit d6c2dd5
Show file tree
Hide file tree
Showing 14 changed files with 949 additions and 766 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/nodejs-codestyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ jobs:
with:
node-version: lts/*

- name: Pre-build dependencies
run: npm install yarn

- name: Run Binding Linter
run: yarn && yarn lint
working-directory: binding/nodejs
16 changes: 11 additions & 5 deletions .github/workflows/nodejs-demos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14.x, 16.x, 18.x, 20.x]
node-version: [16.x, 18.x, 20.x]

steps:
- uses: actions/checkout@v3
Expand All @@ -39,8 +39,11 @@ jobs:
with:
node-version: ${{ matrix.node-version }}

- name: Pre-build dependencies
run: npm install yarn
# ************** REMOVE AFTER RELEASE ********************
- name: Build Node.js SDK
run: yarn && yarn build
working-directory: binding/nodejs
# ********************************************************

- name: Install dependencies
run: yarn install
Expand All @@ -58,8 +61,11 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Pre-build dependencies
run: npm install --global yarn
# ************** REMOVE AFTER RELEASE ********************
- name: Build Node.js SDK
run: yarn && yarn build
working-directory: binding/nodejs
# ********************************************************

- name: Install dependencies
run: yarn install
Expand Down
36 changes: 15 additions & 21 deletions .github/workflows/nodejs-perf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
init_performance_threshold_sec: 2.1
proc_performance_threshold_sec: 0.5
init_performance_threshold_sec: 3.0
proc_performance_threshold_sec: 0.75
- os: windows-latest
init_performance_threshold_sec: 2.5
init_performance_threshold_sec: 3.0
proc_performance_threshold_sec: 0.8
- os: macos-latest
init_performance_threshold_sec: 2.3
proc_performance_threshold_sec: 0.8
init_performance_threshold_sec: 3.5
proc_performance_threshold_sec: 4.0

steps:
- uses: actions/checkout@v3
Expand All @@ -49,9 +49,6 @@ jobs:
with:
node-version: lts/*

- name: Pre-build dependencies
run: npm install yarn

- name: Install dependencies
run: yarn install

Expand All @@ -67,27 +64,24 @@ jobs:
machine: [rpi3-32, rpi3-64, rpi4-32, rpi4-64, jetson]
include:
- machine: rpi3-32
init_performance_threshold_sec: 7.5
proc_performance_threshold_sec: 3.0
init_performance_threshold_sec: 9.0
proc_performance_threshold_sec: 8.5
- machine: rpi3-64
init_performance_threshold_sec: 8.5
proc_performance_threshold_sec: 3.0
init_performance_threshold_sec: 9.0
proc_performance_threshold_sec: 7.0
- machine: rpi4-32
init_performance_threshold_sec: 5.7
proc_performance_threshold_sec: 2.0
init_performance_threshold_sec: 6.2
proc_performance_threshold_sec: 4.0
- machine: rpi4-64
init_performance_threshold_sec: 5.1
proc_performance_threshold_sec: 1.9
init_performance_threshold_sec: 5.5
proc_performance_threshold_sec: 3.5
- machine: jetson
init_performance_threshold_sec: 5.0
proc_performance_threshold_sec: 2.0
init_performance_threshold_sec: 5.5
proc_performance_threshold_sec: 4.3

steps:
- uses: actions/checkout@v3

- name: Pre-build dependencies
run: npm install --global yarn

- name: Install dependencies
run: yarn install

Expand Down
8 changes: 1 addition & 7 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14.x, 16.x, 18.x, 20.x]
node-version: [16.x, 18.x, 20.x]

steps:
- uses: actions/checkout@v3
Expand All @@ -39,9 +39,6 @@ jobs:
with:
node-version: ${{ matrix.node-version }}

- name: Pre-build dependencies
run: npm install yarn

- name: Install dependencies
run: yarn install

Expand All @@ -58,9 +55,6 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Pre-build dependencies
run: npm install --global yarn

- name: Install dependencies
run: yarn install

Expand Down
2 changes: 1 addition & 1 deletion binding/nodejs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Cheetah is an on-device streaming speech-to-text engine. Cheetah is:

## Compatibility

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

## Installation
Expand Down
4 changes: 2 additions & 2 deletions binding/nodejs/copy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2022 Picovoice Inc.
// Copyright 2022-2023 Picovoice Inc.
//
// You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
// file accompanying this source.
Expand All @@ -10,7 +10,7 @@
//
"use strict";

const mkdirp = require("mkdirp");
const { mkdirp } = require("mkdirp");
const ncp = require("ncp").ncp;

console.log("Copying library files...");
Expand Down
8 changes: 4 additions & 4 deletions binding/nodejs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@picovoice/cheetah-node",
"version": "1.1.1",
"version": "2.0.0",
"description": "Picovoice Cheetah Node.js binding",
"main": "dist/index.js",
"types": "dist/types/index.d.ts",
Expand Down Expand Up @@ -39,13 +39,13 @@
"homepage": "https://picovoice.ai/products/cheetah/",
"devDependencies": {
"@types/jest": "^27.4.1",
"@types/node": "^17.0.21",
"@types/node": "^18.11.9",
"@typescript-eslint/eslint-plugin": "^5.19.0",
"@typescript-eslint/parser": "^5.19.0",
"eslint": "^8.13.0",
"eslint-plugin-jest": "^27.1.6",
"jest": "^27.5.1",
"mkdirp": "^1.0.4",
"mkdirp": "^3.0.1",
"ncp": "^2.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^2.6.2",
Expand All @@ -54,7 +54,7 @@
"wavefile": "^11.0.0"
},
"engines": {
"node": ">=12.0.0"
"node": ">=16.0.0"
},
"cpu": [
"!ia32",
Expand Down
25 changes: 18 additions & 7 deletions binding/nodejs/src/cheetah.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,26 +97,28 @@ export default class Cheetah {
}

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

let cheetahHandleAndStatus: CheetahHandleAndStatus | null = null;
try {
pvCheetah.set_sdk("nodejs");

cheetahHandleAndStatus = pvCheetah.init(
accessKey,
modelPath,
endpointDurationSec,
enableAutomaticPunctuation
);
} catch (err: any) {
pvStatusToException(<PvStatus>err.code, err);
pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err);
}

const status = cheetahHandleAndStatus!.status;
if (status !== PvStatus.SUCCESS) {
pvStatusToException(status, 'Cheetah failed to initialize');
this.handlePvStatus(status, 'Cheetah failed to initialize');
}

this._handle = cheetahHandleAndStatus!.handle;
this._pvCheetah = pvCheetah;
this._sampleRate = pvCheetah.sample_rate();
this._frameLength = pvCheetah.frame_length();
this._version = pvCheetah.version();
Expand Down Expand Up @@ -178,12 +180,12 @@ export default class Cheetah {
try {
partialTranscriptAndStatus = this._pvCheetah.process(this._handle, pcm);
} catch (err: any) {
pvStatusToException(<PvStatus>err.code, err);
pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err);
}

const status = partialTranscriptAndStatus!.status;
if (status !== PvStatus.SUCCESS) {
pvStatusToException(status, 'Cheetah failed to process the audio frame');
this.handlePvStatus(status, 'Cheetah failed to process the audio frame');
}

return [
Expand All @@ -210,12 +212,12 @@ export default class Cheetah {
try {
transcriptAndStatus = this._pvCheetah.flush(this._handle);
} catch (err: any) {
pvStatusToException(<PvStatus>err.code, err);
pvStatusToException(PvStatus[err.code as keyof typeof PvStatus], err);
}

const status = transcriptAndStatus!.status;
if (status !== PvStatus.SUCCESS) {
pvStatusToException(status, 'Cheetah failed to process the audio frame');
this.handlePvStatus(status, 'Cheetah failed to flush');
}

return transcriptAndStatus!.transcript;
Expand All @@ -240,4 +242,13 @@ export default class Cheetah {
console.warn('Cheetah is not initialized');
}
}

private handlePvStatus(status: PvStatus, message: string): void {
const errorObject = this._pvCheetah.get_error_stack();
if (errorObject.status === PvStatus.SUCCESS) {
pvStatusToException(status, message, errorObject.message_stack);
} else {
pvStatusToException(status, "Unable to get Cheetah error state");
}
}
}
68 changes: 50 additions & 18 deletions binding/nodejs/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,50 +12,82 @@

import PvStatus from './pv_status_t';

export class CheetahError extends Error {}
export class CheetahError extends Error {
private readonly _message: string;
private readonly _messageStack: string[];

constructor(message: string, messageStack: string[] = []) {
super(CheetahError.errorToString(message, messageStack));
this._message = message;
this._messageStack = messageStack;
}

get message(): string {
return this._message;
}

get messageStack(): string[] {
return this._messageStack;
}

private static errorToString(
initial: string,
messageStack: string[]
): string {
let msg = initial;

if (messageStack.length > 0) {
msg += `: ${messageStack.reduce((acc, value, index) =>
acc + '\n [' + index + '] ' + value, '')}`;
}

return msg;
}
}

export class CheetahOutOfMemoryError extends CheetahError {}
export class CheetahIoError extends CheetahError {}
export class CheetahIOError extends CheetahError {}
export class CheetahInvalidArgumentError extends CheetahError {}
export class CheetahStopIterationError extends CheetahError {}
export class CheetahKeyError extends CheetahError {}
export class CheetahInvalidStateError extends CheetahError {}
export class CheetahRuntimeError extends CheetahError {}
export class CheetahActivationError extends CheetahError {}
export class CheetahActivationLimitReached extends CheetahError {}
export class CheetahActivationThrottled extends CheetahError {}
export class CheetahActivationRefused extends CheetahError {}
export class CheetahActivationLimitReachedError extends CheetahError {}
export class CheetahActivationThrottledError extends CheetahError {}
export class CheetahActivationRefusedError extends CheetahError {}

export function pvStatusToException(
pvStatus: PvStatus,
errorMessage: string
errorMessage: string,
messageStack: string[] = []
): CheetahError {
switch (pvStatus) {
case PvStatus.OUT_OF_MEMORY:
throw new CheetahOutOfMemoryError(errorMessage);
throw new CheetahOutOfMemoryError(errorMessage, messageStack);
case PvStatus.IO_ERROR:
throw new CheetahIoError(errorMessage);
throw new CheetahIOError(errorMessage, messageStack);
case PvStatus.INVALID_ARGUMENT:
throw new CheetahInvalidArgumentError(errorMessage);
throw new CheetahInvalidArgumentError(errorMessage, messageStack);
case PvStatus.STOP_ITERATION:
throw new CheetahStopIterationError(errorMessage);
throw new CheetahStopIterationError(errorMessage, messageStack);
case PvStatus.KEY_ERROR:
throw new CheetahKeyError(errorMessage);
throw new CheetahKeyError(errorMessage, messageStack);
case PvStatus.INVALID_STATE:
throw new CheetahInvalidStateError(errorMessage);
throw new CheetahInvalidStateError(errorMessage, messageStack);
case PvStatus.RUNTIME_ERROR:
throw new CheetahRuntimeError(errorMessage);
throw new CheetahRuntimeError(errorMessage, messageStack);
case PvStatus.ACTIVATION_ERROR:
throw new CheetahActivationError(errorMessage);
throw new CheetahActivationError(errorMessage, messageStack);
case PvStatus.ACTIVATION_LIMIT_REACHED:
throw new CheetahActivationLimitReached(errorMessage);
throw new CheetahActivationLimitReachedError(errorMessage, messageStack);
case PvStatus.ACTIVATION_THROTTLED:
throw new CheetahActivationThrottled(errorMessage);
throw new CheetahActivationThrottledError(errorMessage, messageStack);
case PvStatus.ACTIVATION_REFUSED:
throw new CheetahActivationRefused(errorMessage);
throw new CheetahActivationRefusedError(errorMessage, messageStack);
default:
// eslint-disable-next-line no-console
console.warn(`Unmapped error code: ${pvStatus}`);
throw new CheetahError(errorMessage);
throw new CheetahError(errorMessage, messageStack);
}
}
Loading

0 comments on commit d6c2dd5

Please sign in to comment.