Skip to content

Commit f57893c

Browse files
authored
v2.0 node (#115)
1 parent 49dca3f commit f57893c

File tree

15 files changed

+211
-63
lines changed

15 files changed

+211
-63
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: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ jobs:
2929
strategy:
3030
matrix:
3131
os: [ ubuntu-latest, windows-latest, macos-latest ]
32-
node-version: [18.x, 20.x, 22.x]
32+
device: [cpu:1, cpu]
33+
node-version: [18.x, 20.x, 22.x, 24.x]
3334
include:
3435
- os: ubuntu-latest
3536
install-dep: sudo apt install libasound2-dev -y
@@ -43,32 +44,52 @@ jobs:
4344
with:
4445
node-version: ${{ matrix.node-version }}
4546

47+
# REMOVE AFTER RELEASE
48+
- name: Install binding
49+
run: yarn install && yarn build
50+
working-directory: binding/nodejs
51+
# REMOVE AFTER RELEASE
52+
4653
- name: Install dependencies
4754
run: |
4855
${{ matrix.install-dep }}
4956
yarn install
5057
5158
- name: Test streaming
52-
run: yarn streaming -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -t "Hello, I am Orca!"
59+
run: yarn streaming -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -y ${{ matrix.device }} -t "Hello, I am Orca!"
5360

5461
- name: Test file
55-
run: yarn file -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -t "Hello, I am Orca!" -o "./tmp.wav"
62+
run: yarn file -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -y ${{ matrix.device }} -t "Hello, I am Orca!" -o "./tmp.wav"
5663

5764
build-self-hosted:
5865
runs-on: ${{ matrix.machine }}
5966

6067
strategy:
6168
matrix:
69+
device: [best]
6270
machine: [ rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-64, pv-windows-arm64 ]
71+
include:
72+
- device: gpu
73+
machine: pv-linux
74+
- device: gpu
75+
machine: pv-windows
76+
- device: gpu
77+
machine: pv-ios
6378

6479
steps:
6580
- uses: actions/checkout@v3
6681

82+
# REMOVE AFTER RELEASE
83+
- name: Install binding
84+
run: yarn install && yarn build
85+
working-directory: binding/nodejs
86+
# REMOVE AFTER RELEASE
87+
6788
- name: Install dependencies
6889
run: yarn install
6990

7091
- name: Test streaming
71-
run: yarn streaming -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -t "Hello, I am Orca!"
92+
run: yarn streaming -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -y ${{ matrix.device }} -t "Hello, I am Orca!"
7293

7394
- name: Test file
74-
run: yarn file -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -t "Hello, I am Orca!" -o "./tmp.wav"
95+
run: yarn file -a ${{secrets.PV_VALID_ACCESS_KEY}} -m ../../lib/common/orca_params_en_female.pv -y ${{ matrix.device }} -t "Hello, I am Orca!" -o "./tmp.wav"

.github/workflows/nodejs-perf.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
run: yarn install
5151

5252
- name: Test
53-
run: yarn test test/perf.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --num_test_iterations=50 --proc_performance_threshold_sec=${{matrix.proc_performance_threshold_sec}}
53+
run: yarn test test/perf.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --device=cpu:1 --num_test_iterations=50 --proc_performance_threshold_sec=${{matrix.proc_performance_threshold_sec}}
5454

5555
perf-self-hosted:
5656
runs-on: ${{ matrix.machine }}
@@ -82,7 +82,7 @@ jobs:
8282
run: bash machine-state.sh
8383

8484
- name: Test
85-
run: yarn test test/perf.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --num_test_iterations=20 --proc_performance_threshold_sec=${{matrix.proc_performance_threshold_sec}}
85+
run: yarn test test/perf.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --device=cpu:1 --num_test_iterations=20 --proc_performance_threshold_sec=${{matrix.proc_performance_threshold_sec}}
8686

8787
- name: Machine state after
8888
working-directory: resources/.scripts
@@ -106,4 +106,4 @@ jobs:
106106
run: yarn install
107107

108108
- name: Test
109-
run: yarn test test/perf.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --num_test_iterations=50 --proc_performance_threshold_sec=${{matrix.proc_performance_threshold_sec}}
109+
run: yarn test test/perf.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --device=cpu:1 --num_test_iterations=50 --proc_performance_threshold_sec=${{matrix.proc_performance_threshold_sec}}

.github/workflows/nodejs.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ jobs:
3333
strategy:
3434
matrix:
3535
os: [ ubuntu-latest, windows-latest, macos-latest ]
36-
node-version: [18.x, 20.x, 22.x]
36+
device: [cpu:1, cpu]
37+
node-version: [18.x, 20.x, 22.x, 24.x]
3738

3839
steps:
3940
- uses: actions/checkout@v3
@@ -47,14 +48,22 @@ jobs:
4748
run: yarn install
4849

4950
- name: Test
50-
run: yarn test test/index.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}}
51+
run: yarn test test/index.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --device=${{ matrix.device }}
5152

