Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
8 changes: 4 additions & 4 deletions .github/workflows/web-codestyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ on:
push:
branches: [ main ]
paths:
- '**/web/*.js'
- '**/web/*.ts'
- 'binding/web/*.js'
- 'binding/web/*.ts'
- '.github/workflows/web-codestyle.yml'
pull_request:
branches: [ main, 'v[0-9]+.[0-9]+' ]
paths:
- '**/web/*.js'
- '**/web/*.ts'
- 'binding/web/*.js'
- 'binding/web/*.ts'
- '.github/workflows/web-codestyle.yml'

jobs:
Expand Down
9 changes: 4 additions & 5 deletions .github/workflows/web-demos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18.x, 20.x, 22.x]
node-version: [18.x, 20.x, 22.x, 24.x]

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

# ************** REMOVE AFTER RELEASE ********************
- name: Build Web SDK
run: yarn && yarn copywasm && yarn build
run: yarn install && yarn copywasm && yarn build
working-directory: binding/web

- name: Pre-build dependencies
run: npm install yarn
# ************** REMOVE AFTER RELEASE ********************

- name: Install dependencies
run: yarn install
5 changes: 1 addition & 4 deletions .github/workflows/web-perf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 @@ -55,4 +52,4 @@ jobs:
run: yarn setup-test

- name: Test
run: yarn test-perf --env ACCESS_KEY=${{secrets.PV_VALID_ACCESS_KEY}},NUM_TEST_ITERATIONS=20,ENROLL_PERFORMANCE_THRESHOLD_SEC=${{matrix.enrollPerformanceThresholdSec}},PROCESS_PERFORMANCE_THRESHOLD_SEC=${{matrix.processPerformanceThresholdSec}}
run: yarn test-perf --env ACCESS_KEY=${{secrets.PV_VALID_ACCESS_KEY}},DEVICE=cpu:1,NUM_TEST_ITERATIONS=20,ENROLL_PERFORMANCE_THRESHOLD_SEC=${{matrix.enrollPerformanceThresholdSec}},PROCESS_PERFORMANCE_THRESHOLD_SEC=${{matrix.processPerformanceThresholdSec}}
8 changes: 3 additions & 5 deletions .github/workflows/web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ jobs:

strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
device: [ cpu:1, cpu ]
node-version: [18.x, 20.x, 22.x, 24.x]

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

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

- name: Install dependencies
run: yarn install

Expand All @@ -57,4 +55,4 @@ jobs:
run: yarn setup-test

- name: Test
run: yarn test --env ACCESS_KEY=${{secrets.PV_VALID_ACCESS_KEY}}
run: yarn test --env ACCESS_KEY=${{secrets.PV_VALID_ACCESS_KEY}},DEVICE=${{ matrix.device }}
2 changes: 1 addition & 1 deletion binding/web/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
node_modules
dist
lib/pv_eagle*.wasm
src/lib/*
test/eagle_params.js
test/eagle_params.pv
cypress/fixtures/audio_samples/*.wav
19 changes: 17 additions & 2 deletions binding/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Eagle is an on-device speaker recognition engine. Eagle is:

- Private; All voice processing runs locally.
- Cross-Platform:
- Linux (x86_64), macOS (x86_64, arm64), Windows (x86_64)
- Linux (x86_64), macOS (x86_64, arm64), Windows (x86_64, arm64)
- Android and iOS
- Chrome, Safari, Firefox, and Edge
- Raspberry Pi (3, 4, 5)
Expand All @@ -19,6 +19,21 @@ Eagle is an on-device speaker recognition engine. Eagle is:
- Firefox
- Safari

## Requirements

The Eagle Web Binding uses [SharedArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer).

Include the following headers in the response to enable the use of `SharedArrayBuffers`:

```
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
```

Refer to our [Web demo](../../demo/web) for an example on creating a server with the corresponding response headers.

Browsers that don't support `SharedArrayBuffers` or applications that don't include the required headers will fall back to using standard `ArrayBuffers`. This will disable multithreaded processing.

### Restrictions

IndexedDB is required to use `Eagle` in a worker thread. Browsers without IndexedDB support
Expand Down Expand Up @@ -88,7 +103,7 @@ function getAudioData(numSamples): Int16Array {
let percentage = 0;
while (percentage < 100) {
const audioData = getAudioData(eagleProfiler.minEnrollSamples);

const result: EagleProfilerEnrollResult = await eagleProfiler.enroll(audioData);
if (result.feedback === EagleProfilerEnrollFeedback.AUDIO_OK) {
// audio is good!
Expand Down
9 changes: 9 additions & 0 deletions binding/web/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,14 @@ export default defineConfig({
video: false,
screenshotOnRunFailure: false,
defaultCommandTimeout: 10000,
setupNodeEvents(on) {
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome') {
launchOptions.args.push('--enable-features=SharedArrayBuffer');
}

return launchOptions;
});
},
},
});
2 changes: 1 addition & 1 deletion binding/web/cypress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"types": ["cypress"]
"types": ["cypress", "node"]
},
"include": [
"../test/**/*.ts",
Expand Down
Empty file removed binding/web/lib/.gitkeep
Empty file.
5 changes: 5 additions & 0 deletions binding/web/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ declare module "*.wasm" {
export default content;
}

