Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.0 node #261

Merged
merged 8 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
ksyeo1010 marked this conversation as resolved.
Show resolved Hide resolved
},
"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