5253
build-self-hosted:
5354
runs-on: ${{ matrix.machine }}
5455

5556
strategy:
5657
matrix:
58+
device: [best]
5759
machine: [ rpi3-32, rpi3-64, rpi4-32, rpi4-64, rpi5-64, pv-windows-arm64 ]
60+
include:
61+
- device: gpu
62+
machine: pv-linux
63+
- device: gpu
64+
machine: pv-windows
65+
- device: gpu
66+
machine: pv-ios
5867

5968
steps:
6069
- uses: actions/checkout@v3
@@ -63,4 +72,4 @@ jobs:
6372
run: yarn install
6473

6574
- name: Test
66-
run: yarn test test/index.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}}
75+
run: yarn test test/index.test.ts --access_key=${{secrets.PV_VALID_ACCESS_KEY}} --device=${{ matrix.device }}

binding/nodejs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ voice assistants. Orca is:
1616

1717
## Compatibility
1818

19-
- Node.js 16+
19+
- Node.js 18+
2020
- Runs on Linux (x86_64), macOS (x86_64, arm64), Windows (x86_64, arm64), and Raspberry Pi (3, 4, 5).
2121

2222
## Installation

binding/nodejs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@picovoice/orca-node",
3-
"version": "1.2.0",
3+
"version": "2.0.0",
44
"description": "Picovoice Orca Node.js binding",
55
"main": "dist/index.js",
66
"types": "dist/types/index.d.ts",

binding/nodejs/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2024 Picovoice Inc.
2+
// Copyright 2024-2025 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.
@@ -34,6 +34,7 @@ import {
3434
OrcaSynthesizeResult,
3535
OrcaSynthesizeToFileResult,
3636
OrcaStreamSynthesizeResult,
37+
OrcaInputOptions,
3738
OrcaOptions,
3839
} from './types';
3940

@@ -46,6 +47,7 @@ export {
4647
OrcaSynthesizeResult,
4748
OrcaSynthesizeToFileResult,
4849
OrcaStreamSynthesizeResult,
50+
OrcaInputOptions,
4951
OrcaOptions,
5052
OrcaActivationError,
5153
OrcaActivationLimitReachedError,

binding/nodejs/src/orca.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
} from './errors';
2121