declare module "*.txt" {
const content: string;
export default content;
}

declare module 'web-worker:*.ts' {
const WorkerFactory: new () => Worker;
export default WorkerFactory;
Expand Down
11 changes: 6 additions & 5 deletions binding/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Eagle Speaker Recognition engine for web browsers (via WebAssembly)",
"author": "Picovoice Inc",
"license": "Apache-2.0",
"version": "1.0.0",
"version": "2.0.0",
"keywords": [
"eagle",
"web",
Expand Down Expand Up @@ -33,11 +33,11 @@
"format": "prettier --write \"**/*.{js,ts,json}\"",
"copywasm": "node scripts/copy_wasm.js",
"setup-test": "node scripts/setup_test.js && npx pvbase64 -i ./test/eagle_params.pv -o ./test/eagle_params.js",
"test": "cypress run --spec test/eagle.test.ts",
"test-perf": "cypress run --spec test/eagle_perf.test.ts"
"test": "cypress run --spec test/eagle.test.ts --browser chrome",
"test-perf": "cypress run --spec test/eagle_perf.test.ts --browser chrome"
},
"dependencies": {
"@picovoice/web-utils": "=1.3.2"
"@picovoice/web-utils": "=1.4.3"
},
"devDependencies": {
"@babel/core": "^7.20.12",
Expand All @@ -49,6 +49,7 @@
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-terser": "^0.4.0",
"@rollup/pluginutils": "^5.0.2",
"@types/emscripten": "1.40.0",
"@types/node": "^18.13.0",
"@typescript-eslint/eslint-plugin": "^5.51.0",
"@typescript-eslint/parser": "^5.51.0",
Expand All @@ -67,6 +68,6 @@
"wasm-feature-detect": "^1.5.0"
},
"engines": {
"node": ">=16"
"node": ">=18"
}
}
2 changes: 1 addition & 1 deletion binding/web/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default {
exclude: '**/node_modules/**',
}),
base64({
include: ['./lib/**/*.wasm']
include: ['./src/lib/*.wasm', './src/lib/*.txt'],
})
],
};
34 changes: 25 additions & 9 deletions binding/web/scripts/copy_wasm.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
const fs = require('fs');
const { join } = require('path');
const fs = require("fs");
const { join, extname } = require("path");

const wasmFiles = ['pv_eagle.wasm', 'pv_eagle_simd.wasm'];
const wasmFiles = [
"pv_eagle_simd.wasm",
"pv_eagle_simd.js",
"pv_eagle_pthread.wasm",
"pv_eagle_pthread.js",
]

console.log('Copying the WASM model...');
console.log("Copying the WASM model...");

const sourceDirectory = join(__dirname, '..', '..', '..', 'lib', 'wasm');
const sourceDirectory = join(
__dirname,
"..",
"..",
"..",
"lib",
"wasm"
);

const outputDirectory = join(__dirname, '..', 'lib');
const outputDirectory = join(__dirname, "..", "src", "lib");

try {
fs.mkdirSync(outputDirectory, { recursive: true });
wasmFiles.forEach(file => {
fs.copyFileSync(join(sourceDirectory, file), join(outputDirectory, file));
});
fs.copyFileSync(join(sourceDirectory, file), join(outputDirectory, file))
const ext = extname(file);
if (ext === ".js") {
fs.copyFileSync(join(sourceDirectory, file), join(outputDirectory, file.replace(ext, ".txt")));
}
})
} catch (error) {
console.error(error);
}

console.log('... Done!');
console.log("... Done!");
Loading