2222
import {
23+
OrcaInputOptions,
2324
OrcaOptions,
2425
OrcaSynthesizeParams,
2526
OrcaSynthesizeResult,
@@ -39,6 +40,10 @@ type OrcaStreamResult = {
3940
status: PvStatus;
4041
pcm: Int16Array;
4142
};
43+
type OrcaHardwareDevicesResult = {
44+
hardware_devices: string[];
45+
status: PvStatus;
46+
};
4247

4348
class Stream {
4449
private readonly _stream: any;
@@ -155,6 +160,12 @@ export class Orca {
155160
* @param {string} accessKey AccessKey obtained from Picovoice Console (https://console.picovoice.ai/).
156161
* @param {OrcaOptions} options Optional configuration arguments.
157162
* @param {string} options.modelPath The path to save and use the model from (.pv extension)
163+
* @param {string} options.device String representation of the device (e.g., CPU or GPU) to use for inference.
164+
* If set to `best`, the most suitable device is selected automatically. If set to `gpu`, the engine uses the
165+
* first available GPU device. To select a specific GPU device, set this argument to `gpu:${GPU_INDEX}`, where
166+
* `${GPU_INDEX}` is the index of the target GPU. If set to `cpu`, the engine will run on the CPU with the
167+
* default number of threads. To specify the number of threads, set this argument to `cpu:${NUM_THREADS}`,
168+
* where `${NUM_THREADS}` is the desired number of threads.
158169
* @param {string} options.libraryPath the path to the Orca dynamic library (.node extension)
159170
*/
160171
constructor(accessKey: string, options: OrcaOptions = {}) {
@@ -168,6 +179,7 @@ export class Orca {
168179

169180
const {
170181
modelPath = path.resolve(__dirname, DEFAULT_MODEL_PATH),
182+
device = 'best',
171183
libraryPath = getSystemLibraryPath(),
172184
} = options;
173185

@@ -190,7 +202,7 @@ export class Orca {
190202
try {
191203
pvOrca.set_sdk('nodejs');
192204

193-
orcaHandleAndStatus = pvOrca.init(accessKey, modelPath);
205+
orcaHandleAndStatus = pvOrca.init(accessKey, modelPath, device);
194206
} catch (err: any) {
195207
pvStatusToException(<PvStatus>err.code, err);
196208
}
@@ -465,6 +477,41 @@ export class Orca {
465477
}
466478
}
467479

480+
/**
481+
* Lists all available devices that Orca can use for inference. Each entry in the list can be used
482+
* as the `device` argument when creating an instance of Orca.
483+
* @param {OrcaInputOptions} options Optional configuration arguments.
484+
* @param {string} options.libraryPath the path to the Orca dynamic library (.node extension)
485+
*
486+
* @returns List of all available devices that Orca can use for inference.
487+
*/
488+
static listAvailableDevices(options: OrcaInputOptions = {}): string[] {
489+
const {
490+
libraryPath = getSystemLibraryPath(),
491+
} = options;
492+
493+
const pvOrca = require(libraryPath); // eslint-disable-line
494+
495+
let orcaHardwareDevicesResult: OrcaHardwareDevicesResult | null = null;
496+
try {
497+
orcaHardwareDevicesResult = pvOrca.list_hardware_devices();
498+
} catch (err: any) {
499+
pvStatusToException(<PvStatus>err.code, err);
500+
}
501+
502+
const status = orcaHardwareDevicesResult!.status;
503+
if (status !== PvStatus.SUCCESS) {
504+
const errorObject = pvOrca.get_error_stack();
505+
if (errorObject.status === PvStatus.SUCCESS) {
506+
pvStatusToException(status, 'Orca failed to get available devices', errorObject.message_stack);
507+
} else {
508+
pvStatusToException(status, 'Unable to get Orca error state');
509+
}
510+
}
511+
512+
return orcaHardwareDevicesResult!.hardware_devices;
513+
}
514+
468515
private handlePvStatus(status: PvStatus, message: string): void {
469516
const errorObject = this._pvOrca.get_error_stack();
470517
if (errorObject.status === PvStatus.SUCCESS) {

binding/nodejs/src/types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2024 Picovoice Inc.
2+
Copyright 2024-2025 Picovoice Inc.
33
You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
44
file accompanying this source.
55
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
@@ -34,7 +34,13 @@ export type OrcaSynthesizeToFileResult = OrcaAlignment[]
3434

3535
export type OrcaStreamSynthesizeResult = Int16Array | null
3636

37-
export type OrcaOptions = {
37+
export type OrcaInitOptions = {
3838
modelPath?: string;
39+
device?: string;
40+
};
41+
42+
export type OrcaInputOptions = {
3943
libraryPath?: string;
4044
};
45+
46+
export type OrcaOptions = OrcaInitOptions & OrcaInputOptions;

0 commit comments

Comments
 (0)