Spaces:
Running
Running
Commit ·
3d610ae
0
Parent(s):
Clean private browser preview
Browse files- .gitattributes +35 -0
- ONNXRUNTIME_LICENSE +21 -0
- README.md +80 -0
- SHERPA_ONNX_LICENSE +202 -0
- THIRD_PARTY_NOTICES.md +21 -0
- app.js +965 -0
- capture-worklet.js +23 -0
- huggingface-logo.svg +37 -0
- index.html +200 -0
- model-config.json +69 -0
- model-files/pnc/config.json +53 -0
- model-files/pnc/pnc.int8.onnx +3 -0
- model-files/pnc/tokenizer.json +0 -0
- model-files/tiny/nemo-transducer-decoder.onnx +3 -0
- model-files/tiny/nemo-transducer-encoder.onnx +3 -0
- model-files/tiny/nemo-transducer-joiner.onnx +3 -0
- model-files/tiny/silero_vad.onnx +3 -0
- model-files/tiny/tokens.txt +45 -0
- model-terms/pnc/LICENSES/CC-BY-4.0.txt +396 -0
- model-terms/pnc/LICENSES/CC0-1.0.txt +121 -0
- model-terms/pnc/LICENSES/CORAL-LICENSE +223 -0
- model-terms/pnc/LICENSES/FTSPEECH-LICENSE.md +8 -0
- model-terms/pnc/MODEL_LICENSE.md +23 -0
- model-terms/pnc/NOTICE +8 -0
- model-terms/tiny/LICENSES/CC-BY-4.0.txt +396 -0
- model-terms/tiny/LICENSES/CORAL-LICENSE +223 -0
- model-terms/tiny/LICENSES/FTSPEECH-LICENSE.md +8 -0
- model-terms/tiny/LICENSES/NVIDIA-OPEN-MODEL-LICENSE.pdf +0 -0
- model-terms/tiny/MODEL_LICENSE.md +23 -0
- model-terms/tiny/NOTICE +8 -0
- ort-wasm-simd-threaded.mjs +59 -0
- ort-wasm-simd-threaded.wasm +3 -0
- ort.wasm.min.js +8 -0
- ort.wasm.min.js.map +0 -0
- pnc-worker.js +326 -0
- sherpa-onnx-asr.js +2011 -0
- sherpa-onnx-vad.js +331 -0
- sherpa-onnx-wasm-main-vad-asr.data +5 -0
- sherpa-onnx-wasm-main-vad-asr.js +1 -0
- sherpa-onnx-wasm-main-vad-asr.wasm +3 -0
- style.css +28 -0
- styles.css +1365 -0
- validation.json +253 -0
- worker.js +466 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
ONNXRUNTIME_LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) Microsoft Corporation
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Ekko Tiny + PnC — Danish speech to text in your browser
|
| 3 |
+
emoji: 🎙️
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: static
|
| 7 |
+
app_file: index.html
|
| 8 |
+
pinned: false
|
| 9 |
+
short_description: On-device Danish speech recognition and punctuation
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
# Ekko v1 Tiny browser demo
|
| 13 |
+
|
| 14 |
+
This Space's code is MIT licensed. The Tiny and PnC model weights have separate
|
| 15 |
+
terms. The private preview includes those terms under `model-terms/`.
|
| 16 |
+
|
| 17 |
+
This static demo transcribes Danish speech locally in the browser with Ekko v1
|
| 18 |
+
Tiny int8, sherpa-onnx WebAssembly, and Silero VAD. Ekko PnC loads separately
|
| 19 |
+
and adds punctuation and capitalization without changing word timestamps.
|
| 20 |
+
Audio and transcripts are never sent to an inference server. The most recent
|
| 21 |
+
20 transcript sessions are saved in the browser's local storage; audio is not
|
| 22 |
+
saved.
|
| 23 |
+
|
| 24 |
+
The model URLs and checksums are pinned in [`model-config.json`](model-config.json).
|
| 25 |
+
The first load downloads Tiny and then PnC. Microphone access requires a secure
|
| 26 |
+
origin and the browser's permission prompt, shown after the app's introductory
|
| 27 |
+
mic dialog. Browser support remains a preview while physical-device and mobile
|
| 28 |
+
checks are completed.
|
| 29 |
+
|
| 30 |
+
The browser and Python CLI pin the same PnC v2 int8 artifact. The Python
|
| 31 |
+
downloader also verifies the accompanying legal files from that revision.
|
| 32 |
+
|
| 33 |
+
## Local preview
|
| 34 |
+
|
| 35 |
+
From the repository root, use the checksum-verified local model cache:
|
| 36 |
+
|
| 37 |
+
```bash
|
| 38 |
+
uv sync --locked
|
| 39 |
+
uv run --no-sync python demo/ekko-tiny-browser/serve_local.py
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
The private PnC v2 files must already be in the Hugging Face cache, or pass a
|
| 43 |
+
local directory explicitly:
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
uv run --no-sync python demo/ekko-tiny-browser/serve_local.py \
|
| 47 |
+
--pnc-dir /path/to/ekko-pnc-v2
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
The preview checks all PnC file sizes and hashes before serving them. A public
|
| 51 |
+
Space cannot fetch the pinned private model revisions until those artifacts
|
| 52 |
+
are released.
|
| 53 |
+
|
| 54 |
+
## Build and deploy
|
| 55 |
+
|
| 56 |
+
```bash
|
| 57 |
+
demo/ekko-tiny-browser/build.sh
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
The build pins sherpa-onnx v1.13.6, Emscripten 4.0.23, and ONNX Runtime Web
|
| 61 |
+
1.29.0. It writes a static site to `demo/ekko-tiny-browser/dist/`; model
|
| 62 |
+
weights are downloaded by the browser and are not committed. Set
|
| 63 |
+
`EKKO_WASM_BUILDER=docker` to use the pinned container image instead of a local
|
| 64 |
+
Emscripten installation.
|
| 65 |
+
|
| 66 |
+
The GitHub workflow builds the Space for demo pull requests and pushes to
|
| 67 |
+
`main`. On pushes to `main`, it also deploys to `RyeAI/ekko-tiny-browser` when
|
| 68 |
+
the repository variable `HF_SPACE_DEPLOY_ENABLED` is `true`. A manual workflow
|
| 69 |
+
run can deploy as well. Deployment requires the `HF_TOKEN` secret and
|
| 70 |
+
anonymously accessible model URLs. The upload mirrors `dist/`, including
|
| 71 |
+
deletions of old generated files.
|
| 72 |
+
|
| 73 |
+
[`validation.json`](validation.json) records the current browser checks and
|
| 74 |
+
remaining device validation. The JavaScript behavior checks can be run with:
|
| 75 |
+
|
| 76 |
+
```bash
|
| 77 |
+
node tests/browser_live_chunking.mjs
|
| 78 |
+
node tests/browser_pnc_sentence_casing.mjs
|
| 79 |
+
node tests/browser_space_signed_assets.mjs
|
| 80 |
+
```
|
SHERPA_ONNX_LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
Apache License
|
| 3 |
+
Version 2.0, January 2004
|
| 4 |
+
http://www.apache.org/licenses/
|
| 5 |
+
|
| 6 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 7 |
+
|
| 8 |
+
1. Definitions.
|
| 9 |
+
|
| 10 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 11 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 12 |
+
|
| 13 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 14 |
+
the copyright owner that is granting the License.
|
| 15 |
+
|
| 16 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 17 |
+
other entities that control, are controlled by, or are under common
|
| 18 |
+
control with that entity. For the purposes of this definition,
|
| 19 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 20 |
+
direction or management of such entity, whether by contract or
|
| 21 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 22 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 23 |
+
|
| 24 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 25 |
+
exercising permissions granted by this License.
|
| 26 |
+
|
| 27 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 28 |
+
including but not limited to software source code, documentation
|
| 29 |
+
source, and configuration files.
|
| 30 |
+
|
| 31 |
+
"Object" form shall mean any form resulting from mechanical
|
| 32 |
+
transformation or translation of a Source form, including but
|
| 33 |
+
not limited to compiled object code, generated documentation,
|
| 34 |
+
and conversions to other media types.
|
| 35 |
+
|
| 36 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 37 |
+
Object form, made available under the License, as indicated by a
|
| 38 |
+
copyright notice that is included in or attached to the work
|
| 39 |
+
(an example is provided in the Appendix below).
|
| 40 |
+
|
| 41 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 42 |
+
form, that is based on (or derived from) the Work and for which the
|
| 43 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 44 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 45 |
+
of this License, Derivative Works shall not include works that remain
|
| 46 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 47 |
+
the Work and Derivative Works thereof.
|
| 48 |
+
|
| 49 |
+
"Contribution" shall mean any work of authorship, including
|
| 50 |
+
the original version of the Work and any modifications or additions
|
| 51 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 52 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
| 53 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 54 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 55 |
+
means any form of electronic, verbal, or written communication sent
|
| 56 |
+
to the Licensor or its representatives, including but not limited to
|
| 57 |
+
communication on electronic mailing lists, source code control systems,
|
| 58 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 59 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 60 |
+
excluding communication that is conspicuously marked or otherwise
|
| 61 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 62 |
+
|
| 63 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 64 |
+
on behalf of whom a Contribution has been received by Licensor and
|
| 65 |
+
subsequently incorporated within the Work.
|
| 66 |
+
|
| 67 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 68 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 69 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 70 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 71 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 72 |
+
Work and such Derivative Works in Source or Object form.
|
| 73 |
+
|
| 74 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 75 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 76 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 77 |
+
(except as stated in this section) patent license to make, have made,
|
| 78 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 79 |
+
where such license applies only to those patent claims licensable
|
| 80 |
+
by such Contributor that are necessarily infringed by their
|
| 81 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 82 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 83 |
+
institute patent litigation against any entity (including a
|
| 84 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 85 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 86 |
+
or contributory patent infringement, then any patent licenses
|
| 87 |
+
granted to You under this License for that Work shall terminate
|
| 88 |
+
as of the date such litigation is filed.
|
| 89 |
+
|
| 90 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 91 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 92 |
+
modifications, and in Source or Object form, provided that You
|
| 93 |
+
meet the following conditions:
|
| 94 |
+
|
| 95 |
+
(a) You must give any other recipients of the Work or
|
| 96 |
+
Derivative Works a copy of this License; and
|
| 97 |
+
|
| 98 |
+
(b) You must cause any modified files to carry prominent notices
|
| 99 |
+
stating that You changed the files; and
|
| 100 |
+
|
| 101 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 102 |
+
that You distribute, all copyright, patent, trademark, and
|
| 103 |
+
attribution notices from the Source form of the Work,
|
| 104 |
+
excluding those notices that do not pertain to any part of
|
| 105 |
+
the Derivative Works; and
|
| 106 |
+
|
| 107 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 108 |
+
distribution, then any Derivative Works that You distribute must
|
| 109 |
+
include a readable copy of the attribution notices contained
|
| 110 |
+
within such NOTICE file, excluding those notices that do not
|
| 111 |
+
pertain to any part of the Derivative Works, in at least one
|
| 112 |
+
of the following places: within a NOTICE text file distributed
|
| 113 |
+
as part of the Derivative Works; within the Source form or
|
| 114 |
+
documentation, if provided along with the Derivative Works; or,
|
| 115 |
+
within a display generated by the Derivative Works, if and
|
| 116 |
+
wherever such third-party notices normally appear. The contents
|
| 117 |
+
of the NOTICE file are for informational purposes only and
|
| 118 |
+
do not modify the License. You may add Your own attribution
|
| 119 |
+
notices within Derivative Works that You distribute, alongside
|
| 120 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 121 |
+
that such additional attribution notices cannot be construed
|
| 122 |
+
as modifying the License.
|
| 123 |
+
|
| 124 |
+
You may add Your own copyright statement to Your modifications and
|
| 125 |
+
may provide additional or different license terms and conditions
|
| 126 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 127 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 128 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 129 |
+
the conditions stated in this License.
|
| 130 |
+
|
| 131 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 132 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 133 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 134 |
+
this License, without any additional terms or conditions.
|
| 135 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 136 |
+
the terms of any separate license agreement you may have executed
|
| 137 |
+
with Licensor regarding such Contributions.
|
| 138 |
+
|
| 139 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 140 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 141 |
+
except as required for reasonable and customary use in describing the
|
| 142 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 143 |
+
|
| 144 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 145 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 146 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 147 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 148 |
+
implied, including, without limitation, any warranties or conditions
|
| 149 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 150 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 151 |
+
appropriateness of using or redistributing the Work and assume any
|
| 152 |
+
risks associated with Your exercise of permissions under this License.
|
| 153 |
+
|
| 154 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 155 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 156 |
+
unless required by applicable law (such as deliberate and grossly
|
| 157 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 158 |
+
liable to You for damages, including any direct, indirect, special,
|
| 159 |
+
incidental, or consequential damages of any character arising as a
|
| 160 |
+
result of this License or out of the use or inability to use the
|
| 161 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 162 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 163 |
+
other commercial damages or losses), even if such Contributor
|
| 164 |
+
has been advised of the possibility of such damages.
|
| 165 |
+
|
| 166 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 167 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 168 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 169 |
+
or other liability obligations and/or rights consistent with this
|
| 170 |
+
License. However, in accepting such obligations, You may act only
|
| 171 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 172 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 173 |
+
defend, and hold each Contributor harmless for any liability
|
| 174 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 175 |
+
of your accepting any such warranty or additional liability.
|
| 176 |
+
|
| 177 |
+
END OF TERMS AND CONDITIONS
|
| 178 |
+
|
| 179 |
+
APPENDIX: How to apply the Apache License to your work.
|
| 180 |
+
|
| 181 |
+
To apply the Apache License to your work, attach the following
|
| 182 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
| 183 |
+
replaced with your own identifying information. (Don't include
|
| 184 |
+
the brackets!) The text should be enclosed in the appropriate
|
| 185 |
+
comment syntax for the file format. We also recommend that a
|
| 186 |
+
file or class name and description of purpose be included on the
|
| 187 |
+
same "printed page" as the copyright notice for easier
|
| 188 |
+
identification within third-party archives.
|
| 189 |
+
|
| 190 |
+
Copyright [yyyy] [name of copyright owner]
|
| 191 |
+
|
| 192 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 193 |
+
you may not use this file except in compliance with the License.
|
| 194 |
+
You may obtain a copy of the License at
|
| 195 |
+
|
| 196 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 197 |
+
|
| 198 |
+
Unless required by applicable law or agreed to in writing, software
|
| 199 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 200 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 201 |
+
See the License for the specific language governing permissions and
|
| 202 |
+
limitations under the License.
|
THIRD_PARTY_NOTICES.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Third-party notices
|
| 2 |
+
|
| 3 |
+
The generated browser bundle contains sherpa-onnx v1.13.6, Copyright Xiaomi
|
| 4 |
+
Corporation and contributors, licensed under Apache-2.0. The build copies its
|
| 5 |
+
full license to `SHERPA_ONNX_LICENSE`.
|
| 6 |
+
|
| 7 |
+
Ekko PnC runs with ONNX Runtime Web 1.29.0, Copyright Microsoft Corporation,
|
| 8 |
+
licensed under the MIT license. The build copies its pinned full license to
|
| 9 |
+
`ONNXRUNTIME_LICENSE`.
|
| 10 |
+
|
| 11 |
+
Live microphone segmentation downloads `silero_vad.onnx` from the sherpa-onnx
|
| 12 |
+
ASR model release. Silero VAD is distributed under the MIT license. See
|
| 13 |
+
<https://github.com/snakers4/silero-vad>.
|
| 14 |
+
|
| 15 |
+
Ekko v1 Tiny model files are downloaded separately from
|
| 16 |
+
<https://huggingface.co/RyeAI/ekko-v1-tiny> and remain subject to that
|
| 17 |
+
repository's `MODEL_LICENSE.md`, `NOTICE`, and bundled third-party terms.
|
| 18 |
+
|
| 19 |
+
Ekko PnC model files are downloaded separately from
|
| 20 |
+
<https://huggingface.co/RyeAI/ekko-pnc> and remain subject to that repository's
|
| 21 |
+
`MODEL_LICENSE.md`, `NOTICE`, and bundled third-party terms.
|
app.js
ADDED
|
@@ -0,0 +1,965 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const elements = {
|
| 2 |
+
app: document.querySelector("#app"),
|
| 3 |
+
ambient: document.querySelector("#ambient"),
|
| 4 |
+
orb: document.querySelector("#orb"),
|
| 5 |
+
ring: document.querySelector(".ring-1"),
|
| 6 |
+
statusDot: document.querySelector("#statusDot"),
|
| 7 |
+
statusText: document.querySelector("#statusText"),
|
| 8 |
+
statusDetail: document.querySelector("#statusDetail"),
|
| 9 |
+
progressTrack: document.querySelector("#progressTrack"),
|
| 10 |
+
progressBar: document.querySelector("#progressBar"),
|
| 11 |
+
recordButton: document.querySelector("#recordButton"),
|
| 12 |
+
recordLabel: document.querySelector("#recordLabel"),
|
| 13 |
+
emptyTranscript: document.querySelector("#emptyTranscript"),
|
| 14 |
+
transcriptPanel: document.querySelector("#transcriptPanel"),
|
| 15 |
+
segments: document.querySelector("#segments"),
|
| 16 |
+
pncStatus: document.querySelector("#pncStatus"),
|
| 17 |
+
themeButton: document.querySelector("#themeButton"),
|
| 18 |
+
copyButton: document.querySelector("#copyButton"),
|
| 19 |
+
downloadButton: document.querySelector("#downloadButton"),
|
| 20 |
+
clearButton: document.querySelector("#clearButton"),
|
| 21 |
+
infoButton: document.querySelector("#infoButton"),
|
| 22 |
+
settingsButton: document.querySelector("#settingsButton"),
|
| 23 |
+
historyList: document.querySelector("#historyList"),
|
| 24 |
+
historyEmpty: document.querySelector("#historyEmpty"),
|
| 25 |
+
clearHistoryButton: document.querySelector("#clearHistoryButton"),
|
| 26 |
+
microphoneDialog: document.querySelector("#microphoneDialog"),
|
| 27 |
+
microphoneTitle: document.querySelector("#microphoneTitle"),
|
| 28 |
+
microphoneDescription: document.querySelector("#microphoneDescription"),
|
| 29 |
+
microphoneHelp: document.querySelector("#microphoneHelp"),
|
| 30 |
+
microphoneCloseButton: document.querySelector("#microphoneCloseButton"),
|
| 31 |
+
microphoneCancelButton: document.querySelector("#microphoneCancelButton"),
|
| 32 |
+
microphoneContinueButton: document.querySelector("#microphoneContinueButton"),
|
| 33 |
+
infoDialog: document.querySelector("#infoDialog"),
|
| 34 |
+
settingsDialog: document.querySelector("#settingsDialog"),
|
| 35 |
+
};
|
| 36 |
+
|
| 37 |
+
const HISTORY_STORAGE_KEY = "ekko-tiny-browser:conversations:v1";
|
| 38 |
+
const THEME_STORAGE_KEY = "ekko-tiny-browser:theme:v1";
|
| 39 |
+
const HISTORY_LIMIT = 20;
|
| 40 |
+
|
| 41 |
+
function signedAsset(path) {
|
| 42 |
+
const url = new URL(path, location.href);
|
| 43 |
+
const signature = new URLSearchParams(location.search).get("__sign");
|
| 44 |
+
if (signature && url.origin === location.origin) url.searchParams.set("__sign", signature);
|
| 45 |
+
return url.href;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
function setTheme(theme) {
|
| 49 |
+
const dark = theme === "dark";
|
| 50 |
+
document.documentElement.dataset.theme = dark ? "dark" : "light";
|
| 51 |
+
elements.themeButton.setAttribute("aria-pressed", String(dark));
|
| 52 |
+
const label = dark ? "Slå lys tilstand til" : "Slå mørk tilstand til";
|
| 53 |
+
elements.themeButton.setAttribute("aria-label", label);
|
| 54 |
+
elements.themeButton.title = label;
|
| 55 |
+
document.querySelector('meta[name="theme-color"]').content = dark ? "#10151c" : "#f3f4f0";
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
let savedTheme;
|
| 59 |
+
try { savedTheme = localStorage.getItem(THEME_STORAGE_KEY); } catch { /* Storage may be disabled. */ }
|
| 60 |
+
setTheme(savedTheme || (matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"));
|
| 61 |
+
|
| 62 |
+
const state = {
|
| 63 |
+
ready: false,
|
| 64 |
+
busy: false,
|
| 65 |
+
recording: false,
|
| 66 |
+
stopping: false,
|
| 67 |
+
checkingMicrophonePermission: false,
|
| 68 |
+
startingRecording: false,
|
| 69 |
+
microphonePermissionGranted: false,
|
| 70 |
+
speechDetected: false,
|
| 71 |
+
pncReady: false,
|
| 72 |
+
pncFailed: false,
|
| 73 |
+
pncInitializationRequested: false,
|
| 74 |
+
pncRequestId: 0,
|
| 75 |
+
nextSegmentId: 0,
|
| 76 |
+
rawSegments: [],
|
| 77 |
+
segments: [],
|
| 78 |
+
previewSegment: null,
|
| 79 |
+
history: [],
|
| 80 |
+
currentConversationId: null,
|
| 81 |
+
currentConversationCreatedAt: null,
|
| 82 |
+
punctuationApplied: false,
|
| 83 |
+
microphone: null,
|
| 84 |
+
audioContext: null,
|
| 85 |
+
sourceNode: null,
|
| 86 |
+
captureNode: null,
|
| 87 |
+
silentGain: null,
|
| 88 |
+
resampler: null,
|
| 89 |
+
captureStopResolve: null,
|
| 90 |
+
captureDrainTimedOut: false,
|
| 91 |
+
level: 0,
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
const worker = new Worker(signedAsset("worker.js?v=20260926-4"));
|
| 95 |
+
const pncWorker = new Worker(signedAsset("pnc-worker.js?v=20260926-4"));
|
| 96 |
+
|
| 97 |
+
function setStatus(text, detail = "", kind = "loading") {
|
| 98 |
+
elements.statusText.textContent = text;
|
| 99 |
+
elements.statusDetail.textContent = detail;
|
| 100 |
+
elements.statusDot.classList.toggle("ready", kind === "ready");
|
| 101 |
+
elements.statusDot.classList.toggle("error", kind === "error");
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
function setProgress(value, complete = false) {
|
| 105 |
+
elements.progressBar.style.width = `${Math.max(0, Math.min(1, value)) * 100}%`;
|
| 106 |
+
elements.progressTrack.classList.toggle("complete", complete);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
function formatBytes(value) {
|
| 110 |
+
if (value < 1024 * 1024) return `${Math.round(value / 1024)} KiB`;
|
| 111 |
+
return `${(value / (1024 * 1024)).toFixed(1)} MiB`;
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
function formatTime(seconds) {
|
| 115 |
+
const safe = Math.max(0, Number(seconds) || 0);
|
| 116 |
+
const minutes = Math.floor(safe / 60);
|
| 117 |
+
const remainder = safe - minutes * 60;
|
| 118 |
+
return `${String(minutes).padStart(2, "0")}:${remainder.toFixed(1).padStart(4, "0")}`;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
function transcriptText() {
|
| 122 |
+
return state.segments.map((segment) => segment.text).filter(Boolean).join(" ").trim();
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
function copySegments(segments) {
|
| 126 |
+
if (!Array.isArray(segments)) return [];
|
| 127 |
+
return segments.map((segment, index) => ({
|
| 128 |
+
id: typeof segment.id === "string" ? segment.id : `segment-${index}`,
|
| 129 |
+
text: String(segment.text || ""),
|
| 130 |
+
rawText: String(segment.rawText || segment.text || ""),
|
| 131 |
+
start: Number.isFinite(segment.start) ? segment.start : 0,
|
| 132 |
+
end: Number.isFinite(segment.end) ? segment.end : 0,
|
| 133 |
+
duration: Number.isFinite(segment.duration) ? segment.duration : 0,
|
| 134 |
+
words: Array.isArray(segment.words)
|
| 135 |
+
? segment.words.map((word) => ({
|
| 136 |
+
text: String(word.text || ""),
|
| 137 |
+
start: Number.isFinite(word.start) ? word.start : 0,
|
| 138 |
+
end: Number.isFinite(word.end) ? word.end : 0,
|
| 139 |
+
}))
|
| 140 |
+
: [],
|
| 141 |
+
}));
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
function readConversationHistory() {
|
| 145 |
+
try {
|
| 146 |
+
const records = JSON.parse(localStorage.getItem(HISTORY_STORAGE_KEY) || "[]");
|
| 147 |
+
if (!Array.isArray(records)) return [];
|
| 148 |
+
return records
|
| 149 |
+
.filter((record) => record && typeof record.id === "string" && Array.isArray(record.segments))
|
| 150 |
+
.slice(0, HISTORY_LIMIT)
|
| 151 |
+
.map((record) => ({
|
| 152 |
+
id: record.id,
|
| 153 |
+
createdAt: String(record.createdAt || new Date().toISOString()),
|
| 154 |
+
updatedAt: String(record.updatedAt || record.createdAt || new Date().toISOString()),
|
| 155 |
+
text: String(record.text || ""),
|
| 156 |
+
rawSegments: copySegments(record.rawSegments || record.segments),
|
| 157 |
+
segments: copySegments(record.segments),
|
| 158 |
+
punctuationApplied: Boolean(record.punctuationApplied),
|
| 159 |
+
}));
|
| 160 |
+
} catch (error) {
|
| 161 |
+
console.warn("Kunne ikke læse lokal samtalehistorik", error);
|
| 162 |
+
return [];
|
| 163 |
+
}
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
function formatHistoryDate(value) {
|
| 167 |
+
const date = new Date(value);
|
| 168 |
+
if (Number.isNaN(date.getTime())) return "Ukendt tidspunkt";
|
| 169 |
+
return new Intl.DateTimeFormat("da-DK", {
|
| 170 |
+
dateStyle: "medium",
|
| 171 |
+
timeStyle: "short",
|
| 172 |
+
}).format(date);
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
function historyDuration(record) {
|
| 176 |
+
return record.segments.reduce((maximum, segment) => Math.max(maximum, segment.end || 0), 0);
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
function renderHistory() {
|
| 180 |
+
const hasHistory = state.history.length > 0;
|
| 181 |
+
const historyLocked = state.recording || state.stopping;
|
| 182 |
+
elements.historyList.replaceChildren();
|
| 183 |
+
elements.historyList.hidden = !hasHistory;
|
| 184 |
+
elements.historyEmpty.hidden = hasHistory;
|
| 185 |
+
elements.clearHistoryButton.disabled = !hasHistory || historyLocked;
|
| 186 |
+
|
| 187 |
+
for (const record of state.history) {
|
| 188 |
+
const item = document.createElement("li");
|
| 189 |
+
item.className = "history-item";
|
| 190 |
+
|
| 191 |
+
const openButton = document.createElement("button");
|
| 192 |
+
openButton.type = "button";
|
| 193 |
+
openButton.className = "history-open";
|
| 194 |
+
openButton.dataset.historyOpen = record.id;
|
| 195 |
+
openButton.disabled = historyLocked;
|
| 196 |
+
|
| 197 |
+
const date = document.createElement("time");
|
| 198 |
+
date.className = "history-date";
|
| 199 |
+
date.dateTime = record.createdAt;
|
| 200 |
+
date.textContent = formatHistoryDate(record.createdAt);
|
| 201 |
+
|
| 202 |
+
const preview = document.createElement("span");
|
| 203 |
+
preview.className = "history-preview";
|
| 204 |
+
preview.textContent = record.text;
|
| 205 |
+
|
| 206 |
+
const meta = document.createElement("span");
|
| 207 |
+
meta.className = "history-meta";
|
| 208 |
+
const wordCount = record.text.split(/\s+/).filter(Boolean).length;
|
| 209 |
+
meta.textContent = `${wordCount} ord · ${formatTime(historyDuration(record))}`;
|
| 210 |
+
openButton.append(date, preview, meta);
|
| 211 |
+
|
| 212 |
+
const deleteButton = document.createElement("button");
|
| 213 |
+
deleteButton.type = "button";
|
| 214 |
+
deleteButton.className = "history-delete";
|
| 215 |
+
deleteButton.dataset.historyDelete = record.id;
|
| 216 |
+
deleteButton.disabled = historyLocked;
|
| 217 |
+
deleteButton.setAttribute("aria-label", `Slet samtale fra ${date.textContent}`);
|
| 218 |
+
deleteButton.title = "Slet samtale";
|
| 219 |
+
deleteButton.textContent = "×";
|
| 220 |
+
item.append(openButton, deleteButton);
|
| 221 |
+
elements.historyList.appendChild(item);
|
| 222 |
+
}
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
function writeConversationHistory() {
|
| 226 |
+
let records = state.history.slice(0, HISTORY_LIMIT);
|
| 227 |
+
while (records.length) {
|
| 228 |
+
try {
|
| 229 |
+
localStorage.setItem(HISTORY_STORAGE_KEY, JSON.stringify(records));
|
| 230 |
+
state.history = records;
|
| 231 |
+
renderHistory();
|
| 232 |
+
return;
|
| 233 |
+
} catch (error) {
|
| 234 |
+
records = records.slice(0, -1);
|
| 235 |
+
if (!records.length) console.warn("Kunne ikke gemme lokal samtalehistorik", error);
|
| 236 |
+
}
|
| 237 |
+
}
|
| 238 |
+
state.history = [];
|
| 239 |
+
try {
|
| 240 |
+
localStorage.removeItem(HISTORY_STORAGE_KEY);
|
| 241 |
+
} catch (error) {
|
| 242 |
+
console.warn("Kunne ikke rydde lokal samtalehistorik", error);
|
| 243 |
+
}
|
| 244 |
+
renderHistory();
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
function persistCurrentConversation() {
|
| 248 |
+
const text = transcriptText();
|
| 249 |
+
if (!state.currentConversationId || !text) return;
|
| 250 |
+
const timestamp = new Date().toISOString();
|
| 251 |
+
const record = {
|
| 252 |
+
id: state.currentConversationId,
|
| 253 |
+
createdAt: state.currentConversationCreatedAt || timestamp,
|
| 254 |
+
updatedAt: timestamp,
|
| 255 |
+
text,
|
| 256 |
+
rawSegments: copySegments(state.rawSegments),
|
| 257 |
+
segments: copySegments(state.segments),
|
| 258 |
+
punctuationApplied: state.punctuationApplied,
|
| 259 |
+
};
|
| 260 |
+
state.history = [record, ...state.history.filter((item) => item.id !== record.id)];
|
| 261 |
+
writeConversationHistory();
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
function loadConversation(recordId) {
|
| 265 |
+
const record = state.history.find((item) => item.id === recordId);
|
| 266 |
+
if (!record || state.recording || state.stopping) return;
|
| 267 |
+
state.pncRequestId += 1;
|
| 268 |
+
state.currentConversationId = record.id;
|
| 269 |
+
state.currentConversationCreatedAt = record.createdAt;
|
| 270 |
+
state.rawSegments = copySegments(record.rawSegments);
|
| 271 |
+
state.punctuationApplied = record.punctuationApplied;
|
| 272 |
+
state.segments = copySegments(record.punctuationApplied ? record.segments : record.rawSegments);
|
| 273 |
+
state.nextSegmentId = state.segments.length;
|
| 274 |
+
elements.app.classList.add("session-active");
|
| 275 |
+
document.body.classList.add("session-active");
|
| 276 |
+
setConversationVisible(true);
|
| 277 |
+
renderTranscript();
|
| 278 |
+
elements.recordLabel.textContent = "Tryk for at optage igen";
|
| 279 |
+
setStatus("Tidligere samtale", formatHistoryDate(record.createdAt), "ready");
|
| 280 |
+
elements.settingsDialog.close();
|
| 281 |
+
if (!record.punctuationApplied) requestPunctuation();
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
function deleteConversation(recordId) {
|
| 285 |
+
if (state.recording || state.stopping) return;
|
| 286 |
+
state.history = state.history.filter((item) => item.id !== recordId);
|
| 287 |
+
if (state.currentConversationId === recordId) state.currentConversationId = null;
|
| 288 |
+
writeConversationHistory();
|
| 289 |
+
}
|
| 290 |
+
|
| 291 |
+
function setConversationVisible(visible) {
|
| 292 |
+
elements.app.classList.toggle("conversation-visible", visible);
|
| 293 |
+
elements.transcriptPanel.classList.toggle("open", visible);
|
| 294 |
+
document.body.classList.toggle("conversation-visible", visible);
|
| 295 |
+
if (visible) {
|
| 296 |
+
requestAnimationFrame(() => {
|
| 297 |
+
elements.transcriptPanel.scrollTop = elements.transcriptPanel.scrollHeight;
|
| 298 |
+
});
|
| 299 |
+
}
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
function renderWords(paragraph, segment, animate) {
|
| 303 |
+
paragraph.replaceChildren();
|
| 304 |
+
const words = Array.isArray(segment.words) && segment.words.length
|
| 305 |
+
? segment.words
|
| 306 |
+
: String(segment.text || "").split(/\s+/).filter(Boolean).map((text) => ({text}));
|
| 307 |
+
words.forEach((word, index) => {
|
| 308 |
+
if (index) paragraph.appendChild(document.createTextNode(" "));
|
| 309 |
+
const span = document.createElement("span");
|
| 310 |
+
span.className = `word${animate ? " reveal-word" : ""}`;
|
| 311 |
+
span.textContent = word.text;
|
| 312 |
+
if (animate) span.style.animationDelay = `${Math.min(index * 45, 180)}ms`;
|
| 313 |
+
paragraph.appendChild(span);
|
| 314 |
+
});
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
function updateWords(paragraph, segment, animate) {
|
| 318 |
+
const words = Array.isArray(segment.words) && segment.words.length
|
| 319 |
+
? segment.words
|
| 320 |
+
: String(segment.text || "").split(/\s+/).filter(Boolean).map((text) => ({text}));
|
| 321 |
+
const spans = Array.from(paragraph.querySelectorAll(".word"));
|
| 322 |
+
if (!animate && spans.length === words.length) {
|
| 323 |
+
spans.forEach((span, index) => {
|
| 324 |
+
const word = words[index];
|
| 325 |
+
span.textContent = word.text;
|
| 326 |
+
});
|
| 327 |
+
return;
|
| 328 |
+
}
|
| 329 |
+
renderWords(paragraph, segment, animate);
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
function renderTranscript({animateNew = false} = {}) {
|
| 333 |
+
const hasText = state.segments.some((segment) => segment.text);
|
| 334 |
+
elements.emptyTranscript.hidden = hasText;
|
| 335 |
+
elements.segments.hidden = !hasText;
|
| 336 |
+
const existing = new Map(
|
| 337 |
+
Array.from(elements.segments.children, (item) => [item.dataset.segmentId, item]),
|
| 338 |
+
);
|
| 339 |
+
for (const segment of state.segments) {
|
| 340 |
+
if (!segment.text) continue;
|
| 341 |
+
let item = existing.get(segment.id);
|
| 342 |
+
const isNew = !item;
|
| 343 |
+
if (isNew) {
|
| 344 |
+
item = document.createElement("li");
|
| 345 |
+
item.className = "segment message user";
|
| 346 |
+
item.dataset.segmentId = segment.id;
|
| 347 |
+
const paragraph = document.createElement("p");
|
| 348 |
+
paragraph.className = "segment-text message-bubble";
|
| 349 |
+
item.append(paragraph);
|
| 350 |
+
elements.segments.appendChild(item);
|
| 351 |
+
}
|
| 352 |
+
item.classList.toggle("preview", segment.id === "live-preview");
|
| 353 |
+
existing.delete(segment.id);
|
| 354 |
+
const paragraph = item.querySelector(".segment-text");
|
| 355 |
+
if (paragraph.dataset.text !== segment.text) {
|
| 356 |
+
updateWords(paragraph, segment, animateNew && isNew);
|
| 357 |
+
paragraph.dataset.text = segment.text;
|
| 358 |
+
}
|
| 359 |
+
}
|
| 360 |
+
for (const item of existing.values()) item.remove();
|
| 361 |
+
|
| 362 |
+
elements.copyButton.disabled = !hasText;
|
| 363 |
+
elements.downloadButton.disabled = !hasText;
|
| 364 |
+
elements.clearButton.disabled = !hasText;
|
| 365 |
+
if (hasText) {
|
| 366 |
+
requestAnimationFrame(() => {
|
| 367 |
+
elements.transcriptPanel.scrollTop = elements.transcriptPanel.scrollHeight;
|
| 368 |
+
});
|
| 369 |
+
}
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
function clearTranscript() {
|
| 373 |
+
state.pncRequestId += 1;
|
| 374 |
+
state.nextSegmentId = 0;
|
| 375 |
+
state.rawSegments = [];
|
| 376 |
+
state.segments = [];
|
| 377 |
+
state.previewSegment = null;
|
| 378 |
+
state.punctuationApplied = false;
|
| 379 |
+
state.currentConversationId = null;
|
| 380 |
+
state.currentConversationCreatedAt = null;
|
| 381 |
+
elements.segments.replaceChildren();
|
| 382 |
+
renderTranscript();
|
| 383 |
+
setConversationVisible(false);
|
| 384 |
+
if (!state.recording) {
|
| 385 |
+
elements.app.classList.remove("session-active");
|
| 386 |
+
document.body.classList.remove("session-active");
|
| 387 |
+
}
|
| 388 |
+
}
|
| 389 |
+
|
| 390 |
+
function ensurePunctuation() {
|
| 391 |
+
if (state.pncInitializationRequested) return;
|
| 392 |
+
state.pncInitializationRequested = true;
|
| 393 |
+
pncWorker.postMessage({type: "init", configUrl: signedAsset("model-config.json")});
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
function requestPunctuation() {
|
| 397 |
+
if (state.pncFailed || !state.rawSegments.length) return;
|
| 398 |
+
ensurePunctuation();
|
| 399 |
+
state.pncRequestId += 1;
|
| 400 |
+
pncWorker.postMessage({
|
| 401 |
+
type: "punctuate",
|
| 402 |
+
requestId: state.pncRequestId,
|
| 403 |
+
configUrl: signedAsset("model-config.json"),
|
| 404 |
+
segments: state.rawSegments,
|
| 405 |
+
});
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
class StreamingLinearResampler {
|
| 409 |
+
constructor(sourceRate, targetRate) {
|
| 410 |
+
this.sourceRate = sourceRate;
|
| 411 |
+
this.targetRate = targetRate;
|
| 412 |
+
this.ratio = sourceRate / targetRate;
|
| 413 |
+
this.tail = new Float32Array(0);
|
| 414 |
+
this.position = 0;
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
process(samples) {
|
| 418 |
+
if (this.sourceRate === this.targetRate) return new Float32Array(samples);
|
| 419 |
+
const input = new Float32Array(this.tail.length + samples.length);
|
| 420 |
+
input.set(this.tail);
|
| 421 |
+
input.set(samples, this.tail.length);
|
| 422 |
+
const output = [];
|
| 423 |
+
while (this.position < input.length - 1) {
|
| 424 |
+
const left = Math.floor(this.position);
|
| 425 |
+
const fraction = this.position - left;
|
| 426 |
+
output.push(input[left] * (1 - fraction) + input[left + 1] * fraction);
|
| 427 |
+
this.position += this.ratio;
|
| 428 |
+
}
|
| 429 |
+
const consumed = Math.min(Math.floor(this.position), Math.max(0, input.length - 1));
|
| 430 |
+
this.tail = input.slice(consumed);
|
| 431 |
+
this.position -= consumed;
|
| 432 |
+
return Float32Array.from(output);
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
reset() {
|
| 436 |
+
this.tail = new Float32Array(0);
|
| 437 |
+
this.position = 0;
|
| 438 |
+
}
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
function appendResult(result, {animate = true} = {}) {
|
| 442 |
+
state.punctuationApplied = false;
|
| 443 |
+
state.previewSegment = null;
|
| 444 |
+
state.segments = state.segments.filter((segment) => segment.id !== "live-preview");
|
| 445 |
+
const segment = {
|
| 446 |
+
...result,
|
| 447 |
+
id: `segment-${state.nextSegmentId}`,
|
| 448 |
+
rawText: result.text,
|
| 449 |
+
};
|
| 450 |
+
state.nextSegmentId += 1;
|
| 451 |
+
state.rawSegments.push(segment);
|
| 452 |
+
state.segments.push({...segment});
|
| 453 |
+
setConversationVisible(true);
|
| 454 |
+
renderTranscript({animateNew: animate});
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
async function startRecording() {
|
| 458 |
+
if (!state.ready || state.recording || state.stopping || state.startingRecording) return;
|
| 459 |
+
state.startingRecording = true;
|
| 460 |
+
elements.recordButton.disabled = true;
|
| 461 |
+
setStatus("Venter på mikrofonadgang", "Vælg Tillad i browserens vindue");
|
| 462 |
+
try {
|
| 463 |
+
state.microphone = await navigator.mediaDevices.getUserMedia({
|
| 464 |
+
audio: {
|
| 465 |
+
channelCount: 1,
|
| 466 |
+
echoCancellation: false,
|
| 467 |
+
noiseSuppression: false,
|
| 468 |
+
autoGainControl: true,
|
| 469 |
+
},
|
| 470 |
+
});
|
| 471 |
+
state.microphonePermissionGranted = true;
|
| 472 |
+
state.audioContext = new AudioContext({sampleRate: 16000});
|
| 473 |
+
if (state.audioContext.state === "suspended") await state.audioContext.resume();
|
| 474 |
+
await state.audioContext.audioWorklet.addModule(signedAsset("capture-worklet.js?v=20260926-4"));
|
| 475 |
+
state.sourceNode = state.audioContext.createMediaStreamSource(state.microphone);
|
| 476 |
+
state.captureNode = new AudioWorkletNode(state.audioContext, "ekko-capture");
|
| 477 |
+
const captureSampleRate = state.audioContext.sampleRate;
|
| 478 |
+
state.resampler = new StreamingLinearResampler(captureSampleRate, 16000);
|
| 479 |
+
state.silentGain = state.audioContext.createGain();
|
| 480 |
+
state.silentGain.gain.value = 0;
|
| 481 |
+
state.captureNode.port.onmessage = (event) => {
|
| 482 |
+
if (event.data?.type === "stopped") {
|
| 483 |
+
state.captureStopResolve?.();
|
| 484 |
+
return;
|
| 485 |
+
}
|
| 486 |
+
if (!state.recording && !state.stopping) return;
|
| 487 |
+
const original = event.data;
|
| 488 |
+
const samples = state.resampler.process(original);
|
| 489 |
+
if (!samples.length) return;
|
| 490 |
+
let energy = 0;
|
| 491 |
+
for (const sample of samples) energy += sample * sample;
|
| 492 |
+
state.level = Math.min(1, Math.sqrt(energy / Math.max(1, samples.length)) * 8);
|
| 493 |
+
worker.postMessage({type: "live-chunk", samples: samples.buffer}, [samples.buffer]);
|
| 494 |
+
};
|
| 495 |
+
clearTranscript();
|
| 496 |
+
state.captureDrainTimedOut = false;
|
| 497 |
+
state.currentConversationId = typeof crypto.randomUUID === "function"
|
| 498 |
+
? crypto.randomUUID()
|
| 499 |
+
: `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
| 500 |
+
state.currentConversationCreatedAt = new Date().toISOString();
|
| 501 |
+
elements.app.classList.add("session-active");
|
| 502 |
+
document.body.classList.add("session-active");
|
| 503 |
+
ensurePunctuation();
|
| 504 |
+
worker.postMessage({type: "live-start"});
|
| 505 |
+
state.recording = true;
|
| 506 |
+
state.sourceNode.connect(state.captureNode);
|
| 507 |
+
state.captureNode.connect(state.silentGain);
|
| 508 |
+
state.silentGain.connect(state.audioContext.destination);
|
| 509 |
+
elements.recordButton.classList.add("recording");
|
| 510 |
+
elements.recordButton.setAttribute("aria-label", "Stop optagelse");
|
| 511 |
+
elements.recordLabel.textContent = "Lytter";
|
| 512 |
+
setStatus("Mikrofon aktiv", "Alt behandles lokalt", "ready");
|
| 513 |
+
} catch (error) {
|
| 514 |
+
state.recording = false;
|
| 515 |
+
if (error.name === "NotAllowedError" || error.name === "PermissionDeniedError") {
|
| 516 |
+
state.microphonePermissionGranted = false;
|
| 517 |
+
}
|
| 518 |
+
state.captureNode?.disconnect();
|
| 519 |
+
state.sourceNode?.disconnect();
|
| 520 |
+
state.silentGain?.disconnect();
|
| 521 |
+
state.microphone?.getTracks().forEach((track) => track.stop());
|
| 522 |
+
await state.audioContext?.close();
|
| 523 |
+
state.captureNode = null;
|
| 524 |
+
state.sourceNode = null;
|
| 525 |
+
state.silentGain = null;
|
| 526 |
+
state.microphone = null;
|
| 527 |
+
state.audioContext = null;
|
| 528 |
+
state.resampler = null;
|
| 529 |
+
state.currentConversationId = null;
|
| 530 |
+
state.currentConversationCreatedAt = null;
|
| 531 |
+
elements.app.classList.remove("session-active");
|
| 532 |
+
document.body.classList.remove("session-active");
|
| 533 |
+
setStatus(
|
| 534 |
+
"Mikrofonen kunne ikke startes",
|
| 535 |
+
error.name === "NotAllowedError" || error.name === "PermissionDeniedError"
|
| 536 |
+
? "Tillad mikrofonen i browserens indstillinger for denne side, og prøv igen"
|
| 537 |
+
: error.message,
|
| 538 |
+
"error",
|
| 539 |
+
);
|
| 540 |
+
} finally {
|
| 541 |
+
state.startingRecording = false;
|
| 542 |
+
elements.recordButton.disabled = !state.ready || state.stopping;
|
| 543 |
+
}
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
async function requestStartRecording() {
|
| 547 |
+
if (!state.ready || state.recording || state.stopping || state.startingRecording
|
| 548 |
+
|| state.checkingMicrophonePermission || elements.microphoneDialog.open) return;
|
| 549 |
+
state.checkingMicrophonePermission = true;
|
| 550 |
+
try {
|
| 551 |
+
let permissionState = null;
|
| 552 |
+
try {
|
| 553 |
+
permissionState = (await navigator.permissions?.query({name: "microphone"}))?.state || null;
|
| 554 |
+
} catch (_) {
|
| 555 |
+
// Some browsers do not expose microphone through the Permissions API.
|
| 556 |
+
}
|
| 557 |
+
if (permissionState === "granted" || (state.microphonePermissionGranted && permissionState !== "denied")) {
|
| 558 |
+
startRecording();
|
| 559 |
+
return;
|
| 560 |
+
}
|
| 561 |
+
const blocked = permissionState === "denied";
|
| 562 |
+
elements.microphoneTitle.textContent = blocked
|
| 563 |
+
? "Mikrofonen er blokeret"
|
| 564 |
+
: "Giv Ekko adgang til din mikrofon";
|
| 565 |
+
elements.microphoneDescription.textContent = blocked
|
| 566 |
+
? "Åbn browserens indstillinger for denne side, og tillad adgang til mikrofonen. Du kan derefter prøve igen."
|
| 567 |
+
: "Mikrofonen bruges kun, mens du optager. Lyd og tekst behandles på din enhed, og lyd gemmes ikke.";
|
| 568 |
+
elements.microphoneHelp.textContent = blocked
|
| 569 |
+
? "Se efter mikrofonikonet eller sideindstillingerne ved adresselinjen."
|
| 570 |
+
: "Når du fortsætter, beder browseren dig om at vælge Tillad.";
|
| 571 |
+
elements.microphoneCancelButton.textContent = blocked ? "Luk" : "Ikke nu";
|
| 572 |
+
elements.microphoneContinueButton.hidden = blocked;
|
| 573 |
+
elements.microphoneDialog.showModal();
|
| 574 |
+
} finally {
|
| 575 |
+
state.checkingMicrophonePermission = false;
|
| 576 |
+
}
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
async function stopRecording() {
|
| 580 |
+
if (!state.recording || state.stopping) return;
|
| 581 |
+
state.recording = false;
|
| 582 |
+
state.stopping = true;
|
| 583 |
+
elements.recordButton.disabled = true;
|
| 584 |
+
elements.recordButton.classList.remove("recording");
|
| 585 |
+
elements.recordButton.setAttribute("aria-label", "Begynd optagelse");
|
| 586 |
+
elements.recordLabel.textContent = "Færdiggør sidste segment";
|
| 587 |
+
if (state.captureNode) {
|
| 588 |
+
const drained = await new Promise((resolve) => {
|
| 589 |
+
const timeout = window.setTimeout(() => resolve(false), 1000);
|
| 590 |
+
state.captureStopResolve = () => {
|
| 591 |
+
window.clearTimeout(timeout);
|
| 592 |
+
resolve(true);
|
| 593 |
+
};
|
| 594 |
+
state.captureNode.port.postMessage({type: "stop"});
|
| 595 |
+
});
|
| 596 |
+
state.captureDrainTimedOut = !drained;
|
| 597 |
+
state.captureStopResolve = null;
|
| 598 |
+
}
|
| 599 |
+
state.captureNode?.disconnect();
|
| 600 |
+
state.sourceNode?.disconnect();
|
| 601 |
+
state.silentGain?.disconnect();
|
| 602 |
+
state.microphone?.getTracks().forEach((track) => track.stop());
|
| 603 |
+
await state.audioContext?.close();
|
| 604 |
+
state.captureNode = null;
|
| 605 |
+
state.sourceNode = null;
|
| 606 |
+
state.silentGain = null;
|
| 607 |
+
state.microphone = null;
|
| 608 |
+
state.audioContext = null;
|
| 609 |
+
state.resampler?.reset();
|
| 610 |
+
state.resampler = null;
|
| 611 |
+
state.level = 0;
|
| 612 |
+
worker.postMessage({type: "live-stop"});
|
| 613 |
+
}
|
| 614 |
+
|
| 615 |
+
worker.onmessage = (event) => {
|
| 616 |
+
const message = event.data || {};
|
| 617 |
+
if (message.type === "model-progress") {
|
| 618 |
+
const percent = Math.round(message.overall * 100);
|
| 619 |
+
setStatus("Henter lokal model", `${percent}% · ${message.file}`);
|
| 620 |
+
setProgress(message.overall);
|
| 621 |
+
} else if (message.type === "ready") {
|
| 622 |
+
state.ready = true;
|
| 623 |
+
elements.recordButton.disabled = false;
|
| 624 |
+
elements.recordLabel.textContent = "Klik for at tale";
|
| 625 |
+
setStatus("Klar", `${formatBytes(message.bytes)} hentet`, "ready");
|
| 626 |
+
setProgress(1, true);
|
| 627 |
+
ensurePunctuation();
|
| 628 |
+
} else if (message.type === "live-result") {
|
| 629 |
+
appendResult(message.result);
|
| 630 |
+
persistCurrentConversation();
|
| 631 |
+
requestPunctuation();
|
| 632 |
+
} else if (message.type === "live-preview") {
|
| 633 |
+
state.previewSegment = {...message.result, id: "live-preview", rawText: message.result.text};
|
| 634 |
+
state.segments = [
|
| 635 |
+
...state.segments.filter((segment) => segment.id !== "live-preview"),
|
| 636 |
+
state.previewSegment,
|
| 637 |
+
];
|
| 638 |
+
setConversationVisible(true);
|
| 639 |
+
renderTranscript();
|
| 640 |
+
} else if (message.type === "live-preview-clear") {
|
| 641 |
+
state.previewSegment = null;
|
| 642 |
+
state.segments = state.segments.filter((segment) => segment.id !== "live-preview");
|
| 643 |
+
renderTranscript();
|
| 644 |
+
} else if (message.type === "speech-state") {
|
| 645 |
+
state.speechDetected = Boolean(message.detected);
|
| 646 |
+
if (state.recording) elements.recordLabel.textContent = state.speechDetected ? "Tale registreret" : "Lytter";
|
| 647 |
+
} else if (message.type === "live-stopped") {
|
| 648 |
+
state.stopping = false;
|
| 649 |
+
elements.recordButton.disabled = false;
|
| 650 |
+
persistCurrentConversation();
|
| 651 |
+
elements.recordLabel.textContent = state.segments.length ? "Tryk for at optage igen" : "Klik for at tale";
|
| 652 |
+
setStatus(
|
| 653 |
+
state.captureDrainTimedOut ? "Optagelsen kan mangle afslutningen" : "Klar",
|
| 654 |
+
state.captureDrainTimedOut
|
| 655 |
+
? "Lydkøen blev ikke bekræftet ved stop"
|
| 656 |
+
: state.segments.length ? "Optagelse færdig" : "Ingen tale fundet",
|
| 657 |
+
state.captureDrainTimedOut ? "error" : "ready",
|
| 658 |
+
);
|
| 659 |
+
if (!state.segments.length) {
|
| 660 |
+
elements.app.classList.remove("session-active");
|
| 661 |
+
document.body.classList.remove("session-active");
|
| 662 |
+
}
|
| 663 |
+
} else if (message.type === "error") {
|
| 664 |
+
state.busy = false;
|
| 665 |
+
elements.recordButton.disabled = !state.ready;
|
| 666 |
+
setStatus("Noget gik galt", message.message, "error");
|
| 667 |
+
}
|
| 668 |
+
};
|
| 669 |
+
|
| 670 |
+
pncWorker.onmessage = (event) => {
|
| 671 |
+
const message = event.data || {};
|
| 672 |
+
if (message.type === "pnc-progress") {
|
| 673 |
+
elements.pncStatus.textContent = `Henter lokalt · ${Math.round(message.overall * 100)}%`;
|
| 674 |
+
} else if (message.type === "pnc-ready") {
|
| 675 |
+
state.pncReady = true;
|
| 676 |
+
elements.pncStatus.textContent = `Klar · ${formatBytes(message.bytes)}`;
|
| 677 |
+
requestPunctuation();
|
| 678 |
+
} else if (message.type === "pnc-result") {
|
| 679 |
+
if (message.requestId !== state.pncRequestId) return;
|
| 680 |
+
state.punctuationApplied = true;
|
| 681 |
+
state.segments = [...message.segments, ...(state.previewSegment ? [state.previewSegment] : [])];
|
| 682 |
+
renderTranscript();
|
| 683 |
+
persistCurrentConversation();
|
| 684 |
+
} else if (message.type === "pnc-error") {
|
| 685 |
+
state.pncFailed = true;
|
| 686 |
+
elements.pncStatus.textContent = "Tegnsætning utilgængelig";
|
| 687 |
+
console.error(message.message);
|
| 688 |
+
}
|
| 689 |
+
};
|
| 690 |
+
|
| 691 |
+
worker.onerror = (event) => {
|
| 692 |
+
console.error(event.message);
|
| 693 |
+
setStatus("WASM-runtime kunne ikke startes", "Genindlæs siden", "error");
|
| 694 |
+
};
|
| 695 |
+
|
| 696 |
+
elements.recordButton.addEventListener("click", () => state.recording ? stopRecording() : requestStartRecording());
|
| 697 |
+
elements.microphoneCloseButton.addEventListener("click", () => elements.microphoneDialog.close());
|
| 698 |
+
elements.microphoneCancelButton.addEventListener("click", () => elements.microphoneDialog.close());
|
| 699 |
+
elements.microphoneContinueButton.addEventListener("click", () => {
|
| 700 |
+
elements.microphoneDialog.close();
|
| 701 |
+
startRecording();
|
| 702 |
+
});
|
| 703 |
+
elements.clearButton.addEventListener("click", clearTranscript);
|
| 704 |
+
elements.historyList.addEventListener("click", (event) => {
|
| 705 |
+
const openButton = event.target.closest("[data-history-open]");
|
| 706 |
+
if (openButton) {
|
| 707 |
+
loadConversation(openButton.dataset.historyOpen);
|
| 708 |
+
return;
|
| 709 |
+
}
|
| 710 |
+
const deleteButton = event.target.closest("[data-history-delete]");
|
| 711 |
+
if (deleteButton) deleteConversation(deleteButton.dataset.historyDelete);
|
| 712 |
+
});
|
| 713 |
+
elements.clearHistoryButton.addEventListener("click", () => {
|
| 714 |
+
if (state.recording || state.stopping) return;
|
| 715 |
+
if (!window.confirm("Slet alle gemte samtaler fra denne browser?")) return;
|
| 716 |
+
state.history = [];
|
| 717 |
+
state.currentConversationId = null;
|
| 718 |
+
writeConversationHistory();
|
| 719 |
+
});
|
| 720 |
+
elements.copyButton.addEventListener("click", async () => {
|
| 721 |
+
await navigator.clipboard.writeText(transcriptText());
|
| 722 |
+
elements.copyButton.textContent = "✓";
|
| 723 |
+
window.setTimeout(() => { elements.copyButton.textContent = "⧉"; }, 1200);
|
| 724 |
+
});
|
| 725 |
+
elements.downloadButton.addEventListener("click", () => {
|
| 726 |
+
const payload = {
|
| 727 |
+
schema: "ekko-browser-transcript-v1",
|
| 728 |
+
model: "Ekko v1 Tiny int8",
|
| 729 |
+
generatedAt: new Date().toISOString(),
|
| 730 |
+
punctuation: state.punctuationApplied ? "Ekko PnC v2 int8" : "pending_or_unavailable",
|
| 731 |
+
text: transcriptText(),
|
| 732 |
+
segments: state.segments,
|
| 733 |
+
};
|
| 734 |
+
const url = URL.createObjectURL(new Blob([JSON.stringify(payload, null, 2)], {type: "application/json"}));
|
| 735 |
+
const link = document.createElement("a");
|
| 736 |
+
link.href = url;
|
| 737 |
+
link.download = "ekko-transcript.json";
|
| 738 |
+
link.click();
|
| 739 |
+
URL.revokeObjectURL(url);
|
| 740 |
+
});
|
| 741 |
+
|
| 742 |
+
elements.themeButton.addEventListener("click", () => {
|
| 743 |
+
const theme = document.documentElement.dataset.theme === "dark" ? "light" : "dark";
|
| 744 |
+
setTheme(theme);
|
| 745 |
+
try { localStorage.setItem(THEME_STORAGE_KEY, theme); } catch { /* Storage may be disabled. */ }
|
| 746 |
+
});
|
| 747 |
+
|
| 748 |
+
elements.infoButton.addEventListener("click", () => elements.infoDialog.showModal());
|
| 749 |
+
elements.settingsButton.addEventListener("click", () => {
|
| 750 |
+
renderHistory();
|
| 751 |
+
elements.settingsDialog.showModal();
|
| 752 |
+
});
|
| 753 |
+
|
| 754 |
+
const ORB_VERTEX_SHADER = `#version 300 es
|
| 755 |
+
in vec2 position;
|
| 756 |
+
void main(){gl_Position=vec4(position,0.0,1.0);}`;
|
| 757 |
+
|
| 758 |
+
const ORB_FRAGMENT_SHADER = `#version 300 es
|
| 759 |
+
precision highp float;
|
| 760 |
+
uniform vec2 iResolution;
|
| 761 |
+
uniform float iTime;
|
| 762 |
+
uniform float uTimeSpeed;
|
| 763 |
+
uniform float uColorBalance;
|
| 764 |
+
uniform float uWarpStrength;
|
| 765 |
+
uniform float uWarpFrequency;
|
| 766 |
+
uniform float uWarpSpeed;
|
| 767 |
+
uniform float uWarpAmplitude;
|
| 768 |
+
uniform float uBlendAngle;
|
| 769 |
+
uniform float uBlendSoftness;
|
| 770 |
+
uniform float uRotationAmount;
|
| 771 |
+
uniform float uNoiseScale;
|
| 772 |
+
uniform float uGrainAmount;
|
| 773 |
+
uniform float uGrainScale;
|
| 774 |
+
uniform float uGrainAnimated;
|
| 775 |
+
uniform float uContrast;
|
| 776 |
+
uniform float uGamma;
|
| 777 |
+
uniform float uSaturation;
|
| 778 |
+
uniform vec2 uCenterOffset;
|
| 779 |
+
uniform float uZoom;
|
| 780 |
+
uniform vec3 uColor1;
|
| 781 |
+
uniform vec3 uColor2;
|
| 782 |
+
uniform vec3 uColor3;
|
| 783 |
+
out vec4 fragColor;
|
| 784 |
+
#define S(a,b,t) smoothstep(a,b,t)
|
| 785 |
+
mat2 Rot(float a){float s=sin(a),c=cos(a);return mat2(c,-s,s,c);}
|
| 786 |
+
vec2 hash(vec2 p){p=vec2(dot(p,vec2(2127.1,81.17)),dot(p,vec2(1269.5,283.37)));return fract(sin(p)*43758.5453);}
|
| 787 |
+
float noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.0-2.0*f);float n=mix(mix(dot(-1.0+2.0*hash(i+vec2(0.0,0.0)),f-vec2(0.0,0.0)),dot(-1.0+2.0*hash(i+vec2(1.0,0.0)),f-vec2(1.0,0.0)),u.x),mix(dot(-1.0+2.0*hash(i+vec2(0.0,1.0)),f-vec2(0.0,1.0)),dot(-1.0+2.0*hash(i+vec2(1.0,1.0)),f-vec2(1.0,1.0)),u.x),u.y);return 0.5+0.5*n;}
|
| 788 |
+
void mainImage(out vec4 o,vec2 C){
|
| 789 |
+
float t=iTime*uTimeSpeed;
|
| 790 |
+
vec2 uv=C/iResolution.xy;
|
| 791 |
+
float ratio=iResolution.x/iResolution.y;
|
| 792 |
+
vec2 tuv=uv-0.5+uCenterOffset;
|
| 793 |
+
tuv/=max(uZoom,0.001);
|
| 794 |
+
float degree=noise(vec2(t*0.1,tuv.x*tuv.y)*uNoiseScale);
|
| 795 |
+
tuv.y*=1.0/ratio;
|
| 796 |
+
tuv*=Rot(radians((degree-0.5)*uRotationAmount+180.0));
|
| 797 |
+
tuv.y*=ratio;
|
| 798 |
+
float frequency=uWarpFrequency;
|
| 799 |
+
float ws=max(uWarpStrength,0.001);
|
| 800 |
+
float amplitude=uWarpAmplitude/ws;
|
| 801 |
+
float warpTime=t*uWarpSpeed;
|
| 802 |
+
tuv.x+=sin(tuv.y*frequency+warpTime)/amplitude;
|
| 803 |
+
tuv.y+=sin(tuv.x*(frequency*1.5)+warpTime)/(amplitude*0.5);
|
| 804 |
+
vec3 colLav=uColor1;vec3 colOrg=uColor2;vec3 colDark=uColor3;
|
| 805 |
+
float b=uColorBalance;float ss=max(uBlendSoftness,0.0);
|
| 806 |
+
mat2 blendRot=Rot(radians(uBlendAngle));
|
| 807 |
+
float blendX=(tuv*blendRot).x;
|
| 808 |
+
float edge0=-0.3-b-ss;float edge1=0.2-b+ss;float v0=0.5-b+ss;float v1=-0.3-b-ss;
|
| 809 |
+
vec3 layer1=mix(colDark,colOrg,S(edge0,edge1,blendX));
|
| 810 |
+
vec3 layer2=mix(colOrg,colLav,S(edge0,edge1,blendX));
|
| 811 |
+
vec3 col=mix(layer1,layer2,S(v0,v1,tuv.y));
|
| 812 |
+
vec2 grainUv=uv*max(uGrainScale,0.001);
|
| 813 |
+
if(uGrainAnimated>0.5){grainUv+=vec2(iTime*0.05);}
|
| 814 |
+
float grain=fract(sin(dot(grainUv,vec2(12.9898,78.233)))*43758.5453);
|
| 815 |
+
col+=(grain-0.5)*uGrainAmount;
|
| 816 |
+
col=(col-0.5)*uContrast+0.5;
|
| 817 |
+
float luma=dot(col,vec3(0.2126,0.7152,0.0722));
|
| 818 |
+
col=mix(vec3(luma),col,uSaturation);
|
| 819 |
+
col=pow(max(col,0.0),vec3(1.0/max(uGamma,0.001)));
|
| 820 |
+
col=clamp(col,0.0,1.0);
|
| 821 |
+
o=vec4(col,1.0);
|
| 822 |
+
}
|
| 823 |
+
void main(){vec4 o=vec4(0.0);mainImage(o,gl_FragCoord.xy);fragColor=o;}`;
|
| 824 |
+
|
| 825 |
+
function hexRgb(hex) {
|
| 826 |
+
const match = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
| 827 |
+
return match
|
| 828 |
+
? new Float32Array([
|
| 829 |
+
parseInt(match[1], 16) / 255,
|
| 830 |
+
parseInt(match[2], 16) / 255,
|
| 831 |
+
parseInt(match[3], 16) / 255,
|
| 832 |
+
])
|
| 833 |
+
: new Float32Array([1, 1, 1]);
|
| 834 |
+
}
|
| 835 |
+
|
| 836 |
+
function initGrainient() {
|
| 837 |
+
const canvas = document.createElement("canvas");
|
| 838 |
+
elements.orb.appendChild(canvas);
|
| 839 |
+
const gl = canvas.getContext("webgl2", {alpha: false, antialias: false});
|
| 840 |
+
if (!gl) return;
|
| 841 |
+
const makeShader = (type, source) => {
|
| 842 |
+
const shader = gl.createShader(type);
|
| 843 |
+
gl.shaderSource(shader, source);
|
| 844 |
+
gl.compileShader(shader);
|
| 845 |
+
return shader;
|
| 846 |
+
};
|
| 847 |
+
const program = gl.createProgram();
|
| 848 |
+
gl.attachShader(program, makeShader(gl.VERTEX_SHADER, ORB_VERTEX_SHADER));
|
| 849 |
+
gl.attachShader(program, makeShader(gl.FRAGMENT_SHADER, ORB_FRAGMENT_SHADER));
|
| 850 |
+
gl.linkProgram(program);
|
| 851 |
+
gl.useProgram(program);
|
| 852 |
+
const buffer = gl.createBuffer();
|
| 853 |
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
| 854 |
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
|
| 855 |
+
const position = gl.getAttribLocation(program, "position");
|
| 856 |
+
gl.enableVertexAttribArray(position);
|
| 857 |
+
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
|
| 858 |
+
const uniform = (name) => gl.getUniformLocation(program, name);
|
| 859 |
+
const uniforms = {
|
| 860 |
+
time: uniform("iTime"), resolution: uniform("iResolution"), timeSpeed: uniform("uTimeSpeed"),
|
| 861 |
+
colorBalance: uniform("uColorBalance"), warpStrength: uniform("uWarpStrength"),
|
| 862 |
+
warpFrequency: uniform("uWarpFrequency"), warpSpeed: uniform("uWarpSpeed"),
|
| 863 |
+
warpAmplitude: uniform("uWarpAmplitude"), blendAngle: uniform("uBlendAngle"),
|
| 864 |
+
blendSoftness: uniform("uBlendSoftness"), rotation: uniform("uRotationAmount"),
|
| 865 |
+
noiseScale: uniform("uNoiseScale"), grainAmount: uniform("uGrainAmount"),
|
| 866 |
+
grainScale: uniform("uGrainScale"), grainAnimated: uniform("uGrainAnimated"),
|
| 867 |
+
contrast: uniform("uContrast"), gamma: uniform("uGamma"), saturation: uniform("uSaturation"),
|
| 868 |
+
center: uniform("uCenterOffset"), zoom: uniform("uZoom"), color1: uniform("uColor1"),
|
| 869 |
+
color2: uniform("uColor2"), color3: uniform("uColor3"),
|
| 870 |
+
};
|
| 871 |
+
gl.uniform1f(uniforms.colorBalance, 0);
|
| 872 |
+
gl.uniform1f(uniforms.blendAngle, 0);
|
| 873 |
+
gl.uniform1f(uniforms.blendSoftness, 0.05);
|
| 874 |
+
gl.uniform1f(uniforms.noiseScale, 2);
|
| 875 |
+
gl.uniform1f(uniforms.grainAmount, 0.045);
|
| 876 |
+
gl.uniform1f(uniforms.grainScale, 2);
|
| 877 |
+
gl.uniform1f(uniforms.grainAnimated, 0);
|
| 878 |
+
gl.uniform1f(uniforms.gamma, 1);
|
| 879 |
+
gl.uniform2f(uniforms.center, 0, 0);
|
| 880 |
+
gl.uniform1f(uniforms.timeSpeed, 0.25);
|
| 881 |
+
gl.uniform1f(uniforms.warpAmplitude, 16);
|
| 882 |
+
gl.uniform1f(uniforms.warpSpeed, 5);
|
| 883 |
+
gl.uniform1f(uniforms.warpStrength, 1);
|
| 884 |
+
gl.uniform1f(uniforms.warpFrequency, 1);
|
| 885 |
+
gl.uniform1f(uniforms.rotation, 100);
|
| 886 |
+
gl.uniform1f(uniforms.zoom, 0.95);
|
| 887 |
+
gl.uniform1f(uniforms.contrast, 1.5);
|
| 888 |
+
gl.uniform1f(uniforms.saturation, 1);
|
| 889 |
+
gl.uniform3fv(uniforms.color1, hexRgb("#27AE60"));
|
| 890 |
+
gl.uniform3fv(uniforms.color2, hexRgb("#8CBFFF"));
|
| 891 |
+
gl.uniform3fv(uniforms.color3, hexRgb("#FFAAAD"));
|
| 892 |
+
|
| 893 |
+
const resize = () => {
|
| 894 |
+
const ratio = Math.min(window.devicePixelRatio || 1, 2);
|
| 895 |
+
const rectangle = elements.orb.getBoundingClientRect();
|
| 896 |
+
canvas.width = Math.ceil(rectangle.width * ratio);
|
| 897 |
+
canvas.height = Math.ceil(rectangle.height * ratio);
|
| 898 |
+
gl.viewport(0, 0, canvas.width, canvas.height);
|
| 899 |
+
gl.uniform2f(uniforms.resolution, canvas.width, canvas.height);
|
| 900 |
+
};
|
| 901 |
+
new ResizeObserver(resize).observe(elements.orb);
|
| 902 |
+
resize();
|
| 903 |
+
|
| 904 |
+
const startedAt = performance.now();
|
| 905 |
+
let animationFrame = 0;
|
| 906 |
+
function render(time) {
|
| 907 |
+
animationFrame = requestAnimationFrame(render);
|
| 908 |
+
gl.uniform1f(uniforms.time, (time - startedAt) * 0.001);
|
| 909 |
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
| 910 |
+
}
|
| 911 |
+
render(performance.now());
|
| 912 |
+
document.addEventListener("visibilitychange", () => {
|
| 913 |
+
if (document.hidden) cancelAnimationFrame(animationFrame);
|
| 914 |
+
else render(performance.now());
|
| 915 |
+
});
|
| 916 |
+
}
|
| 917 |
+
|
| 918 |
+
function resizeCanvas(canvas) {
|
| 919 |
+
const ratio = Math.min(2, window.devicePixelRatio || 1);
|
| 920 |
+
const rectangle = canvas.getBoundingClientRect();
|
| 921 |
+
canvas.width = Math.max(1, Math.round(rectangle.width * ratio));
|
| 922 |
+
canvas.height = Math.max(1, Math.round(rectangle.height * ratio));
|
| 923 |
+
return ratio;
|
| 924 |
+
}
|
| 925 |
+
|
| 926 |
+
let ambientRatio = resizeCanvas(elements.ambient);
|
| 927 |
+
window.addEventListener("resize", () => { ambientRatio = resizeCanvas(elements.ambient); });
|
| 928 |
+
|
| 929 |
+
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
| 930 |
+
let smoothedLevel = 0;
|
| 931 |
+
function drawVisuals(timestamp) {
|
| 932 |
+
const time = reduceMotion ? 0 : timestamp / 1000;
|
| 933 |
+
const target = state.recording ? state.level : 0;
|
| 934 |
+
smoothedLevel += (target - smoothedLevel) * (target > smoothedLevel ? 0.3 : 0.075);
|
| 935 |
+
if (smoothedLevel < 0.006) {
|
| 936 |
+
elements.orb.style.scale = "";
|
| 937 |
+
elements.ring.style.scale = "";
|
| 938 |
+
} else {
|
| 939 |
+
elements.orb.style.scale = String(1 + smoothedLevel * 0.085);
|
| 940 |
+
elements.ring.style.scale = String(1 + smoothedLevel * 0.18);
|
| 941 |
+
}
|
| 942 |
+
const ambient = elements.ambient.getContext("2d");
|
| 943 |
+
const aw = elements.ambient.width;
|
| 944 |
+
const ah = elements.ambient.height;
|
| 945 |
+
ambient.clearRect(0, 0, aw, ah);
|
| 946 |
+
if (state.recording) {
|
| 947 |
+
ambient.beginPath();
|
| 948 |
+
for (let x = 0; x <= aw; x += 12 * ambientRatio) {
|
| 949 |
+
const y = ah * 0.72 + Math.sin(x / (74 * ambientRatio) + time * 3) * (14 + state.level * 28) * ambientRatio;
|
| 950 |
+
x === 0 ? ambient.moveTo(x, y) : ambient.lineTo(x, y);
|
| 951 |
+
}
|
| 952 |
+
ambient.strokeStyle = "rgba(198,12,46,0.18)";
|
| 953 |
+
ambient.lineWidth = ambientRatio;
|
| 954 |
+
ambient.stroke();
|
| 955 |
+
}
|
| 956 |
+
state.level *= 0.9;
|
| 957 |
+
requestAnimationFrame(drawVisuals);
|
| 958 |
+
}
|
| 959 |
+
|
| 960 |
+
state.history = readConversationHistory();
|
| 961 |
+
renderHistory();
|
| 962 |
+
renderTranscript();
|
| 963 |
+
initGrainient();
|
| 964 |
+
requestAnimationFrame(drawVisuals);
|
| 965 |
+
worker.postMessage({type: "init", configUrl: signedAsset("model-config.json")});
|
capture-worklet.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class EkkoCaptureProcessor extends AudioWorkletProcessor {
|
| 2 |
+
constructor() {
|
| 3 |
+
super();
|
| 4 |
+
this.stopped = false;
|
| 5 |
+
this.port.onmessage = (event) => {
|
| 6 |
+
if (event.data?.type !== "stop") return;
|
| 7 |
+
this.stopped = true;
|
| 8 |
+
this.port.postMessage({type: "stopped"});
|
| 9 |
+
};
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
process(inputs) {
|
| 13 |
+
if (this.stopped) return true;
|
| 14 |
+
const input = inputs[0];
|
| 15 |
+
if (input && input[0]) {
|
| 16 |
+
const samples = new Float32Array(input[0]);
|
| 17 |
+
this.port.postMessage(samples, [samples.buffer]);
|
| 18 |
+
}
|
| 19 |
+
return true;
|
| 20 |
+
}
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
registerProcessor("ekko-capture", EkkoCaptureProcessor);
|
huggingface-logo.svg
ADDED
|
|
index.html
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
+
<html lang="da">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8" />
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| 6 |
+
<meta
|
| 7 |
+
name="description"
|
| 8 |
+
content="Lokal dansk talegenkendelse i browseren med Ekko v1 Tiny."
|
| 9 |
+
/>
|
| 10 |
+
<meta name="theme-color" content="#f3f4f0" />
|
| 11 |
+
<title>Ekko v1 Tiny | Rye AI</title>
|
| 12 |
+
<link rel="icon" href="data:," />
|
| 13 |
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
| 14 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
| 15 |
+
<link
|
| 16 |
+
href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700&display=swap"
|
| 17 |
+
rel="stylesheet"
|
| 18 |
+
/>
|
| 19 |
+
<link rel="stylesheet" href="styles.css?v=20260926-9" />
|
| 20 |
+
</head>
|
| 21 |
+
<body>
|
| 22 |
+
<canvas id="ambient" aria-hidden="true"></canvas>
|
| 23 |
+
|
| 24 |
+
<header class="topbar">
|
| 25 |
+
<a class="brand" href="https://rye-ai.com" target="_blank" rel="noreferrer">
|
| 26 |
+
<span class="brand-mark">Rye AI</span>
|
| 27 |
+
<span class="brand-divider">/</span>
|
| 28 |
+
<span class="product-name">EKKO-TINY-V1</span>
|
| 29 |
+
</a>
|
| 30 |
+
<div class="topbar-actions">
|
| 31 |
+
<button class="circle-button theme-button" id="themeButton" type="button" aria-label="Slå mørk tilstand til" title="Slå mørk tilstand til" aria-pressed="false">
|
| 32 |
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.2 15.5A8.5 8.5 0 0 1 8.5 3.8 8.5 8.5 0 1 0 20.2 15.5Z" /></svg>
|
| 33 |
+
</button>
|
| 34 |
+
<button class="circle-button" id="infoButton" aria-label="Om demoen" title="Om demoen">
|
| 35 |
+
<span aria-hidden="true">i</span>
|
| 36 |
+
</button>
|
| 37 |
+
<button class="circle-button sliders" id="settingsButton" aria-label="Indstillinger" title="Indstillinger">
|
| 38 |
+
<span aria-hidden="true"></span>
|
| 39 |
+
</button>
|
| 40 |
+
</div>
|
| 41 |
+
</header>
|
| 42 |
+
|
| 43 |
+
<main class="scene" id="app">
|
| 44 |
+
<section class="intro" aria-labelledby="pageTitle">
|
| 45 |
+
<h1 id="pageTitle">Sig det til Ekko</h1>
|
| 46 |
+
<p class="intro-copy">
|
| 47 |
+
Dansk tale til tekst - direkte i din browser.<br />
|
| 48 |
+
Ingen lyd eller tekst forlader din enhed.
|
| 49 |
+
</p>
|
| 50 |
+
</section>
|
| 51 |
+
|
| 52 |
+
<section class="workspace" aria-label="Transskription">
|
| 53 |
+
<div class="model-status" aria-live="polite">
|
| 54 |
+
<span class="status-dot" id="statusDot"></span>
|
| 55 |
+
<span id="statusText">Forbereder lokal model</span>
|
| 56 |
+
<span id="statusDetail"></span>
|
| 57 |
+
</div>
|
| 58 |
+
<div class="progress-track" id="progressTrack" aria-hidden="true">
|
| 59 |
+
<span id="progressBar"></span>
|
| 60 |
+
</div>
|
| 61 |
+
|
| 62 |
+
<div id="livePanel" class="mode-panel">
|
| 63 |
+
<button class="stage" id="recordButton" disabled aria-label="Begynd optagelse">
|
| 64 |
+
<span class="ring ring-1" aria-hidden="true"></span>
|
| 65 |
+
<span class="orb" id="orb" aria-hidden="true"></span>
|
| 66 |
+
</button>
|
| 67 |
+
<div class="stage-copy">
|
| 68 |
+
<p class="stage-label" id="recordLabel">Modellen indlæses</p>
|
| 69 |
+
<p class="stage-note">Tekst vises løbende, mens du taler</p>
|
| 70 |
+
</div>
|
| 71 |
+
</div>
|
| 72 |
+
</section>
|
| 73 |
+
|
| 74 |
+
<section class="transcript" id="transcriptPanel" aria-labelledby="transcriptTitle">
|
| 75 |
+
<h2 id="transcriptTitle" hidden>Transskription</h2>
|
| 76 |
+
<div class="empty-transcript" id="emptyTranscript">
|
| 77 |
+
Din transskription vises her.
|
| 78 |
+
</div>
|
| 79 |
+
<ol class="segments" id="segments" aria-live="polite"></ol>
|
| 80 |
+
</section>
|
| 81 |
+
<div class="transcript-heading" aria-label="Transskriptionshandlinger">
|
| 82 |
+
<div class="transcript-actions">
|
| 83 |
+
<button class="icon-button" id="copyButton" disabled title="Kopiér tekst" aria-label="Kopiér tekst">⧉</button>
|
| 84 |
+
<button class="icon-button" id="downloadButton" disabled title="Hent JSON" aria-label="Hent JSON">↓</button>
|
| 85 |
+
<button class="icon-button" id="clearButton" disabled title="Ryd" aria-label="Ryd">×</button>
|
| 86 |
+
</div>
|
| 87 |
+
</div>
|
| 88 |
+
</main>
|
| 89 |
+
|
| 90 |
+
<footer>
|
| 91 |
+
<span>Ekko v1 Tiny + PnC · int8 · CPU/WASM</span>
|
| 92 |
+
<nav class="footer-links" aria-label="Modeller, kildekode og Rye AI">
|
| 93 |
+
<a class="footer-chip footer-chip--tiny" href="https://huggingface.co/RyeAI/ekko-v1-tiny" target="_blank" rel="noreferrer" aria-label="Ekko v1 Tiny på Hugging Face">
|
| 94 |
+
<img src="huggingface-logo.svg" width="16" height="16" alt="" aria-hidden="true" />
|
| 95 |
+
<span>Tiny</span>
|
| 96 |
+
</a>
|
| 97 |
+
<a class="footer-chip footer-chip--pnc" href="https://huggingface.co/RyeAI/ekko-pnc" target="_blank" rel="noreferrer" aria-label="Ekko PnC på Hugging Face">
|
| 98 |
+
<img src="huggingface-logo.svg" width="16" height="16" alt="" aria-hidden="true" />
|
| 99 |
+
<span>PnC</span>
|
| 100 |
+
</a>
|
| 101 |
+
<a class="footer-chip footer-chip--github" href="https://github.com/Rye-A1/ekko-danish-stt" target="_blank" rel="noreferrer" aria-label="Ekko kildekode på GitHub">
|
| 102 |
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
| 103 |
+
<path d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 19 4.77 5.07 5.07 0 0 0 18.91 1S17.73.65 15 2.48a13.38 13.38 0 0 0-7 0C5.27.65 4.09 1 4.09 1A5.07 5.07 0 0 0 4 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 8 18.13V22" />
|
| 104 |
+
</svg>
|
| 105 |
+
<span>GitHub</span>
|
| 106 |
+
</a>
|
| 107 |
+
<a class="footer-chip footer-chip--linkedin" href="https://www.linkedin.com/company/rye-a1" target="_blank" rel="noreferrer" aria-label="Rye AI på LinkedIn">
|
| 108 |
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
| 109 |
+
<path d="M8 11v5M8 8v.01M12 16v-5M16 16v-3a2 2 0 1 0-4 0M3 7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4v10a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V7" />
|
| 110 |
+
</svg>
|
| 111 |
+
<span>LinkedIn</span>
|
| 112 |
+
</a>
|
| 113 |
+
</nav>
|
| 114 |
+
</footer>
|
| 115 |
+
|
| 116 |
+
<dialog id="microphoneDialog" aria-labelledby="microphoneTitle" aria-describedby="microphoneDescription">
|
| 117 |
+
<div class="microphone-dialog-content">
|
| 118 |
+
<button class="dialog-close" id="microphoneCloseButton" type="button" aria-label="Luk">×</button>
|
| 119 |
+
<div class="microphone-icon" aria-hidden="true">
|
| 120 |
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
| 121 |
+
<rect x="9" y="2" width="6" height="12" rx="3" />
|
| 122 |
+
<path d="M5 10a7 7 0 0 0 14 0M12 17v5m-4 0h8" />
|
| 123 |
+
</svg>
|
| 124 |
+
</div>
|
| 125 |
+
<p class="section-label">FØR DU BEGYNDER</p>
|
| 126 |
+
<h2 id="microphoneTitle">Giv Ekko adgang til din mikrofon</h2>
|
| 127 |
+
<p id="microphoneDescription">Mikrofonen bruges kun, mens du optager. Lyd og tekst behandles på din enhed, og lyd gemmes ikke.</p>
|
| 128 |
+
<p class="microphone-browser-note" id="microphoneHelp">Når du fortsætter, beder browseren dig om at vælge Tillad.</p>
|
| 129 |
+
<div class="microphone-actions">
|
| 130 |
+
<button class="microphone-secondary" id="microphoneCancelButton" type="button">Ikke nu</button>
|
| 131 |
+
<button class="microphone-primary" id="microphoneContinueButton" type="button">Fortsæt</button>
|
| 132 |
+
</div>
|
| 133 |
+
</div>
|
| 134 |
+
</dialog>
|
| 135 |
+
|
| 136 |
+
<dialog id="infoDialog">
|
| 137 |
+
<form method="dialog">
|
| 138 |
+
<button class="dialog-close" aria-label="Luk">×</button>
|
| 139 |
+
<p class="section-label">OM DEMOEN</p>
|
| 140 |
+
<h2>Alt sker lokalt</h2>
|
| 141 |
+
<p>
|
| 142 |
+
Modellen hentes ved første besøg og kører derefter i browserens
|
| 143 |
+
WebAssembly-runtime. Ingen lyd, tekst eller brugsdata forlader din browser.
|
| 144 |
+
</p>
|
| 145 |
+
<dl>
|
| 146 |
+
<div>
|
| 147 |
+
<dt>Talegenkendelse</dt>
|
| 148 |
+
<dd>
|
| 149 |
+
<a class="model-link" href="https://huggingface.co/RyeAI/ekko-v1-tiny" target="_blank" rel="noreferrer">
|
| 150 |
+
Ekko v1 Tiny int8
|
| 151 |
+
<svg class="lucide lucide-chevron-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
| 152 |
+
<path d="m9 18 6-6-6-6" />
|
| 153 |
+
</svg>
|
| 154 |
+
</a>
|
| 155 |
+
</dd>
|
| 156 |
+
</div>
|
| 157 |
+
<div>
|
| 158 |
+
<dt>Tegnsætning</dt>
|
| 159 |
+
<dd>
|
| 160 |
+
<a class="model-link" href="https://huggingface.co/RyeAI/ekko-pnc" target="_blank" rel="noreferrer">
|
| 161 |
+
Ekko PnC v2 int8
|
| 162 |
+
<svg class="lucide lucide-chevron-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
| 163 |
+
<path d="m9 18 6-6-6-6" />
|
| 164 |
+
</svg>
|
| 165 |
+
</a>
|
| 166 |
+
</dd>
|
| 167 |
+
</div>
|
| 168 |
+
<div><dt>Runtime</dt><dd>sherpa-onnx + ONNX Runtime</dd></div>
|
| 169 |
+
<div><dt>Modelstørrelse</dt><dd>ca. 153 MiB samlet</dd></div>
|
| 170 |
+
<div><dt>Kildekode</dt><dd><a class="model-link" href="https://github.com/Rye-A1/ekko-danish-stt" target="_blank" rel="noreferrer">Ekko på GitHub</a></dd></div>
|
| 171 |
+
</dl>
|
| 172 |
+
</form>
|
| 173 |
+
</dialog>
|
| 174 |
+
|
| 175 |
+
<dialog id="settingsDialog">
|
| 176 |
+
<form method="dialog">
|
| 177 |
+
<button class="dialog-close" aria-label="Luk">×</button>
|
| 178 |
+
<p class="section-label">INDSTILLINGER</p>
|
| 179 |
+
<h2>Transskription</h2>
|
| 180 |
+
<div class="setting-row">
|
| 181 |
+
<span><strong>Tegnsætning</strong><small id="pncStatus">Hentes i baggrunden</small></span>
|
| 182 |
+
</div>
|
| 183 |
+
<section class="history-section" aria-labelledby="historyTitle">
|
| 184 |
+
<div class="history-title-row">
|
| 185 |
+
<div>
|
| 186 |
+
<p class="section-label">HISTORIK</p>
|
| 187 |
+
<h2 id="historyTitle">Tidligere samtaler</h2>
|
| 188 |
+
</div>
|
| 189 |
+
<button class="history-clear" id="clearHistoryButton" type="button" disabled>Ryd alle</button>
|
| 190 |
+
</div>
|
| 191 |
+
<p>Kun transskriptioner gemmes i denne browser. Lyd gemmes ikke.</p>
|
| 192 |
+
<p class="history-empty" id="historyEmpty">Ingen gemte samtaler endnu.</p>
|
| 193 |
+
<ol class="history-list" id="historyList" hidden></ol>
|
| 194 |
+
</section>
|
| 195 |
+
</form>
|
| 196 |
+
</dialog>
|
| 197 |
+
|
| 198 |
+
<script src="app.js?v=20260926-4" type="module"></script>
|
| 199 |
+
</body>
|
| 200 |
+
</html>
|
model-config.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "ekko-browser-model-v1",
|
| 3 |
+
"name": "Ekko v1 Tiny int8",
|
| 4 |
+
"repository": "RyeAI/ekko-v1-tiny",
|
| 5 |
+
"revision": "d89411a3b893a1460ef0d46ef983b128028aa6b0",
|
| 6 |
+
"runtime": "sherpa-onnx 1.13.6 WebAssembly",
|
| 7 |
+
"sampleRate": 16000,
|
| 8 |
+
"featureDim": 80,
|
| 9 |
+
"modelType": "nemo_transducer",
|
| 10 |
+
"pnc": {
|
| 11 |
+
"name": "Ekko PnC v2 int8",
|
| 12 |
+
"repository": "RyeAI/ekko-pnc",
|
| 13 |
+
"revision": "d8ea368b1c442efdfea83aa0ac2d35e7715395ee",
|
| 14 |
+
"runtime": "onnxruntime-web 1.29.0",
|
| 15 |
+
"maxLength": 256,
|
| 16 |
+
"files": [
|
| 17 |
+
{
|
| 18 |
+
"path": "pnc.int8.onnx",
|
| 19 |
+
"url": "model-files/pnc/pnc.int8.onnx?sha256=46bb979d409731872f10b6cb71298594595f16368d2aec2fcaf94d87b4266527",
|
| 20 |
+
"sha256": "46bb979d409731872f10b6cb71298594595f16368d2aec2fcaf94d87b4266527",
|
| 21 |
+
"bytes": 22424741
|
| 22 |
+
},
|
| 23 |
+
{
|
| 24 |
+
"path": "tokenizer.json",
|
| 25 |
+
"url": "model-files/pnc/tokenizer.json?sha256=a1e0d43ee307ad7a1ccc23e6e5398d877a68ca7f576067ac507625a0d50e9502",
|
| 26 |
+
"sha256": "a1e0d43ee307ad7a1ccc23e6e5398d877a68ca7f576067ac507625a0d50e9502",
|
| 27 |
+
"bytes": 2301084
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
"path": "config.json",
|
| 31 |
+
"url": "model-files/pnc/config.json?sha256=dc655c46f69eeb15dd43786ad58fb5862cc794b36cc9d2c426ab5bc4b01f23ca",
|
| 32 |
+
"sha256": "dc655c46f69eeb15dd43786ad58fb5862cc794b36cc9d2c426ab5bc4b01f23ca",
|
| 33 |
+
"bytes": 1062
|
| 34 |
+
}
|
| 35 |
+
]
|
| 36 |
+
},
|
| 37 |
+
"files": [
|
| 38 |
+
{
|
| 39 |
+
"path": "nemo-transducer-encoder.onnx",
|
| 40 |
+
"url": "model-files/tiny/nemo-transducer-encoder.onnx?sha256=e7ee366cb92cbf5b14beee01f04245293185ec3b271bb12acd7715e94d1f4cf2",
|
| 41 |
+
"sha256": "e7ee366cb92cbf5b14beee01f04245293185ec3b271bb12acd7715e94d1f4cf2",
|
| 42 |
+
"bytes": 131201109
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"path": "nemo-transducer-decoder.onnx",
|
| 46 |
+
"url": "model-files/tiny/nemo-transducer-decoder.onnx?sha256=09beaa741719190c0052566a0785de0de212f1b89b0e8e8293fe08e1d0ebb352",
|
| 47 |
+
"sha256": "09beaa741719190c0052566a0785de0de212f1b89b0e8e8293fe08e1d0ebb352",
|
| 48 |
+
"bytes": 3328663
|
| 49 |
+
},
|
| 50 |
+
{
|
| 51 |
+
"path": "nemo-transducer-joiner.onnx",
|
| 52 |
+
"url": "model-files/tiny/nemo-transducer-joiner.onnx?sha256=894007e36304dcc24584e2dbbe4dff9b47088fd6e9c0763f38344b270a2ccc72",
|
| 53 |
+
"sha256": "894007e36304dcc24584e2dbbe4dff9b47088fd6e9c0763f38344b270a2ccc72",
|
| 54 |
+
"bytes": 777055
|
| 55 |
+
},
|
| 56 |
+
{
|
| 57 |
+
"path": "tokens.txt",
|
| 58 |
+
"url": "model-files/tiny/tokens.txt?sha256=f6240fdbb496236106174a08b086a1a59a209aea50c5468b5233f0da9e62780b",
|
| 59 |
+
"sha256": "f6240fdbb496236106174a08b086a1a59a209aea50c5468b5233f0da9e62780b",
|
| 60 |
+
"bytes": 231
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"path": "silero_vad.onnx",
|
| 64 |
+
"url": "model-files/tiny/silero_vad.onnx?sha256=9e2449e1087496d8d4caba907f23e0bd3f78d91fa552479bb9c23ac09cbb1fd6",
|
| 65 |
+
"sha256": "9e2449e1087496d8d4caba907f23e0bd3f78d91fa552479bb9c23ac09cbb1fd6",
|
| 66 |
+
"bytes": 643854
|
| 67 |
+
}
|
| 68 |
+
]
|
| 69 |
+
}
|
model-files/pnc/config.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"ElectraForTokenClassification"
|
| 4 |
+
],
|
| 5 |
+
"attention_probs_dropout_prob": 0.1,
|
| 6 |
+
"classifier_dropout": null,
|
| 7 |
+
"dtype": "float32",
|
| 8 |
+
"embedding_size": 128,
|
| 9 |
+
"hidden_act": "gelu",
|
| 10 |
+
"hidden_dropout_prob": 0.1,
|
| 11 |
+
"hidden_size": 256,
|
| 12 |
+
"id2label": {
|
| 13 |
+
"0": "O",
|
| 14 |
+
"1": "O|U",
|
| 15 |
+
"2": ",",
|
| 16 |
+
"3": ",|U",
|
| 17 |
+
"4": ".",
|
| 18 |
+
"5": ".|U",
|
| 19 |
+
"6": "?",
|
| 20 |
+
"7": "?|U",
|
| 21 |
+
"8": "!",
|
| 22 |
+
"9": "!|U"
|
| 23 |
+
},
|
| 24 |
+
"initializer_range": 0.02,
|
| 25 |
+
"intermediate_size": 1024,
|
| 26 |
+
"label2id": {
|
| 27 |
+
"!": 8,
|
| 28 |
+
"!|U": 9,
|
| 29 |
+
",": 2,
|
| 30 |
+
",|U": 3,
|
| 31 |
+
".": 4,
|
| 32 |
+
".|U": 5,
|
| 33 |
+
"?": 6,
|
| 34 |
+
"?|U": 7,
|
| 35 |
+
"O": 0,
|
| 36 |
+
"O|U": 1
|
| 37 |
+
},
|
| 38 |
+
"layer_norm_eps": 1e-12,
|
| 39 |
+
"max_position_embeddings": 512,
|
| 40 |
+
"model_type": "electra",
|
| 41 |
+
"num_attention_heads": 4,
|
| 42 |
+
"num_hidden_layers": 12,
|
| 43 |
+
"pad_token_id": 0,
|
| 44 |
+
"position_embedding_type": "absolute",
|
| 45 |
+
"summary_activation": "gelu",
|
| 46 |
+
"summary_last_dropout": 0.1,
|
| 47 |
+
"summary_type": "first",
|
| 48 |
+
"summary_use_proj": true,
|
| 49 |
+
"transformers_version": "4.57.6",
|
| 50 |
+
"type_vocab_size": 2,
|
| 51 |
+
"use_cache": true,
|
| 52 |
+
"vocab_size": 96105
|
| 53 |
+
}
|
model-files/pnc/pnc.int8.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:46bb979d409731872f10b6cb71298594595f16368d2aec2fcaf94d87b4266527
|
| 3 |
+
size 22424741
|
model-files/pnc/tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model-files/tiny/nemo-transducer-decoder.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:09beaa741719190c0052566a0785de0de212f1b89b0e8e8293fe08e1d0ebb352
|
| 3 |
+
size 3328663
|
model-files/tiny/nemo-transducer-encoder.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e7ee366cb92cbf5b14beee01f04245293185ec3b271bb12acd7715e94d1f4cf2
|
| 3 |
+
size 131201109
|
model-files/tiny/nemo-transducer-joiner.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:894007e36304dcc24584e2dbbe4dff9b47088fd6e9c0763f38344b270a2ccc72
|
| 3 |
+
size 777055
|
model-files/tiny/silero_vad.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9e2449e1087496d8d4caba907f23e0bd3f78d91fa552479bb9c23ac09cbb1fd6
|
| 3 |
+
size 643854
|
model-files/tiny/tokens.txt
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<unk> 0
|
| 2 |
+
er 1
|
| 3 |
+
▁ 2
|
| 4 |
+
e 3
|
| 5 |
+
r 4
|
| 6 |
+
n 5
|
| 7 |
+
t 6
|
| 8 |
+
i 7
|
| 9 |
+
a 8
|
| 10 |
+
s 9
|
| 11 |
+
d 10
|
| 12 |
+
l 11
|
| 13 |
+
o 12
|
| 14 |
+
g 13
|
| 15 |
+
m 14
|
| 16 |
+
k 15
|
| 17 |
+
f 16
|
| 18 |
+
v 17
|
| 19 |
+
b 18
|
| 20 |
+
u 19
|
| 21 |
+
h 20
|
| 22 |
+
p 21
|
| 23 |
+
å 22
|
| 24 |
+
ø 23
|
| 25 |
+
æ 24
|
| 26 |
+
y 25
|
| 27 |
+
j 26
|
| 28 |
+
c 27
|
| 29 |
+
1 28
|
| 30 |
+
0 29
|
| 31 |
+
9 30
|
| 32 |
+
2 31
|
| 33 |
+
8 32
|
| 34 |
+
w 33
|
| 35 |
+
7 34
|
| 36 |
+
6 35
|
| 37 |
+
5 36
|
| 38 |
+
4 37
|
| 39 |
+
3 38
|
| 40 |
+
z 39
|
| 41 |
+
x 40
|
| 42 |
+
é 41
|
| 43 |
+
q 42
|
| 44 |
+
ü 43
|
| 45 |
+
<blk> 44
|
model-terms/pnc/LICENSES/CC-BY-4.0.txt
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Attribution 4.0 International
|
| 2 |
+
|
| 3 |
+
=======================================================================
|
| 4 |
+
|
| 5 |
+
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
| 6 |
+
does not provide legal services or legal advice. Distribution of
|
| 7 |
+
Creative Commons public licenses does not create a lawyer-client or
|
| 8 |
+
other relationship. Creative Commons makes its licenses and related
|
| 9 |
+
information available on an "as-is" basis. Creative Commons gives no
|
| 10 |
+
warranties regarding its licenses, any material licensed under their
|
| 11 |
+
terms and conditions, or any related information. Creative Commons
|
| 12 |
+
disclaims all liability for damages resulting from their use to the
|
| 13 |
+
fullest extent possible.
|
| 14 |
+
|
| 15 |
+
Using Creative Commons Public Licenses
|
| 16 |
+
|
| 17 |
+
Creative Commons public licenses provide a standard set of terms and
|
| 18 |
+
conditions that creators and other rights holders may use to share
|
| 19 |
+
original works of authorship and other material subject to copyright
|
| 20 |
+
and certain other rights specified in the public license below. The
|
| 21 |
+
following considerations are for informational purposes only, are not
|
| 22 |
+
exhaustive, and do not form part of our licenses.
|
| 23 |
+
|
| 24 |
+
Considerations for licensors: Our public licenses are
|
| 25 |
+
intended for use by those authorized to give the public
|
| 26 |
+
permission to use material in ways otherwise restricted by
|
| 27 |
+
copyright and certain other rights. Our licenses are
|
| 28 |
+
irrevocable. Licensors should read and understand the terms
|
| 29 |
+
and conditions of the license they choose before applying it.
|
| 30 |
+
Licensors should also secure all rights necessary before
|
| 31 |
+
applying our licenses so that the public can reuse the
|
| 32 |
+
material as expected. Licensors should clearly mark any
|
| 33 |
+
material not subject to the license. This includes other CC-
|
| 34 |
+
licensed material, or material used under an exception or
|
| 35 |
+
limitation to copyright. More considerations for licensors:
|
| 36 |
+
wiki.creativecommons.org/Considerations_for_licensors
|
| 37 |
+
|
| 38 |
+
Considerations for the public: By using one of our public
|
| 39 |
+
licenses, a licensor grants the public permission to use the
|
| 40 |
+
licensed material under specified terms and conditions. If
|
| 41 |
+
the licensor's permission is not necessary for any reason--for
|
| 42 |
+
example, because of any applicable exception or limitation to
|
| 43 |
+
copyright--then that use is not regulated by the license. Our
|
| 44 |
+
licenses grant only permissions under copyright and certain
|
| 45 |
+
other rights that a licensor has authority to grant. Use of
|
| 46 |
+
the licensed material may still be restricted for other
|
| 47 |
+
reasons, including because others have copyright or other
|
| 48 |
+
rights in the material. A licensor may make special requests,
|
| 49 |
+
such as asking that all changes be marked or described.
|
| 50 |
+
Although not required by our licenses, you are encouraged to
|
| 51 |
+
respect those requests where reasonable. More considerations
|
| 52 |
+
for the public:
|
| 53 |
+
wiki.creativecommons.org/Considerations_for_licensees
|
| 54 |
+
|
| 55 |
+
=======================================================================
|
| 56 |
+
|
| 57 |
+
Creative Commons Attribution 4.0 International Public License
|
| 58 |
+
|
| 59 |
+
By exercising the Licensed Rights (defined below), You accept and agree
|
| 60 |
+
to be bound by the terms and conditions of this Creative Commons
|
| 61 |
+
Attribution 4.0 International Public License ("Public License"). To the
|
| 62 |
+
extent this Public License may be interpreted as a contract, You are
|
| 63 |
+
granted the Licensed Rights in consideration of Your acceptance of
|
| 64 |
+
these terms and conditions, and the Licensor grants You such rights in
|
| 65 |
+
consideration of benefits the Licensor receives from making the
|
| 66 |
+
Licensed Material available under these terms and conditions.
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
Section 1 -- Definitions.
|
| 70 |
+
|
| 71 |
+
a. Adapted Material means material subject to Copyright and Similar
|
| 72 |
+
Rights that is derived from or based upon the Licensed Material
|
| 73 |
+
and in which the Licensed Material is translated, altered,
|
| 74 |
+
arranged, transformed, or otherwise modified in a manner requiring
|
| 75 |
+
permission under the Copyright and Similar Rights held by the
|
| 76 |
+
Licensor. For purposes of this Public License, where the Licensed
|
| 77 |
+
Material is a musical work, performance, or sound recording,
|
| 78 |
+
Adapted Material is always produced where the Licensed Material is
|
| 79 |
+
synched in timed relation with a moving image.
|
| 80 |
+
|
| 81 |
+
b. Adapter's License means the license You apply to Your Copyright
|
| 82 |
+
and Similar Rights in Your contributions to Adapted Material in
|
| 83 |
+
accordance with the terms and conditions of this Public License.
|
| 84 |
+
|
| 85 |
+
c. Copyright and Similar Rights means copyright and/or similar rights
|
| 86 |
+
closely related to copyright including, without limitation,
|
| 87 |
+
performance, broadcast, sound recording, and Sui Generis Database
|
| 88 |
+
Rights, without regard to how the rights are labeled or
|
| 89 |
+
categorized. For purposes of this Public License, the rights
|
| 90 |
+
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
| 91 |
+
Rights.
|
| 92 |
+
|
| 93 |
+
d. Effective Technological Measures means those measures that, in the
|
| 94 |
+
absence of proper authority, may not be circumvented under laws
|
| 95 |
+
fulfilling obligations under Article 11 of the WIPO Copyright
|
| 96 |
+
Treaty adopted on December 20, 1996, and/or similar international
|
| 97 |
+
agreements.
|
| 98 |
+
|
| 99 |
+
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
| 100 |
+
any other exception or limitation to Copyright and Similar Rights
|
| 101 |
+
that applies to Your use of the Licensed Material.
|
| 102 |
+
|
| 103 |
+
f. Licensed Material means the artistic or literary work, database,
|
| 104 |
+
or other material to which the Licensor applied this Public
|
| 105 |
+
License.
|
| 106 |
+
|
| 107 |
+
g. Licensed Rights means the rights granted to You subject to the
|
| 108 |
+
terms and conditions of this Public License, which are limited to
|
| 109 |
+
all Copyright and Similar Rights that apply to Your use of the
|
| 110 |
+
Licensed Material and that the Licensor has authority to license.
|
| 111 |
+
|
| 112 |
+
h. Licensor means the individual(s) or entity(ies) granting rights
|
| 113 |
+
under this Public License.
|
| 114 |
+
|
| 115 |
+
i. Share means to provide material to the public by any means or
|
| 116 |
+
process that requires permission under the Licensed Rights, such
|
| 117 |
+
as reproduction, public display, public performance, distribution,
|
| 118 |
+
dissemination, communication, or importation, and to make material
|
| 119 |
+
available to the public including in ways that members of the
|
| 120 |
+
public may access the material from a place and at a time
|
| 121 |
+
individually chosen by them.
|
| 122 |
+
|
| 123 |
+
j. Sui Generis Database Rights means rights other than copyright
|
| 124 |
+
resulting from Directive 96/9/EC of the European Parliament and of
|
| 125 |
+
the Council of 11 March 1996 on the legal protection of databases,
|
| 126 |
+
as amended and/or succeeded, as well as other essentially
|
| 127 |
+
equivalent rights anywhere in the world.
|
| 128 |
+
|
| 129 |
+
k. You means the individual or entity exercising the Licensed Rights
|
| 130 |
+
under this Public License. Your has a corresponding meaning.
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
Section 2 -- Scope.
|
| 134 |
+
|
| 135 |
+
a. License grant.
|
| 136 |
+
|
| 137 |
+
1. Subject to the terms and conditions of this Public License,
|
| 138 |
+
the Licensor hereby grants You a worldwide, royalty-free,
|
| 139 |
+
non-sublicensable, non-exclusive, irrevocable license to
|
| 140 |
+
exercise the Licensed Rights in the Licensed Material to:
|
| 141 |
+
|
| 142 |
+
a. reproduce and Share the Licensed Material, in whole or
|
| 143 |
+
in part; and
|
| 144 |
+
|
| 145 |
+
b. produce, reproduce, and Share Adapted Material.
|
| 146 |
+
|
| 147 |
+
2. Exceptions and Limitations. For the avoidance of doubt, where
|
| 148 |
+
Exceptions and Limitations apply to Your use, this Public
|
| 149 |
+
License does not apply, and You do not need to comply with
|
| 150 |
+
its terms and conditions.
|
| 151 |
+
|
| 152 |
+
3. Term. The term of this Public License is specified in Section
|
| 153 |
+
6(a).
|
| 154 |
+
|
| 155 |
+
4. Media and formats; technical modifications allowed. The
|
| 156 |
+
Licensor authorizes You to exercise the Licensed Rights in
|
| 157 |
+
all media and formats whether now known or hereafter created,
|
| 158 |
+
and to make technical modifications necessary to do so. The
|
| 159 |
+
Licensor waives and/or agrees not to assert any right or
|
| 160 |
+
authority to forbid You from making technical modifications
|
| 161 |
+
necessary to exercise the Licensed Rights, including
|
| 162 |
+
technical modifications necessary to circumvent Effective
|
| 163 |
+
Technological Measures. For purposes of this Public License,
|
| 164 |
+
simply making modifications authorized by this Section 2(a)
|
| 165 |
+
(4) never produces Adapted Material.
|
| 166 |
+
|
| 167 |
+
5. Downstream recipients.
|
| 168 |
+
|
| 169 |
+
a. Offer from the Licensor -- Licensed Material. Every
|
| 170 |
+
recipient of the Licensed Material automatically
|
| 171 |
+
receives an offer from the Licensor to exercise the
|
| 172 |
+
Licensed Rights under the terms and conditions of this
|
| 173 |
+
Public License.
|
| 174 |
+
|
| 175 |
+
b. No downstream restrictions. You may not offer or impose
|
| 176 |
+
any additional or different terms or conditions on, or
|
| 177 |
+
apply any Effective Technological Measures to, the
|
| 178 |
+
Licensed Material if doing so restricts exercise of the
|
| 179 |
+
Licensed Rights by any recipient of the Licensed
|
| 180 |
+
Material.
|
| 181 |
+
|
| 182 |
+
6. No endorsement. Nothing in this Public License constitutes or
|
| 183 |
+
may be construed as permission to assert or imply that You
|
| 184 |
+
are, or that Your use of the Licensed Material is, connected
|
| 185 |
+
with, or sponsored, endorsed, or granted official status by,
|
| 186 |
+
the Licensor or others designated to receive attribution as
|
| 187 |
+
provided in Section 3(a)(1)(A)(i).
|
| 188 |
+
|
| 189 |
+
b. Other rights.
|
| 190 |
+
|
| 191 |
+
1. Moral rights, such as the right of integrity, are not
|
| 192 |
+
licensed under this Public License, nor are publicity,
|
| 193 |
+
privacy, and/or other similar personality rights; however, to
|
| 194 |
+
the extent possible, the Licensor waives and/or agrees not to
|
| 195 |
+
assert any such rights held by the Licensor to the limited
|
| 196 |
+
extent necessary to allow You to exercise the Licensed
|
| 197 |
+
Rights, but not otherwise.
|
| 198 |
+
|
| 199 |
+
2. Patent and trademark rights are not licensed under this
|
| 200 |
+
Public License.
|
| 201 |
+
|
| 202 |
+
3. To the extent possible, the Licensor waives any right to
|
| 203 |
+
collect royalties from You for the exercise of the Licensed
|
| 204 |
+
Rights, whether directly or through a collecting society
|
| 205 |
+
under any voluntary or waivable statutory or compulsory
|
| 206 |
+
licensing scheme. In all other cases the Licensor expressly
|
| 207 |
+
reserves any right to collect such royalties.
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
Section 3 -- License Conditions.
|
| 211 |
+
|
| 212 |
+
Your exercise of the Licensed Rights is expressly made subject to the
|
| 213 |
+
following conditions.
|
| 214 |
+
|
| 215 |
+
a. Attribution.
|
| 216 |
+
|
| 217 |
+
1. If You Share the Licensed Material (including in modified
|
| 218 |
+
form), You must:
|
| 219 |
+
|
| 220 |
+
a. retain the following if it is supplied by the Licensor
|
| 221 |
+
with the Licensed Material:
|
| 222 |
+
|
| 223 |
+
i. identification of the creator(s) of the Licensed
|
| 224 |
+
Material and any others designated to receive
|
| 225 |
+
attribution, in any reasonable manner requested by
|
| 226 |
+
the Licensor (including by pseudonym if
|
| 227 |
+
designated);
|
| 228 |
+
|
| 229 |
+
ii. a copyright notice;
|
| 230 |
+
|
| 231 |
+
iii. a notice that refers to this Public License;
|
| 232 |
+
|
| 233 |
+
iv. a notice that refers to the disclaimer of
|
| 234 |
+
warranties;
|
| 235 |
+
|
| 236 |
+
v. a URI or hyperlink to the Licensed Material to the
|
| 237 |
+
extent reasonably practicable;
|
| 238 |
+
|
| 239 |
+
b. indicate if You modified the Licensed Material and
|
| 240 |
+
retain an indication of any previous modifications; and
|
| 241 |
+
|
| 242 |
+
c. indicate the Licensed Material is licensed under this
|
| 243 |
+
Public License, and include the text of, or the URI or
|
| 244 |
+
hyperlink to, this Public License.
|
| 245 |
+
|
| 246 |
+
2. You may satisfy the conditions in Section 3(a)(1) in any
|
| 247 |
+
reasonable manner based on the medium, means, and context in
|
| 248 |
+
which You Share the Licensed Material. For example, it may be
|
| 249 |
+
reasonable to satisfy the conditions by providing a URI or
|
| 250 |
+
hyperlink to a resource that includes the required
|
| 251 |
+
information.
|
| 252 |
+
|
| 253 |
+
3. If requested by the Licensor, You must remove any of the
|
| 254 |
+
information required by Section 3(a)(1)(A) to the extent
|
| 255 |
+
reasonably practicable.
|
| 256 |
+
|
| 257 |
+
4. If You Share Adapted Material You produce, the Adapter's
|
| 258 |
+
License You apply must not prevent recipients of the Adapted
|
| 259 |
+
Material from complying with this Public License.
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
Section 4 -- Sui Generis Database Rights.
|
| 263 |
+
|
| 264 |
+
Where the Licensed Rights include Sui Generis Database Rights that
|
| 265 |
+
apply to Your use of the Licensed Material:
|
| 266 |
+
|
| 267 |
+
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
| 268 |
+
to extract, reuse, reproduce, and Share all or a substantial
|
| 269 |
+
portion of the contents of the database;
|
| 270 |
+
|
| 271 |
+
b. if You include all or a substantial portion of the database
|
| 272 |
+
contents in a database in which You have Sui Generis Database
|
| 273 |
+
Rights, then the database in which You have Sui Generis Database
|
| 274 |
+
Rights (but not its individual contents) is Adapted Material; and
|
| 275 |
+
|
| 276 |
+
c. You must comply with the conditions in Section 3(a) if You Share
|
| 277 |
+
all or a substantial portion of the contents of the database.
|
| 278 |
+
|
| 279 |
+
For the avoidance of doubt, this Section 4 supplements and does not
|
| 280 |
+
replace Your obligations under this Public License where the Licensed
|
| 281 |
+
Rights include other Copyright and Similar Rights.
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
| 285 |
+
|
| 286 |
+
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
| 287 |
+
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
| 288 |
+
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
| 289 |
+
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
| 290 |
+
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
| 291 |
+
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
| 292 |
+
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
| 293 |
+
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
| 294 |
+
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
| 295 |
+
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
| 296 |
+
|
| 297 |
+
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
| 298 |
+
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
| 299 |
+
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
| 300 |
+
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
| 301 |
+
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
| 302 |
+
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
| 303 |
+
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
| 304 |
+
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
| 305 |
+
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
| 306 |
+
|
| 307 |
+
c. The disclaimer of warranties and limitation of liability provided
|
| 308 |
+
above shall be interpreted in a manner that, to the extent
|
| 309 |
+
possible, most closely approximates an absolute disclaimer and
|
| 310 |
+
waiver of all liability.
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
Section 6 -- Term and Termination.
|
| 314 |
+
|
| 315 |
+
a. This Public License applies for the term of the Copyright and
|
| 316 |
+
Similar Rights licensed here. However, if You fail to comply with
|
| 317 |
+
this Public License, then Your rights under this Public License
|
| 318 |
+
terminate automatically.
|
| 319 |
+
|
| 320 |
+
b. Where Your right to use the Licensed Material has terminated under
|
| 321 |
+
Section 6(a), it reinstates:
|
| 322 |
+
|
| 323 |
+
1. automatically as of the date the violation is cured, provided
|
| 324 |
+
it is cured within 30 days of Your discovery of the
|
| 325 |
+
violation; or
|
| 326 |
+
|
| 327 |
+
2. upon express reinstatement by the Licensor.
|
| 328 |
+
|
| 329 |
+
For the avoidance of doubt, this Section 6(b) does not affect any
|
| 330 |
+
right the Licensor may have to seek remedies for Your violations
|
| 331 |
+
of this Public License.
|
| 332 |
+
|
| 333 |
+
c. For the avoidance of doubt, the Licensor may also offer the
|
| 334 |
+
Licensed Material under separate terms or conditions or stop
|
| 335 |
+
distributing the Licensed Material at any time; however, doing so
|
| 336 |
+
will not terminate this Public License.
|
| 337 |
+
|
| 338 |
+
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
| 339 |
+
License.
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
Section 7 -- Other Terms and Conditions.
|
| 343 |
+
|
| 344 |
+
a. The Licensor shall not be bound by any additional or different
|
| 345 |
+
terms or conditions communicated by You unless expressly agreed.
|
| 346 |
+
|
| 347 |
+
b. Any arrangements, understandings, or agreements regarding the
|
| 348 |
+
Licensed Material not stated herein are separate from and
|
| 349 |
+
independent of the terms and conditions of this Public License.
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
Section 8 -- Interpretation.
|
| 353 |
+
|
| 354 |
+
a. For the avoidance of doubt, this Public License does not, and
|
| 355 |
+
shall not be interpreted to, reduce, limit, restrict, or impose
|
| 356 |
+
conditions on any use of the Licensed Material that could lawfully
|
| 357 |
+
be made without permission under this Public License.
|
| 358 |
+
|
| 359 |
+
b. To the extent possible, if any provision of this Public License is
|
| 360 |
+
deemed unenforceable, it shall be automatically reformed to the
|
| 361 |
+
minimum extent necessary to make it enforceable. If the provision
|
| 362 |
+
cannot be reformed, it shall be severed from this Public License
|
| 363 |
+
without affecting the enforceability of the remaining terms and
|
| 364 |
+
conditions.
|
| 365 |
+
|
| 366 |
+
c. No term or condition of this Public License will be waived and no
|
| 367 |
+
failure to comply consented to unless expressly agreed to by the
|
| 368 |
+
Licensor.
|
| 369 |
+
|
| 370 |
+
d. Nothing in this Public License constitutes or may be interpreted
|
| 371 |
+
as a limitation upon, or waiver of, any privileges and immunities
|
| 372 |
+
that apply to the Licensor or You, including from the legal
|
| 373 |
+
processes of any jurisdiction or authority.
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
=======================================================================
|
| 377 |
+
|
| 378 |
+
Creative Commons is not a party to its public
|
| 379 |
+
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
| 380 |
+
its public licenses to material it publishes and in those instances
|
| 381 |
+
will be considered the “Licensor.” The text of the Creative Commons
|
| 382 |
+
public licenses is dedicated to the public domain under the CC0 Public
|
| 383 |
+
Domain Dedication. Except for the limited purpose of indicating that
|
| 384 |
+
material is shared under a Creative Commons public license or as
|
| 385 |
+
otherwise permitted by the Creative Commons policies published at
|
| 386 |
+
creativecommons.org/policies, Creative Commons does not authorize the
|
| 387 |
+
use of the trademark "Creative Commons" or any other trademark or logo
|
| 388 |
+
of Creative Commons without its prior written consent including,
|
| 389 |
+
without limitation, in connection with any unauthorized modifications
|
| 390 |
+
to any of its public licenses or any other arrangements,
|
| 391 |
+
understandings, or agreements concerning use of licensed material. For
|
| 392 |
+
the avoidance of doubt, this paragraph does not form part of the
|
| 393 |
+
public licenses.
|
| 394 |
+
|
| 395 |
+
Creative Commons may be contacted at creativecommons.org.
|
| 396 |
+
|
model-terms/pnc/LICENSES/CC0-1.0.txt
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Creative Commons Legal Code
|
| 2 |
+
|
| 3 |
+
CC0 1.0 Universal
|
| 4 |
+
|
| 5 |
+
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
| 6 |
+
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
| 7 |
+
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
| 8 |
+
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
| 9 |
+
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
| 10 |
+
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
| 11 |
+
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
| 12 |
+
HEREUNDER.
|
| 13 |
+
|
| 14 |
+
Statement of Purpose
|
| 15 |
+
|
| 16 |
+
The laws of most jurisdictions throughout the world automatically confer
|
| 17 |
+
exclusive Copyright and Related Rights (defined below) upon the creator
|
| 18 |
+
and subsequent owner(s) (each and all, an "owner") of an original work of
|
| 19 |
+
authorship and/or a database (each, a "Work").
|
| 20 |
+
|
| 21 |
+
Certain owners wish to permanently relinquish those rights to a Work for
|
| 22 |
+
the purpose of contributing to a commons of creative, cultural and
|
| 23 |
+
scientific works ("Commons") that the public can reliably and without fear
|
| 24 |
+
of later claims of infringement build upon, modify, incorporate in other
|
| 25 |
+
works, reuse and redistribute as freely as possible in any form whatsoever
|
| 26 |
+
and for any purposes, including without limitation commercial purposes.
|
| 27 |
+
These owners may contribute to the Commons to promote the ideal of a free
|
| 28 |
+
culture and the further production of creative, cultural and scientific
|
| 29 |
+
works, or to gain reputation or greater distribution for their Work in
|
| 30 |
+
part through the use and efforts of others.
|
| 31 |
+
|
| 32 |
+
For these and/or other purposes and motivations, and without any
|
| 33 |
+
expectation of additional consideration or compensation, the person
|
| 34 |
+
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
| 35 |
+
is an owner of Copyright and Related Rights in the Work, voluntarily
|
| 36 |
+
elects to apply CC0 to the Work and publicly distribute the Work under its
|
| 37 |
+
terms, with knowledge of his or her Copyright and Related Rights in the
|
| 38 |
+
Work and the meaning and intended legal effect of CC0 on those rights.
|
| 39 |
+
|
| 40 |
+
1. Copyright and Related Rights. A Work made available under CC0 may be
|
| 41 |
+
protected by copyright and related or neighboring rights ("Copyright and
|
| 42 |
+
Related Rights"). Copyright and Related Rights include, but are not
|
| 43 |
+
limited to, the following:
|
| 44 |
+
|
| 45 |
+
i. the right to reproduce, adapt, distribute, perform, display,
|
| 46 |
+
communicate, and translate a Work;
|
| 47 |
+
ii. moral rights retained by the original author(s) and/or performer(s);
|
| 48 |
+
iii. publicity and privacy rights pertaining to a person's image or
|
| 49 |
+
likeness depicted in a Work;
|
| 50 |
+
iv. rights protecting against unfair competition in regards to a Work,
|
| 51 |
+
subject to the limitations in paragraph 4(a), below;
|
| 52 |
+
v. rights protecting the extraction, dissemination, use and reuse of data
|
| 53 |
+
in a Work;
|
| 54 |
+
vi. database rights (such as those arising under Directive 96/9/EC of the
|
| 55 |
+
European Parliament and of the Council of 11 March 1996 on the legal
|
| 56 |
+
protection of databases, and under any national implementation
|
| 57 |
+
thereof, including any amended or successor version of such
|
| 58 |
+
directive); and
|
| 59 |
+
vii. other similar, equivalent or corresponding rights throughout the
|
| 60 |
+
world based on applicable law or treaty, and any national
|
| 61 |
+
implementations thereof.
|
| 62 |
+
|
| 63 |
+
2. Waiver. To the greatest extent permitted by, but not in contravention
|
| 64 |
+
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
| 65 |
+
irrevocably and unconditionally waives, abandons, and surrenders all of
|
| 66 |
+
Affirmer's Copyright and Related Rights and associated claims and causes
|
| 67 |
+
of action, whether now known or unknown (including existing as well as
|
| 68 |
+
future claims and causes of action), in the Work (i) in all territories
|
| 69 |
+
worldwide, (ii) for the maximum duration provided by applicable law or
|
| 70 |
+
treaty (including future time extensions), (iii) in any current or future
|
| 71 |
+
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
| 72 |
+
including without limitation commercial, advertising or promotional
|
| 73 |
+
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
| 74 |
+
member of the public at large and to the detriment of Affirmer's heirs and
|
| 75 |
+
successors, fully intending that such Waiver shall not be subject to
|
| 76 |
+
revocation, rescission, cancellation, termination, or any other legal or
|
| 77 |
+
equitable action to disrupt the quiet enjoyment of the Work by the public
|
| 78 |
+
as contemplated by Affirmer's express Statement of Purpose.
|
| 79 |
+
|
| 80 |
+
3. Public License Fallback. Should any part of the Waiver for any reason
|
| 81 |
+
be judged legally invalid or ineffective under applicable law, then the
|
| 82 |
+
Waiver shall be preserved to the maximum extent permitted taking into
|
| 83 |
+
account Affirmer's express Statement of Purpose. In addition, to the
|
| 84 |
+
extent the Waiver is so judged Affirmer hereby grants to each affected
|
| 85 |
+
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
| 86 |
+
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
| 87 |
+
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
| 88 |
+
maximum duration provided by applicable law or treaty (including future
|
| 89 |
+
time extensions), (iii) in any current or future medium and for any number
|
| 90 |
+
of copies, and (iv) for any purpose whatsoever, including without
|
| 91 |
+
limitation commercial, advertising or promotional purposes (the
|
| 92 |
+
"License"). The License shall be deemed effective as of the date CC0 was
|
| 93 |
+
applied by Affirmer to the Work. Should any part of the License for any
|
| 94 |
+
reason be judged legally invalid or ineffective under applicable law, such
|
| 95 |
+
partial invalidity or ineffectiveness shall not invalidate the remainder
|
| 96 |
+
of the License, and in such case Affirmer hereby affirms that he or she
|
| 97 |
+
will not (i) exercise any of his or her remaining Copyright and Related
|
| 98 |
+
Rights in the Work or (ii) assert any associated claims and causes of
|
| 99 |
+
action with respect to the Work, in either case contrary to Affirmer's
|
| 100 |
+
express Statement of Purpose.
|
| 101 |
+
|
| 102 |
+
4. Limitations and Disclaimers.
|
| 103 |
+
|
| 104 |
+
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
| 105 |
+
surrendered, licensed or otherwise affected by this document.
|
| 106 |
+
b. Affirmer offers the Work as-is and makes no representations or
|
| 107 |
+
warranties of any kind concerning the Work, express, implied,
|
| 108 |
+
statutory or otherwise, including without limitation warranties of
|
| 109 |
+
title, merchantability, fitness for a particular purpose, non
|
| 110 |
+
infringement, or the absence of latent or other defects, accuracy, or
|
| 111 |
+
the present or absence of errors, whether or not discoverable, all to
|
| 112 |
+
the greatest extent permissible under applicable law.
|
| 113 |
+
c. Affirmer disclaims responsibility for clearing rights of other persons
|
| 114 |
+
that may apply to the Work or any use thereof, including without
|
| 115 |
+
limitation any person's Copyright and Related Rights in the Work.
|
| 116 |
+
Further, Affirmer disclaims responsibility for obtaining any necessary
|
| 117 |
+
consents, permissions or other rights required for any use of the
|
| 118 |
+
Work.
|
| 119 |
+
d. Affirmer understands and acknowledges that Creative Commons is not a
|
| 120 |
+
party to this document and has no duty or obligation with respect to
|
| 121 |
+
this CC0 or use of the Work.
|
model-terms/pnc/LICENSES/CORAL-LICENSE
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
LICENSED MATERIAL (INCLUDING DATA) - LICENSE TO USE
|
| 2 |
+
|
| 3 |
+
The Licensed Material (as defined below) is made available to You by Alexandra
|
| 4 |
+
Instituttet A/S, Åbogade 34, 8200 Aarhus N, Denmark and may be utilised solely in
|
| 5 |
+
accordance with the license terms stipulated in this document.
|
| 6 |
+
|
| 7 |
+
The license is based on "AI PUBS OPEN RAIL-M LICENSE" available at
|
| 8 |
+
www.licenses.ai/ai-licenses modified to fit the licensing of Data (hereinafter referred
|
| 9 |
+
to as "the Conditions"), a copy of the modified conditions is attached hereto, with the
|
| 10 |
+
following additions:
|
| 11 |
+
|
| 12 |
+
1. The license is governed by the laws of the Kingdom of Denmark
|
| 13 |
+
2. Any dispute arising out of or in connection herewith, including any disputes
|
| 14 |
+
regarding the existence, validity or termination of the license, shall be first
|
| 15 |
+
referred to mediation administered by the Danish Institute of Arbitration in
|
| 16 |
+
accordance with the Rules on Mediation adopted by the Board of the Danish Institute
|
| 17 |
+
of Arbitration. If the mediation proceedings are terminated without a settlement,
|
| 18 |
+
the dispute shall be finally settled by arbitration administered by the Danish
|
| 19 |
+
Institute of Arbitration in accordance with the Rules of Arbitration adopted by the
|
| 20 |
+
Board of the Danish Institute of Arbitration. The arbitral tribunal shall be
|
| 21 |
+
composed of three arbitrators. The place of arbitration shall be Aarhus, Denmark.
|
| 22 |
+
The language to be used in the arbitral proceedings shall be the English language.
|
| 23 |
+
3. If, at any time, the compilation, storage, utilisation, or processing of the
|
| 24 |
+
Licensed Material or the Adapted Material (all as defined below) constitute
|
| 25 |
+
violation of applicable laws, regardless of anything to the contrary in these
|
| 26 |
+
conditions, the license shall automatically become null and void without any
|
| 27 |
+
liability for the Licensor whatsoever.
|
| 28 |
+
4. Supplementing Attachment A to the Conditions, You additionally agree not to use the
|
| 29 |
+
Licensed Material or the Adapted Material:
|
| 30 |
+
|
| 31 |
+
(a) To impersonate any person or entity or otherwise misrepresent its affiliation
|
| 32 |
+
with a person or entity, including (but not limited to) the creation of
|
| 33 |
+
synthetic speech (i) emulating a specific natural person or (ii) which is found
|
| 34 |
+
to be similar to a specific natural person's speech (regardless of whether the
|
| 35 |
+
identity of such natural person is known at the time of the creation); or
|
| 36 |
+
(b) To detect or infer aspects and/or features of an identity of any natural
|
| 37 |
+
persons, such as name, family name, address, gender, sexual orientation, race,
|
| 38 |
+
religion, age, location (at any geographical level), skin color, society or
|
| 39 |
+
political affiliations, employment status and/or employment history, and health
|
| 40 |
+
and medical conditions.
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
CONDITIONS
|
| 44 |
+
|
| 45 |
+
Section I: PREAMBLE
|
| 46 |
+
|
| 47 |
+
These Conditions are based on OpenRAIL-M License adopted to fit the licensing of Data. A
|
| 48 |
+
version of the Conditions with all changes to the OpenRAIL-M License highlighted is
|
| 49 |
+
available at www.licenses.ai/ai-licenses. The “Open” nomenclature indicates that the
|
| 50 |
+
Licensed Material is freely accessible to downstream and other users. The “RAIL”
|
| 51 |
+
nomenclature indicates that there are use restrictions prohibiting the use of the
|
| 52 |
+
Licensed Material. These restrictions are intended to avoid potential misuse. Even
|
| 53 |
+
though Adapted Material could be released under different licensing terms, the
|
| 54 |
+
Conditions specify that the use restrictions in the original License must apply to such
|
| 55 |
+
Adapted Material.
|
| 56 |
+
|
| 57 |
+
NOW THEREFORE, You and Licensor agree as follows:
|
| 58 |
+
|
| 59 |
+
1. Definitions
|
| 60 |
+
|
| 61 |
+
(a) "Adapted Material" means material (including Models) derived from or based upon
|
| 62 |
+
the Licensed Material.
|
| 63 |
+
(b) "Data"” means a collection of information and/or content extracted from the
|
| 64 |
+
dataset used with the Model, including to train, pretrain, or otherwise evaluate
|
| 65 |
+
a Model. The Data form part of the Licensed Material.
|
| 66 |
+
(c) "Distribution" means any transmission, reproduction, publication or other
|
| 67 |
+
sharing of the Licensed Material or the Adapted Material to a third party,
|
| 68 |
+
including providing the Licensed Material or the Adapted Material as a hosted
|
| 69 |
+
service made available by electronic or other remote means - e.g. API-based or
|
| 70 |
+
web access.
|
| 71 |
+
(d) "Harm" includes but is not limited to physical, mental, psychological, financial
|
| 72 |
+
and reputational damage, pain, or loss
|
| 73 |
+
(e) "License" means the terms and conditions for use, reproduction, and Distribution
|
| 74 |
+
as defined in this document, including the additions and amendments stated
|
| 75 |
+
above.
|
| 76 |
+
(f) "Licensed Material" means the artistic or literary work, database, or other
|
| 77 |
+
material to which the Licensor applied this License.
|
| 78 |
+
(g) "Licensor" means the rights owner or entity authorized by the rights owner that
|
| 79 |
+
is granting the License, including the persons or entities that may have rights
|
| 80 |
+
in the Licensed Material or the Adapted Material and/or distributing the
|
| 81 |
+
Licensed Material or the Adapted Material.
|
| 82 |
+
(h) "Model" means any accompanying machine-learning based assemblies (including
|
| 83 |
+
checkpoints), consisting of learnt weights, parameters (including optimizer
|
| 84 |
+
states), that have been trained or tuned, in whole or in part on the Data, using
|
| 85 |
+
the Licensed Material. The term "Model" includes algorithmic assemblies,
|
| 86 |
+
including but not limited to machine-learning based assemblies trained on
|
| 87 |
+
Licensed Material as well as other material and/or data.
|
| 88 |
+
(i) "Output" means the results of operating a Model as embodied in informational
|
| 89 |
+
content resulting therefrom.
|
| 90 |
+
(j) "Third Parties" means individuals or legal entities that are not under common
|
| 91 |
+
control with Licensor or You.
|
| 92 |
+
(k) "You" (or "Your") means an individual or legal entity exercising permissions
|
| 93 |
+
granted by this License and/or making use of the Licensed Material for whichever
|
| 94 |
+
purpose and in any field of use, including usage of the Licensed Material or
|
| 95 |
+
Adapted Material in an end-use application - e.g. chatbot, translator, image
|
| 96 |
+
generator, speech recognizer, speech generator, adapter etc.
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
Section II: INTELLECTUAL PROPERTY RIGHTS
|
| 100 |
+
|
| 101 |
+
Both copyright and patent grants may apply to the Licensed Material or the Adapted
|
| 102 |
+
Material. The Licensed Material or the Adapted Material are subject to additional terms
|
| 103 |
+
as described in Section III, which shall govern the use of the Licensed Material or the
|
| 104 |
+
Adapted Material even in the event Section II is held unenforceable.
|
| 105 |
+
|
| 106 |
+
2. Grant of Copyright License. Subject to the terms and conditions of this License,
|
| 107 |
+
Licensor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
|
| 108 |
+
royalty-free, irrevocable copyright license to reproduce, prepare, publicly display,
|
| 109 |
+
publicly perform, sublicense, and distribute the Licensed Material or the Adapted
|
| 110 |
+
Material.
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
Section III: CONDITIONS OF USAGE, DISTRIBUTION AND REDISTRIBUTION
|
| 114 |
+
|
| 115 |
+
3. Distribution and Redistribution. You may host for Third Party remote access purposes
|
| 116 |
+
(e.g. software-as-a-service), reproduce and distribute copies of the Licensed
|
| 117 |
+
Material or the Adapted Material in any medium, with or without modifications,
|
| 118 |
+
provided that You meet the following conditions:
|
| 119 |
+
|
| 120 |
+
(a) Use-based restrictions in paragraph 4 MUST be included as an enforceable
|
| 121 |
+
provision by You in any type of legal agreement (e.g. a license) governing the
|
| 122 |
+
use and/or distribution of the Licensed Material or the Adapted Material, and
|
| 123 |
+
You shall give notice to subsequent users You Distribute to, that the Licensed
|
| 124 |
+
Material or the Adapted Material are subject to paragraph 4.
|
| 125 |
+
(b) You must give any Third Party recipients of the Licensed Material or the Adapted
|
| 126 |
+
Material a copy of this License;
|
| 127 |
+
(c) You must cause any modified files to carry prominent notices stating that You
|
| 128 |
+
changed the files;
|
| 129 |
+
(d) You must retain all copyright, patent, trademark, and attribution notices
|
| 130 |
+
excluding those notices that do not pertain to any part of the Licensed Material
|
| 131 |
+
or the Adapted Material. You may add Your own copyright statement to Your
|
| 132 |
+
modifications and may provide additional or different license terms and
|
| 133 |
+
conditions - respecting paragraph 3.a - for use, reproduction, or Distribution
|
| 134 |
+
of Your modifications, or for any such Adapted Material as a whole, provided
|
| 135 |
+
Your use, reproduction, and Distribution of the Licensed Material or the Adapted
|
| 136 |
+
Material otherwise complies with the conditions stated in this License.
|
| 137 |
+
|
| 138 |
+
4. Use-based restrictions. The restrictions set forth in Attachment A are considered
|
| 139 |
+
Use-based restrictions. Therefore You cannot use the Licensed Material or the Adapted
|
| 140 |
+
Material in violation of such restrictions. You may use the Licensed Material or the
|
| 141 |
+
Adapted Material subject to this License, including only for lawful purposes and in
|
| 142 |
+
accordance with the License. You shall require all of Your users who use the Licensed
|
| 143 |
+
Material or the Adapted Material to comply with the terms of this paragraph 4.
|
| 144 |
+
5. The Output You Generate. Except as set forth herein, Licensor claims no rights in the
|
| 145 |
+
Output You generate using the Licensed Material or the Adapted Material. You are
|
| 146 |
+
accountable for the Output you generate and its subsequent uses. No use of the output
|
| 147 |
+
can contravene any provision as stated in the License.
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
Section IV: OTHER PROVISIONS
|
| 151 |
+
|
| 152 |
+
6. Updates and Runtime Restrictions. To the maximum extent permitted by law, Licensor
|
| 153 |
+
reserves the right to restrict (remotely or otherwise) usage of the Licensed Material
|
| 154 |
+
or the Adapted Material in violation of this License or update the Licensed Material
|
| 155 |
+
through electronic means.
|
| 156 |
+
7. Trademarks and related. Nothing in this License permits You to make use of Licensors’
|
| 157 |
+
trademarks, trade names, logos or to otherwise suggest endorsement or misrepresent
|
| 158 |
+
the relationship between the parties; and any rights not expressly granted herein are
|
| 159 |
+
reserved by the Licensors.
|
| 160 |
+
8. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing,
|
| 161 |
+
Licensor provides the Licensed Material on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
| 162 |
+
CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any
|
| 163 |
+
warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
|
| 164 |
+
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
|
| 165 |
+
of using or redistributing the Licensed Material or the Adapted Material, and assume
|
| 166 |
+
any risks associated with Your exercise of permissions under this License.
|
| 167 |
+
9. Limitation of Liability. In no event and under no legal theory, whether in tort
|
| 168 |
+
(including negligence), contract, or otherwise, unless required by applicable law
|
| 169 |
+
(such as deliberate and grossly negligent acts) or agreed to in writing, shall
|
| 170 |
+
Licensor be liable to You for damages, including any direct, indirect, special,
|
| 171 |
+
incidental, or consequential damages of any character arising as a result of this
|
| 172 |
+
License or out of the use or inability to use the Licensed Material (including but
|
| 173 |
+
not limited to damages for loss of goodwill, work stoppage, computer failure or
|
| 174 |
+
malfunction, or any and all other commercial damages or losses), even if Licensor has
|
| 175 |
+
been advised of the possibility of such damages.
|
| 176 |
+
10. Accepting Warranty or Additional Liability. While redistributing the Licensed
|
| 177 |
+
Material or the Adapted Material, You may choose to charge a fee in exchange for
|
| 178 |
+
support, warranty, indemnity, or other obligations and/or rights consistent with
|
| 179 |
+
this License. However, in accepting such obligations, You may act only on Your own
|
| 180 |
+
behalf and on Your sole responsibility, not on behalf of Licensor, and only if You
|
| 181 |
+
agree to indemnify, defend, and hold Licensor harmless for any liability incurred
|
| 182 |
+
by, or claims asserted against, Licensor by reason of your accepting any such
|
| 183 |
+
warranty or additional liability.
|
| 184 |
+
11. If any provision of this License is held to be invalid, illegal or unenforceable,
|
| 185 |
+
the remaining provisions shall be unaffected thereby and remain valid as if such
|
| 186 |
+
provision had not been set forth herein.
|
| 187 |
+
|
| 188 |
+
END OF TERMS AND CONDITIONS
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
Attachment A
|
| 192 |
+
|
| 193 |
+
USE RESTRICTIONS
|
| 194 |
+
|
| 195 |
+
You agree not to use the Licensed Material or the Adapted Material in any of the
|
| 196 |
+
following ways:
|
| 197 |
+
|
| 198 |
+
1. Legal:
|
| 199 |
+
(a) In any way that violates any applicable national, federal, state, local or
|
| 200 |
+
international law or regulation.
|
| 201 |
+
2. Harm and Discrimination
|
| 202 |
+
(a) For the purpose of exploiting, Harming or attempting to exploit or Harm minors
|
| 203 |
+
in any way;
|
| 204 |
+
(b) To generate or disseminate false information with the purpose of Harming others;
|
| 205 |
+
(c) To generate or disseminate personal identifiable information that can be used to
|
| 206 |
+
Harm an individual;
|
| 207 |
+
(d) To defame, disparage or otherwise harass others;
|
| 208 |
+
(e) For any use intended to or which has the effect of Harming individuals or groups
|
| 209 |
+
based on online or offline social behavior or known or predicted personal or
|
| 210 |
+
personality characteristics
|
| 211 |
+
(f) To exploit any of the vulnerabilities of a specific group of persons based on
|
| 212 |
+
their age, social, physical or mental characteristics, in order to materially
|
| 213 |
+
distort the behavior of a person belonging to that group in a manner that causes
|
| 214 |
+
or is likely to cause that person or another person Harm
|
| 215 |
+
(g) For any use intended to or which has the effect of discriminating against
|
| 216 |
+
individuals or groups based on legally protected characteristics or categories.
|
| 217 |
+
3. Transparency
|
| 218 |
+
(a) To generate or disseminate machine-generated information or content in any
|
| 219 |
+
medium without expressly and intelligibly disclaiming that it is
|
| 220 |
+
machine-generated;
|
| 221 |
+
(b) To impersonate or attempt to impersonate human beings for purposes of deception;
|
| 222 |
+
(c) For fully automated decision making that adversely impacts an individual’s legal
|
| 223 |
+
rights or otherwise creates or modifies a binding, enforceable obligation.
|
model-terms/pnc/LICENSES/FTSPEECH-LICENSE.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
layout: page
|
| 3 |
+
title: License
|
| 4 |
+
---
|
| 5 |
+
<br>
|
| 6 |
+
2020, **FT Speech**, [ftspeech.dk](ftspeech.dk)
|
| 7 |
+
|
| 8 |
+
Any use of FT Speech text and audio data must be in accordance with the following two licenses: [Folketing's open data](https://www.ft.dk/da/dokumenter/aabne_data#290AB29F56C54AC88474BC53393A3AE0) and [Folketing TV](https://www.ft.dk/da/aktuelt/tv-fra-folketinget/deling-og-rettigheder). The data released here must always be accompanied by this LICENSE statement and the two Folketing licenses.
|
model-terms/pnc/MODEL_LICENSE.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ekko-pnc-stage3a model terms
|
| 2 |
+
|
| 3 |
+
This is a modified model derived from `jonfd/electra-small-nordic`, licensed CC BY 4.0. RyeAI
|
| 4 |
+
applies Creative Commons Attribution 4.0 International to the modifications it has
|
| 5 |
+
the right to license. A copy is included at `LICENSES/CC-BY-4.0.txt`.
|
| 6 |
+
|
| 7 |
+
Training material included text associated with CoRal. `LICENSES/CORAL-LICENSE`
|
| 8 |
+
defines models trained on the data as Adapted Material and requires its use
|
| 9 |
+
restrictions and licence copy to accompany distribution; those restrictions apply
|
| 10 |
+
in addition to CC BY 4.0.
|
| 11 |
+
|
| 12 |
+
FT Speech material was also used; its source statement is at
|
| 13 |
+
`LICENSES/FTSPEECH-LICENSE.md`. The effect of those terms on redistributed weights
|
| 14 |
+
is not settled by this notice. The project owner has chosen to proceed with the
|
| 15 |
+
source statement and Folketinget links attached; no separate legal opinion is
|
| 16 |
+
claimed.
|
| 17 |
+
|
| 18 |
+
NST text was also used. The publisher's
|
| 19 |
+
[`alexandrainst/nst-da` dataset card](https://huggingface.co/datasets/alexandrainst/nst-da)
|
| 20 |
+
identifies its license as CC0 1.0. The legal code is included at
|
| 21 |
+
`LICENSES/CC0-1.0.txt`.
|
| 22 |
+
|
| 23 |
+
This notice is not legal advice.
|
model-terms/pnc/NOTICE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ekko-pnc-stage3a is derived from jonfd/electra-small-nordic (CC BY 4.0).
|
| 2 |
+
|
| 3 |
+
Modifications by RyeAI: a fused Danish punctuation and capitalization head,
|
| 4 |
+
a running-text fine-tune (stage 3a), a boundary-logit calibration folded into
|
| 5 |
+
the classifier bias, and ONNX exports. Training text included CoRal, FT Speech
|
| 6 |
+
and NST; CoRal and FT Speech punctuation was restored by GPT-4o (Azure OpenAI).
|
| 7 |
+
|
| 8 |
+
See MODEL_LICENSE.md and LICENSES/ for applicable terms and attribution.
|
model-terms/tiny/LICENSES/CC-BY-4.0.txt
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Attribution 4.0 International
|
| 2 |
+
|
| 3 |
+
=======================================================================
|
| 4 |
+
|
| 5 |
+
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
| 6 |
+
does not provide legal services or legal advice. Distribution of
|
| 7 |
+
Creative Commons public licenses does not create a lawyer-client or
|
| 8 |
+
other relationship. Creative Commons makes its licenses and related
|
| 9 |
+
information available on an "as-is" basis. Creative Commons gives no
|
| 10 |
+
warranties regarding its licenses, any material licensed under their
|
| 11 |
+
terms and conditions, or any related information. Creative Commons
|
| 12 |
+
disclaims all liability for damages resulting from their use to the
|
| 13 |
+
fullest extent possible.
|
| 14 |
+
|
| 15 |
+
Using Creative Commons Public Licenses
|
| 16 |
+
|
| 17 |
+
Creative Commons public licenses provide a standard set of terms and
|
| 18 |
+
conditions that creators and other rights holders may use to share
|
| 19 |
+
original works of authorship and other material subject to copyright
|
| 20 |
+
and certain other rights specified in the public license below. The
|
| 21 |
+
following considerations are for informational purposes only, are not
|
| 22 |
+
exhaustive, and do not form part of our licenses.
|
| 23 |
+
|
| 24 |
+
Considerations for licensors: Our public licenses are
|
| 25 |
+
intended for use by those authorized to give the public
|
| 26 |
+
permission to use material in ways otherwise restricted by
|
| 27 |
+
copyright and certain other rights. Our licenses are
|
| 28 |
+
irrevocable. Licensors should read and understand the terms
|
| 29 |
+
and conditions of the license they choose before applying it.
|
| 30 |
+
Licensors should also secure all rights necessary before
|
| 31 |
+
applying our licenses so that the public can reuse the
|
| 32 |
+
material as expected. Licensors should clearly mark any
|
| 33 |
+
material not subject to the license. This includes other CC-
|
| 34 |
+
licensed material, or material used under an exception or
|
| 35 |
+
limitation to copyright. More considerations for licensors:
|
| 36 |
+
wiki.creativecommons.org/Considerations_for_licensors
|
| 37 |
+
|
| 38 |
+
Considerations for the public: By using one of our public
|
| 39 |
+
licenses, a licensor grants the public permission to use the
|
| 40 |
+
licensed material under specified terms and conditions. If
|
| 41 |
+
the licensor's permission is not necessary for any reason--for
|
| 42 |
+
example, because of any applicable exception or limitation to
|
| 43 |
+
copyright--then that use is not regulated by the license. Our
|
| 44 |
+
licenses grant only permissions under copyright and certain
|
| 45 |
+
other rights that a licensor has authority to grant. Use of
|
| 46 |
+
the licensed material may still be restricted for other
|
| 47 |
+
reasons, including because others have copyright or other
|
| 48 |
+
rights in the material. A licensor may make special requests,
|
| 49 |
+
such as asking that all changes be marked or described.
|
| 50 |
+
Although not required by our licenses, you are encouraged to
|
| 51 |
+
respect those requests where reasonable. More considerations
|
| 52 |
+
for the public:
|
| 53 |
+
wiki.creativecommons.org/Considerations_for_licensees
|
| 54 |
+
|
| 55 |
+
=======================================================================
|
| 56 |
+
|
| 57 |
+
Creative Commons Attribution 4.0 International Public License
|
| 58 |
+
|
| 59 |
+
By exercising the Licensed Rights (defined below), You accept and agree
|
| 60 |
+
to be bound by the terms and conditions of this Creative Commons
|
| 61 |
+
Attribution 4.0 International Public License ("Public License"). To the
|
| 62 |
+
extent this Public License may be interpreted as a contract, You are
|
| 63 |
+
granted the Licensed Rights in consideration of Your acceptance of
|
| 64 |
+
these terms and conditions, and the Licensor grants You such rights in
|
| 65 |
+
consideration of benefits the Licensor receives from making the
|
| 66 |
+
Licensed Material available under these terms and conditions.
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
Section 1 -- Definitions.
|
| 70 |
+
|
| 71 |
+
a. Adapted Material means material subject to Copyright and Similar
|
| 72 |
+
Rights that is derived from or based upon the Licensed Material
|
| 73 |
+
and in which the Licensed Material is translated, altered,
|
| 74 |
+
arranged, transformed, or otherwise modified in a manner requiring
|
| 75 |
+
permission under the Copyright and Similar Rights held by the
|
| 76 |
+
Licensor. For purposes of this Public License, where the Licensed
|
| 77 |
+
Material is a musical work, performance, or sound recording,
|
| 78 |
+
Adapted Material is always produced where the Licensed Material is
|
| 79 |
+
synched in timed relation with a moving image.
|
| 80 |
+
|
| 81 |
+
b. Adapter's License means the license You apply to Your Copyright
|
| 82 |
+
and Similar Rights in Your contributions to Adapted Material in
|
| 83 |
+
accordance with the terms and conditions of this Public License.
|
| 84 |
+
|
| 85 |
+
c. Copyright and Similar Rights means copyright and/or similar rights
|
| 86 |
+
closely related to copyright including, without limitation,
|
| 87 |
+
performance, broadcast, sound recording, and Sui Generis Database
|
| 88 |
+
Rights, without regard to how the rights are labeled or
|
| 89 |
+
categorized. For purposes of this Public License, the rights
|
| 90 |
+
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
| 91 |
+
Rights.
|
| 92 |
+
|
| 93 |
+
d. Effective Technological Measures means those measures that, in the
|
| 94 |
+
absence of proper authority, may not be circumvented under laws
|
| 95 |
+
fulfilling obligations under Article 11 of the WIPO Copyright
|
| 96 |
+
Treaty adopted on December 20, 1996, and/or similar international
|
| 97 |
+
agreements.
|
| 98 |
+
|
| 99 |
+
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
| 100 |
+
any other exception or limitation to Copyright and Similar Rights
|
| 101 |
+
that applies to Your use of the Licensed Material.
|
| 102 |
+
|
| 103 |
+
f. Licensed Material means the artistic or literary work, database,
|
| 104 |
+
or other material to which the Licensor applied this Public
|
| 105 |
+
License.
|
| 106 |
+
|
| 107 |
+
g. Licensed Rights means the rights granted to You subject to the
|
| 108 |
+
terms and conditions of this Public License, which are limited to
|
| 109 |
+
all Copyright and Similar Rights that apply to Your use of the
|
| 110 |
+
Licensed Material and that the Licensor has authority to license.
|
| 111 |
+
|
| 112 |
+
h. Licensor means the individual(s) or entity(ies) granting rights
|
| 113 |
+
under this Public License.
|
| 114 |
+
|
| 115 |
+
i. Share means to provide material to the public by any means or
|
| 116 |
+
process that requires permission under the Licensed Rights, such
|
| 117 |
+
as reproduction, public display, public performance, distribution,
|
| 118 |
+
dissemination, communication, or importation, and to make material
|
| 119 |
+
available to the public including in ways that members of the
|
| 120 |
+
public may access the material from a place and at a time
|
| 121 |
+
individually chosen by them.
|
| 122 |
+
|
| 123 |
+
j. Sui Generis Database Rights means rights other than copyright
|
| 124 |
+
resulting from Directive 96/9/EC of the European Parliament and of
|
| 125 |
+
the Council of 11 March 1996 on the legal protection of databases,
|
| 126 |
+
as amended and/or succeeded, as well as other essentially
|
| 127 |
+
equivalent rights anywhere in the world.
|
| 128 |
+
|
| 129 |
+
k. You means the individual or entity exercising the Licensed Rights
|
| 130 |
+
under this Public License. Your has a corresponding meaning.
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
Section 2 -- Scope.
|
| 134 |
+
|
| 135 |
+
a. License grant.
|
| 136 |
+
|
| 137 |
+
1. Subject to the terms and conditions of this Public License,
|
| 138 |
+
the Licensor hereby grants You a worldwide, royalty-free,
|
| 139 |
+
non-sublicensable, non-exclusive, irrevocable license to
|
| 140 |
+
exercise the Licensed Rights in the Licensed Material to:
|
| 141 |
+
|
| 142 |
+
a. reproduce and Share the Licensed Material, in whole or
|
| 143 |
+
in part; and
|
| 144 |
+
|
| 145 |
+
b. produce, reproduce, and Share Adapted Material.
|
| 146 |
+
|
| 147 |
+
2. Exceptions and Limitations. For the avoidance of doubt, where
|
| 148 |
+
Exceptions and Limitations apply to Your use, this Public
|
| 149 |
+
License does not apply, and You do not need to comply with
|
| 150 |
+
its terms and conditions.
|
| 151 |
+
|
| 152 |
+
3. Term. The term of this Public License is specified in Section
|
| 153 |
+
6(a).
|
| 154 |
+
|
| 155 |
+
4. Media and formats; technical modifications allowed. The
|
| 156 |
+
Licensor authorizes You to exercise the Licensed Rights in
|
| 157 |
+
all media and formats whether now known or hereafter created,
|
| 158 |
+
and to make technical modifications necessary to do so. The
|
| 159 |
+
Licensor waives and/or agrees not to assert any right or
|
| 160 |
+
authority to forbid You from making technical modifications
|
| 161 |
+
necessary to exercise the Licensed Rights, including
|
| 162 |
+
technical modifications necessary to circumvent Effective
|
| 163 |
+
Technological Measures. For purposes of this Public License,
|
| 164 |
+
simply making modifications authorized by this Section 2(a)
|
| 165 |
+
(4) never produces Adapted Material.
|
| 166 |
+
|
| 167 |
+
5. Downstream recipients.
|
| 168 |
+
|
| 169 |
+
a. Offer from the Licensor -- Licensed Material. Every
|
| 170 |
+
recipient of the Licensed Material automatically
|
| 171 |
+
receives an offer from the Licensor to exercise the
|
| 172 |
+
Licensed Rights under the terms and conditions of this
|
| 173 |
+
Public License.
|
| 174 |
+
|
| 175 |
+
b. No downstream restrictions. You may not offer or impose
|
| 176 |
+
any additional or different terms or conditions on, or
|
| 177 |
+
apply any Effective Technological Measures to, the
|
| 178 |
+
Licensed Material if doing so restricts exercise of the
|
| 179 |
+
Licensed Rights by any recipient of the Licensed
|
| 180 |
+
Material.
|
| 181 |
+
|
| 182 |
+
6. No endorsement. Nothing in this Public License constitutes or
|
| 183 |
+
may be construed as permission to assert or imply that You
|
| 184 |
+
are, or that Your use of the Licensed Material is, connected
|
| 185 |
+
with, or sponsored, endorsed, or granted official status by,
|
| 186 |
+
the Licensor or others designated to receive attribution as
|
| 187 |
+
provided in Section 3(a)(1)(A)(i).
|
| 188 |
+
|
| 189 |
+
b. Other rights.
|
| 190 |
+
|
| 191 |
+
1. Moral rights, such as the right of integrity, are not
|
| 192 |
+
licensed under this Public License, nor are publicity,
|
| 193 |
+
privacy, and/or other similar personality rights; however, to
|
| 194 |
+
the extent possible, the Licensor waives and/or agrees not to
|
| 195 |
+
assert any such rights held by the Licensor to the limited
|
| 196 |
+
extent necessary to allow You to exercise the Licensed
|
| 197 |
+
Rights, but not otherwise.
|
| 198 |
+
|
| 199 |
+
2. Patent and trademark rights are not licensed under this
|
| 200 |
+
Public License.
|
| 201 |
+
|
| 202 |
+
3. To the extent possible, the Licensor waives any right to
|
| 203 |
+
collect royalties from You for the exercise of the Licensed
|
| 204 |
+
Rights, whether directly or through a collecting society
|
| 205 |
+
under any voluntary or waivable statutory or compulsory
|
| 206 |
+
licensing scheme. In all other cases the Licensor expressly
|
| 207 |
+
reserves any right to collect such royalties.
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
Section 3 -- License Conditions.
|
| 211 |
+
|
| 212 |
+
Your exercise of the Licensed Rights is expressly made subject to the
|
| 213 |
+
following conditions.
|
| 214 |
+
|
| 215 |
+
a. Attribution.
|
| 216 |
+
|
| 217 |
+
1. If You Share the Licensed Material (including in modified
|
| 218 |
+
form), You must:
|
| 219 |
+
|
| 220 |
+
a. retain the following if it is supplied by the Licensor
|
| 221 |
+
with the Licensed Material:
|
| 222 |
+
|
| 223 |
+
i. identification of the creator(s) of the Licensed
|
| 224 |
+
Material and any others designated to receive
|
| 225 |
+
attribution, in any reasonable manner requested by
|
| 226 |
+
the Licensor (including by pseudonym if
|
| 227 |
+
designated);
|
| 228 |
+
|
| 229 |
+
ii. a copyright notice;
|
| 230 |
+
|
| 231 |
+
iii. a notice that refers to this Public License;
|
| 232 |
+
|
| 233 |
+
iv. a notice that refers to the disclaimer of
|
| 234 |
+
warranties;
|
| 235 |
+
|
| 236 |
+
v. a URI or hyperlink to the Licensed Material to the
|
| 237 |
+
extent reasonably practicable;
|
| 238 |
+
|
| 239 |
+
b. indicate if You modified the Licensed Material and
|
| 240 |
+
retain an indication of any previous modifications; and
|
| 241 |
+
|
| 242 |
+
c. indicate the Licensed Material is licensed under this
|
| 243 |
+
Public License, and include the text of, or the URI or
|
| 244 |
+
hyperlink to, this Public License.
|
| 245 |
+
|
| 246 |
+
2. You may satisfy the conditions in Section 3(a)(1) in any
|
| 247 |
+
reasonable manner based on the medium, means, and context in
|
| 248 |
+
which You Share the Licensed Material. For example, it may be
|
| 249 |
+
reasonable to satisfy the conditions by providing a URI or
|
| 250 |
+
hyperlink to a resource that includes the required
|
| 251 |
+
information.
|
| 252 |
+
|
| 253 |
+
3. If requested by the Licensor, You must remove any of the
|
| 254 |
+
information required by Section 3(a)(1)(A) to the extent
|
| 255 |
+
reasonably practicable.
|
| 256 |
+
|
| 257 |
+
4. If You Share Adapted Material You produce, the Adapter's
|
| 258 |
+
License You apply must not prevent recipients of the Adapted
|
| 259 |
+
Material from complying with this Public License.
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
Section 4 -- Sui Generis Database Rights.
|
| 263 |
+
|
| 264 |
+
Where the Licensed Rights include Sui Generis Database Rights that
|
| 265 |
+
apply to Your use of the Licensed Material:
|
| 266 |
+
|
| 267 |
+
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
| 268 |
+
to extract, reuse, reproduce, and Share all or a substantial
|
| 269 |
+
portion of the contents of the database;
|
| 270 |
+
|
| 271 |
+
b. if You include all or a substantial portion of the database
|
| 272 |
+
contents in a database in which You have Sui Generis Database
|
| 273 |
+
Rights, then the database in which You have Sui Generis Database
|
| 274 |
+
Rights (but not its individual contents) is Adapted Material; and
|
| 275 |
+
|
| 276 |
+
c. You must comply with the conditions in Section 3(a) if You Share
|
| 277 |
+
all or a substantial portion of the contents of the database.
|
| 278 |
+
|
| 279 |
+
For the avoidance of doubt, this Section 4 supplements and does not
|
| 280 |
+
replace Your obligations under this Public License where the Licensed
|
| 281 |
+
Rights include other Copyright and Similar Rights.
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
| 285 |
+
|
| 286 |
+
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
| 287 |
+
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
| 288 |
+
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
| 289 |
+
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
| 290 |
+
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
| 291 |
+
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
| 292 |
+
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
| 293 |
+
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
| 294 |
+
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
| 295 |
+
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
| 296 |
+
|
| 297 |
+
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
| 298 |
+
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
| 299 |
+
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
| 300 |
+
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
| 301 |
+
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
| 302 |
+
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
| 303 |
+
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
| 304 |
+
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
| 305 |
+
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
| 306 |
+
|
| 307 |
+
c. The disclaimer of warranties and limitation of liability provided
|
| 308 |
+
above shall be interpreted in a manner that, to the extent
|
| 309 |
+
possible, most closely approximates an absolute disclaimer and
|
| 310 |
+
waiver of all liability.
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
Section 6 -- Term and Termination.
|
| 314 |
+
|
| 315 |
+
a. This Public License applies for the term of the Copyright and
|
| 316 |
+
Similar Rights licensed here. However, if You fail to comply with
|
| 317 |
+
this Public License, then Your rights under this Public License
|
| 318 |
+
terminate automatically.
|
| 319 |
+
|
| 320 |
+
b. Where Your right to use the Licensed Material has terminated under
|
| 321 |
+
Section 6(a), it reinstates:
|
| 322 |
+
|
| 323 |
+
1. automatically as of the date the violation is cured, provided
|
| 324 |
+
it is cured within 30 days of Your discovery of the
|
| 325 |
+
violation; or
|
| 326 |
+
|
| 327 |
+
2. upon express reinstatement by the Licensor.
|
| 328 |
+
|
| 329 |
+
For the avoidance of doubt, this Section 6(b) does not affect any
|
| 330 |
+
right the Licensor may have to seek remedies for Your violations
|
| 331 |
+
of this Public License.
|
| 332 |
+
|
| 333 |
+
c. For the avoidance of doubt, the Licensor may also offer the
|
| 334 |
+
Licensed Material under separate terms or conditions or stop
|
| 335 |
+
distributing the Licensed Material at any time; however, doing so
|
| 336 |
+
will not terminate this Public License.
|
| 337 |
+
|
| 338 |
+
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
| 339 |
+
License.
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
Section 7 -- Other Terms and Conditions.
|
| 343 |
+
|
| 344 |
+
a. The Licensor shall not be bound by any additional or different
|
| 345 |
+
terms or conditions communicated by You unless expressly agreed.
|
| 346 |
+
|
| 347 |
+
b. Any arrangements, understandings, or agreements regarding the
|
| 348 |
+
Licensed Material not stated herein are separate from and
|
| 349 |
+
independent of the terms and conditions of this Public License.
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
Section 8 -- Interpretation.
|
| 353 |
+
|
| 354 |
+
a. For the avoidance of doubt, this Public License does not, and
|
| 355 |
+
shall not be interpreted to, reduce, limit, restrict, or impose
|
| 356 |
+
conditions on any use of the Licensed Material that could lawfully
|
| 357 |
+
be made without permission under this Public License.
|
| 358 |
+
|
| 359 |
+
b. To the extent possible, if any provision of this Public License is
|
| 360 |
+
deemed unenforceable, it shall be automatically reformed to the
|
| 361 |
+
minimum extent necessary to make it enforceable. If the provision
|
| 362 |
+
cannot be reformed, it shall be severed from this Public License
|
| 363 |
+
without affecting the enforceability of the remaining terms and
|
| 364 |
+
conditions.
|
| 365 |
+
|
| 366 |
+
c. No term or condition of this Public License will be waived and no
|
| 367 |
+
failure to comply consented to unless expressly agreed to by the
|
| 368 |
+
Licensor.
|
| 369 |
+
|
| 370 |
+
d. Nothing in this Public License constitutes or may be interpreted
|
| 371 |
+
as a limitation upon, or waiver of, any privileges and immunities
|
| 372 |
+
that apply to the Licensor or You, including from the legal
|
| 373 |
+
processes of any jurisdiction or authority.
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
=======================================================================
|
| 377 |
+
|
| 378 |
+
Creative Commons is not a party to its public
|
| 379 |
+
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
| 380 |
+
its public licenses to material it publishes and in those instances
|
| 381 |
+
will be considered the “Licensor.” The text of the Creative Commons
|
| 382 |
+
public licenses is dedicated to the public domain under the CC0 Public
|
| 383 |
+
Domain Dedication. Except for the limited purpose of indicating that
|
| 384 |
+
material is shared under a Creative Commons public license or as
|
| 385 |
+
otherwise permitted by the Creative Commons policies published at
|
| 386 |
+
creativecommons.org/policies, Creative Commons does not authorize the
|
| 387 |
+
use of the trademark "Creative Commons" or any other trademark or logo
|
| 388 |
+
of Creative Commons without its prior written consent including,
|
| 389 |
+
without limitation, in connection with any unauthorized modifications
|
| 390 |
+
to any of its public licenses or any other arrangements,
|
| 391 |
+
understandings, or agreements concerning use of licensed material. For
|
| 392 |
+
the avoidance of doubt, this paragraph does not form part of the
|
| 393 |
+
public licenses.
|
| 394 |
+
|
| 395 |
+
Creative Commons may be contacted at creativecommons.org.
|
| 396 |
+
|
model-terms/tiny/LICENSES/CORAL-LICENSE
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
LICENSED MATERIAL (INCLUDING DATA) - LICENSE TO USE
|
| 2 |
+
|
| 3 |
+
The Licensed Material (as defined below) is made available to You by Alexandra
|
| 4 |
+
Instituttet A/S, Åbogade 34, 8200 Aarhus N, Denmark and may be utilised solely in
|
| 5 |
+
accordance with the license terms stipulated in this document.
|
| 6 |
+
|
| 7 |
+
The license is based on "AI PUBS OPEN RAIL-M LICENSE" available at
|
| 8 |
+
www.licenses.ai/ai-licenses modified to fit the licensing of Data (hereinafter referred
|
| 9 |
+
to as "the Conditions"), a copy of the modified conditions is attached hereto, with the
|
| 10 |
+
following additions:
|
| 11 |
+
|
| 12 |
+
1. The license is governed by the laws of the Kingdom of Denmark
|
| 13 |
+
2. Any dispute arising out of or in connection herewith, including any disputes
|
| 14 |
+
regarding the existence, validity or termination of the license, shall be first
|
| 15 |
+
referred to mediation administered by the Danish Institute of Arbitration in
|
| 16 |
+
accordance with the Rules on Mediation adopted by the Board of the Danish Institute
|
| 17 |
+
of Arbitration. If the mediation proceedings are terminated without a settlement,
|
| 18 |
+
the dispute shall be finally settled by arbitration administered by the Danish
|
| 19 |
+
Institute of Arbitration in accordance with the Rules of Arbitration adopted by the
|
| 20 |
+
Board of the Danish Institute of Arbitration. The arbitral tribunal shall be
|
| 21 |
+
composed of three arbitrators. The place of arbitration shall be Aarhus, Denmark.
|
| 22 |
+
The language to be used in the arbitral proceedings shall be the English language.
|
| 23 |
+
3. If, at any time, the compilation, storage, utilisation, or processing of the
|
| 24 |
+
Licensed Material or the Adapted Material (all as defined below) constitute
|
| 25 |
+
violation of applicable laws, regardless of anything to the contrary in these
|
| 26 |
+
conditions, the license shall automatically become null and void without any
|
| 27 |
+
liability for the Licensor whatsoever.
|
| 28 |
+
4. Supplementing Attachment A to the Conditions, You additionally agree not to use the
|
| 29 |
+
Licensed Material or the Adapted Material:
|
| 30 |
+
|
| 31 |
+
(a) To impersonate any person or entity or otherwise misrepresent its affiliation
|
| 32 |
+
with a person or entity, including (but not limited to) the creation of
|
| 33 |
+
synthetic speech (i) emulating a specific natural person or (ii) which is found
|
| 34 |
+
to be similar to a specific natural person's speech (regardless of whether the
|
| 35 |
+
identity of such natural person is known at the time of the creation); or
|
| 36 |
+
(b) To detect or infer aspects and/or features of an identity of any natural
|
| 37 |
+
persons, such as name, family name, address, gender, sexual orientation, race,
|
| 38 |
+
religion, age, location (at any geographical level), skin color, society or
|
| 39 |
+
political affiliations, employment status and/or employment history, and health
|
| 40 |
+
and medical conditions.
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
CONDITIONS
|
| 44 |
+
|
| 45 |
+
Section I: PREAMBLE
|
| 46 |
+
|
| 47 |
+
These Conditions are based on OpenRAIL-M License adopted to fit the licensing of Data. A
|
| 48 |
+
version of the Conditions with all changes to the OpenRAIL-M License highlighted is
|
| 49 |
+
available at www.licenses.ai/ai-licenses. The “Open” nomenclature indicates that the
|
| 50 |
+
Licensed Material is freely accessible to downstream and other users. The “RAIL”
|
| 51 |
+
nomenclature indicates that there are use restrictions prohibiting the use of the
|
| 52 |
+
Licensed Material. These restrictions are intended to avoid potential misuse. Even
|
| 53 |
+
though Adapted Material could be released under different licensing terms, the
|
| 54 |
+
Conditions specify that the use restrictions in the original License must apply to such
|
| 55 |
+
Adapted Material.
|
| 56 |
+
|
| 57 |
+
NOW THEREFORE, You and Licensor agree as follows:
|
| 58 |
+
|
| 59 |
+
1. Definitions
|
| 60 |
+
|
| 61 |
+
(a) "Adapted Material" means material (including Models) derived from or based upon
|
| 62 |
+
the Licensed Material.
|
| 63 |
+
(b) "Data"” means a collection of information and/or content extracted from the
|
| 64 |
+
dataset used with the Model, including to train, pretrain, or otherwise evaluate
|
| 65 |
+
a Model. The Data form part of the Licensed Material.
|
| 66 |
+
(c) "Distribution" means any transmission, reproduction, publication or other
|
| 67 |
+
sharing of the Licensed Material or the Adapted Material to a third party,
|
| 68 |
+
including providing the Licensed Material or the Adapted Material as a hosted
|
| 69 |
+
service made available by electronic or other remote means - e.g. API-based or
|
| 70 |
+
web access.
|
| 71 |
+
(d) "Harm" includes but is not limited to physical, mental, psychological, financial
|
| 72 |
+
and reputational damage, pain, or loss
|
| 73 |
+
(e) "License" means the terms and conditions for use, reproduction, and Distribution
|
| 74 |
+
as defined in this document, including the additions and amendments stated
|
| 75 |
+
above.
|
| 76 |
+
(f) "Licensed Material" means the artistic or literary work, database, or other
|
| 77 |
+
material to which the Licensor applied this License.
|
| 78 |
+
(g) "Licensor" means the rights owner or entity authorized by the rights owner that
|
| 79 |
+
is granting the License, including the persons or entities that may have rights
|
| 80 |
+
in the Licensed Material or the Adapted Material and/or distributing the
|
| 81 |
+
Licensed Material or the Adapted Material.
|
| 82 |
+
(h) "Model" means any accompanying machine-learning based assemblies (including
|
| 83 |
+
checkpoints), consisting of learnt weights, parameters (including optimizer
|
| 84 |
+
states), that have been trained or tuned, in whole or in part on the Data, using
|
| 85 |
+
the Licensed Material. The term "Model" includes algorithmic assemblies,
|
| 86 |
+
including but not limited to machine-learning based assemblies trained on
|
| 87 |
+
Licensed Material as well as other material and/or data.
|
| 88 |
+
(i) "Output" means the results of operating a Model as embodied in informational
|
| 89 |
+
content resulting therefrom.
|
| 90 |
+
(j) "Third Parties" means individuals or legal entities that are not under common
|
| 91 |
+
control with Licensor or You.
|
| 92 |
+
(k) "You" (or "Your") means an individual or legal entity exercising permissions
|
| 93 |
+
granted by this License and/or making use of the Licensed Material for whichever
|
| 94 |
+
purpose and in any field of use, including usage of the Licensed Material or
|
| 95 |
+
Adapted Material in an end-use application - e.g. chatbot, translator, image
|
| 96 |
+
generator, speech recognizer, speech generator, adapter etc.
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
Section II: INTELLECTUAL PROPERTY RIGHTS
|
| 100 |
+
|
| 101 |
+
Both copyright and patent grants may apply to the Licensed Material or the Adapted
|
| 102 |
+
Material. The Licensed Material or the Adapted Material are subject to additional terms
|
| 103 |
+
as described in Section III, which shall govern the use of the Licensed Material or the
|
| 104 |
+
Adapted Material even in the event Section II is held unenforceable.
|
| 105 |
+
|
| 106 |
+
2. Grant of Copyright License. Subject to the terms and conditions of this License,
|
| 107 |
+
Licensor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
|
| 108 |
+
royalty-free, irrevocable copyright license to reproduce, prepare, publicly display,
|
| 109 |
+
publicly perform, sublicense, and distribute the Licensed Material or the Adapted
|
| 110 |
+
Material.
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
Section III: CONDITIONS OF USAGE, DISTRIBUTION AND REDISTRIBUTION
|
| 114 |
+
|
| 115 |
+
3. Distribution and Redistribution. You may host for Third Party remote access purposes
|
| 116 |
+
(e.g. software-as-a-service), reproduce and distribute copies of the Licensed
|
| 117 |
+
Material or the Adapted Material in any medium, with or without modifications,
|
| 118 |
+
provided that You meet the following conditions:
|
| 119 |
+
|
| 120 |
+
(a) Use-based restrictions in paragraph 4 MUST be included as an enforceable
|
| 121 |
+
provision by You in any type of legal agreement (e.g. a license) governing the
|
| 122 |
+
use and/or distribution of the Licensed Material or the Adapted Material, and
|
| 123 |
+
You shall give notice to subsequent users You Distribute to, that the Licensed
|
| 124 |
+
Material or the Adapted Material are subject to paragraph 4.
|
| 125 |
+
(b) You must give any Third Party recipients of the Licensed Material or the Adapted
|
| 126 |
+
Material a copy of this License;
|
| 127 |
+
(c) You must cause any modified files to carry prominent notices stating that You
|
| 128 |
+
changed the files;
|
| 129 |
+
(d) You must retain all copyright, patent, trademark, and attribution notices
|
| 130 |
+
excluding those notices that do not pertain to any part of the Licensed Material
|
| 131 |
+
or the Adapted Material. You may add Your own copyright statement to Your
|
| 132 |
+
modifications and may provide additional or different license terms and
|
| 133 |
+
conditions - respecting paragraph 3.a - for use, reproduction, or Distribution
|
| 134 |
+
of Your modifications, or for any such Adapted Material as a whole, provided
|
| 135 |
+
Your use, reproduction, and Distribution of the Licensed Material or the Adapted
|
| 136 |
+
Material otherwise complies with the conditions stated in this License.
|
| 137 |
+
|
| 138 |
+
4. Use-based restrictions. The restrictions set forth in Attachment A are considered
|
| 139 |
+
Use-based restrictions. Therefore You cannot use the Licensed Material or the Adapted
|
| 140 |
+
Material in violation of such restrictions. You may use the Licensed Material or the
|
| 141 |
+
Adapted Material subject to this License, including only for lawful purposes and in
|
| 142 |
+
accordance with the License. You shall require all of Your users who use the Licensed
|
| 143 |
+
Material or the Adapted Material to comply with the terms of this paragraph 4.
|
| 144 |
+
5. The Output You Generate. Except as set forth herein, Licensor claims no rights in the
|
| 145 |
+
Output You generate using the Licensed Material or the Adapted Material. You are
|
| 146 |
+
accountable for the Output you generate and its subsequent uses. No use of the output
|
| 147 |
+
can contravene any provision as stated in the License.
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
Section IV: OTHER PROVISIONS
|
| 151 |
+
|
| 152 |
+
6. Updates and Runtime Restrictions. To the maximum extent permitted by law, Licensor
|
| 153 |
+
reserves the right to restrict (remotely or otherwise) usage of the Licensed Material
|
| 154 |
+
or the Adapted Material in violation of this License or update the Licensed Material
|
| 155 |
+
through electronic means.
|
| 156 |
+
7. Trademarks and related. Nothing in this License permits You to make use of Licensors’
|
| 157 |
+
trademarks, trade names, logos or to otherwise suggest endorsement or misrepresent
|
| 158 |
+
the relationship between the parties; and any rights not expressly granted herein are
|
| 159 |
+
reserved by the Licensors.
|
| 160 |
+
8. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing,
|
| 161 |
+
Licensor provides the Licensed Material on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
| 162 |
+
CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any
|
| 163 |
+
warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR
|
| 164 |
+
A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness
|
| 165 |
+
of using or redistributing the Licensed Material or the Adapted Material, and assume
|
| 166 |
+
any risks associated with Your exercise of permissions under this License.
|
| 167 |
+
9. Limitation of Liability. In no event and under no legal theory, whether in tort
|
| 168 |
+
(including negligence), contract, or otherwise, unless required by applicable law
|
| 169 |
+
(such as deliberate and grossly negligent acts) or agreed to in writing, shall
|
| 170 |
+
Licensor be liable to You for damages, including any direct, indirect, special,
|
| 171 |
+
incidental, or consequential damages of any character arising as a result of this
|
| 172 |
+
License or out of the use or inability to use the Licensed Material (including but
|
| 173 |
+
not limited to damages for loss of goodwill, work stoppage, computer failure or
|
| 174 |
+
malfunction, or any and all other commercial damages or losses), even if Licensor has
|
| 175 |
+
been advised of the possibility of such damages.
|
| 176 |
+
10. Accepting Warranty or Additional Liability. While redistributing the Licensed
|
| 177 |
+
Material or the Adapted Material, You may choose to charge a fee in exchange for
|
| 178 |
+
support, warranty, indemnity, or other obligations and/or rights consistent with
|
| 179 |
+
this License. However, in accepting such obligations, You may act only on Your own
|
| 180 |
+
behalf and on Your sole responsibility, not on behalf of Licensor, and only if You
|
| 181 |
+
agree to indemnify, defend, and hold Licensor harmless for any liability incurred
|
| 182 |
+
by, or claims asserted against, Licensor by reason of your accepting any such
|
| 183 |
+
warranty or additional liability.
|
| 184 |
+
11. If any provision of this License is held to be invalid, illegal or unenforceable,
|
| 185 |
+
the remaining provisions shall be unaffected thereby and remain valid as if such
|
| 186 |
+
provision had not been set forth herein.
|
| 187 |
+
|
| 188 |
+
END OF TERMS AND CONDITIONS
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
Attachment A
|
| 192 |
+
|
| 193 |
+
USE RESTRICTIONS
|
| 194 |
+
|
| 195 |
+
You agree not to use the Licensed Material or the Adapted Material in any of the
|
| 196 |
+
following ways:
|
| 197 |
+
|
| 198 |
+
1. Legal:
|
| 199 |
+
(a) In any way that violates any applicable national, federal, state, local or
|
| 200 |
+
international law or regulation.
|
| 201 |
+
2. Harm and Discrimination
|
| 202 |
+
(a) For the purpose of exploiting, Harming or attempting to exploit or Harm minors
|
| 203 |
+
in any way;
|
| 204 |
+
(b) To generate or disseminate false information with the purpose of Harming others;
|
| 205 |
+
(c) To generate or disseminate personal identifiable information that can be used to
|
| 206 |
+
Harm an individual;
|
| 207 |
+
(d) To defame, disparage or otherwise harass others;
|
| 208 |
+
(e) For any use intended to or which has the effect of Harming individuals or groups
|
| 209 |
+
based on online or offline social behavior or known or predicted personal or
|
| 210 |
+
personality characteristics
|
| 211 |
+
(f) To exploit any of the vulnerabilities of a specific group of persons based on
|
| 212 |
+
their age, social, physical or mental characteristics, in order to materially
|
| 213 |
+
distort the behavior of a person belonging to that group in a manner that causes
|
| 214 |
+
or is likely to cause that person or another person Harm
|
| 215 |
+
(g) For any use intended to or which has the effect of discriminating against
|
| 216 |
+
individuals or groups based on legally protected characteristics or categories.
|
| 217 |
+
3. Transparency
|
| 218 |
+
(a) To generate or disseminate machine-generated information or content in any
|
| 219 |
+
medium without expressly and intelligibly disclaiming that it is
|
| 220 |
+
machine-generated;
|
| 221 |
+
(b) To impersonate or attempt to impersonate human beings for purposes of deception;
|
| 222 |
+
(c) For fully automated decision making that adversely impacts an individual’s legal
|
| 223 |
+
rights or otherwise creates or modifies a binding, enforceable obligation.
|
model-terms/tiny/LICENSES/FTSPEECH-LICENSE.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
layout: page
|
| 3 |
+
title: License
|
| 4 |
+
---
|
| 5 |
+
<br>
|
| 6 |
+
2020, **FT Speech**, [ftspeech.dk](ftspeech.dk)
|
| 7 |
+
|
| 8 |
+
Any use of FT Speech text and audio data must be in accordance with the following two licenses: [Folketing's open data](https://www.ft.dk/da/dokumenter/aabne_data#290AB29F56C54AC88474BC53393A3AE0) and [Folketing TV](https://www.ft.dk/da/aktuelt/tv-fra-folketinget/deling-og-rettigheder). The data released here must always be accompanied by this LICENSE statement and the two Folketing licenses.
|
model-terms/tiny/LICENSES/NVIDIA-OPEN-MODEL-LICENSE.pdf
ADDED
|
Binary file (79 kB). View file
|
|
|
model-terms/tiny/MODEL_LICENSE.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ekko v1 Tiny model terms
|
| 2 |
+
|
| 3 |
+
Ekko v1 Tiny is a Derivative Model of `nvidia/parakeet-rnnt-110m-da-dk` and is
|
| 4 |
+
subject to the NVIDIA Open Model License. The official agreement is included at
|
| 5 |
+
`LICENSES/NVIDIA-OPEN-MODEL-LICENSE.pdf`, and the required NVIDIA attribution is
|
| 6 |
+
in `NOTICE`.
|
| 7 |
+
|
| 8 |
+
RyeAI applies Creative Commons Attribution 4.0 International to the
|
| 9 |
+
modifications it has the right to license. A copy is included at
|
| 10 |
+
`LICENSES/CC-BY-4.0.txt`. This does not replace the NVIDIA agreement.
|
| 11 |
+
|
| 12 |
+
The model was trained on CoRal data. The included `LICENSES/CORAL-LICENSE`
|
| 13 |
+
defines models trained on the data as Adapted Material and requires its use
|
| 14 |
+
restrictions and license copy to accompany distribution. Those restrictions
|
| 15 |
+
apply in addition to the NVIDIA agreement.
|
| 16 |
+
|
| 17 |
+
FT Speech was also used. Its source statement is included at
|
| 18 |
+
`LICENSES/FTSPEECH-LICENSE.md` and points to the applicable Folketinget terms.
|
| 19 |
+
The effect of those terms on redistributed trained weights must be approved
|
| 20 |
+
before this repository is made public.
|
| 21 |
+
|
| 22 |
+
See `README.md` for provenance, modifications, limitations, and attribution.
|
| 23 |
+
This notice is not legal advice.
|
model-terms/tiny/NOTICE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Ekko v1 Tiny is derived from nvidia/parakeet-rnnt-110m-da-dk.
|
| 2 |
+
|
| 3 |
+
Licensed by NVIDIA Corporation under the NVIDIA Open Model License.
|
| 4 |
+
|
| 5 |
+
Modifications by RyeAI include Danish domain adaptation and quantized runtime
|
| 6 |
+
artifacts. See the model card for training-data provenance, additional terms,
|
| 7 |
+
and the official NVIDIA license. The agreement is included at
|
| 8 |
+
`LICENSES/NVIDIA-OPEN-MODEL-LICENSE.pdf`.
|
ort-wasm-simd-threaded.mjs
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
async function ortWasmThreaded(moduleArg={}){var moduleRtn;var h=moduleArg,aa=!!globalThis.window,k=!!globalThis.WorkerGlobalScope,m=globalThis.process?.versions?.node&&"renderer"!=globalThis.process?.type,n=k&&self.name?.startsWith("em-pthread");if(m){const {createRequire:a}=await import("module");var require=a(import.meta.url),ba=require("worker_threads");global.Worker=ba.Worker;n=(k=!ba.hc)&&"em-pthread"==ba.workerData}h.mountExternalData=(a,b)=>{a.startsWith("./")&&(a=a.substring(2));(h.Rb||(h.Rb=new Map)).set(a,b)};
|
| 2 |
+
h.unmountExternalData=()=>{delete h.Rb;delete h.kc;delete h.jc;delete h.lc};var SharedArrayBuffer=globalThis.SharedArrayBuffer??(new WebAssembly.Memory({initial:0,maximum:0,shared:!0})).buffer.constructor,ca="./this.program",da=(a,b)=>{throw b;},ea=import.meta.url,fa="",ha,ia;
|
| 3 |
+
if(m){var fs=require("fs");ea.startsWith("file:")&&(fa=require("path").dirname(require("url").fileURLToPath(ea))+"/");ia=a=>{a=ja(a)?new URL(a):a;return fs.readFileSync(a)};ha=async a=>{a=ja(a)?new URL(a):a;return fs.readFileSync(a,void 0)};1<process.argv.length&&(ca=process.argv[1].replace(/\\/g,"/"));process.argv.slice(2);da=(a,b)=>{process.exitCode=a;throw b;}}else if(aa||k){try{fa=(new URL(".",ea)).href}catch{}m||(k&&(ia=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";
|
| 4 |
+
b.send(null);return new Uint8Array(b.response)}),ha=async a=>{if(ja(a))return new Promise((d,c)=>{var e=new XMLHttpRequest;e.open("GET",a,!0);e.responseType="arraybuffer";e.onload=()=>{200==e.status||0==e.status&&e.response?d(e.response):c(e.status)};e.onerror=c;e.send(null)});var b=await fetch(a,{credentials:"same-origin"});if(b.ok)return b.arrayBuffer();throw Error(b.status+" : "+b.url);})}var ka=console.log.bind(console),la=console.error.bind(console);
|
| 5 |
+
if(m){var ma=require("util"),na=a=>"object"==typeof a?ma.inspect(a):a;ka=(...a)=>fs.writeSync(1,a.map(na).join(" ")+"\n");la=(...a)=>fs.writeSync(2,a.map(na).join(" ")+"\n")}var oa=ka,p=la,q,r,pa=!1,t,ja=a=>a.startsWith("file://");function v(){x.buffer!=z.buffer&&qa()}var ra,sa;
|
| 6 |
+
if(m&&n){var ta=ba.parentPort;ta.on("message",a=>global.onmessage?.({data:a}));Object.assign(globalThis,{self:global,postMessage:a=>ta.postMessage(a)});process.on("uncaughtException",a=>{postMessage({Pb:"uncaughtException",error:a});process.exit(1)})}var ua;
|
| 7 |
+
if(n){var va=!1;self.onunhandledrejection=b=>{throw b.reason||b;};function a(b){try{var d=b.data,c=d.Pb;if("load"===c){let e=[];self.onmessage=f=>e.push(f);ua=()=>{postMessage({Pb:"loaded"});for(let f of e)a(f);self.onmessage=a};for(const f of d.Zb)if(!h[f]||h[f].proxy)h[f]=(...g)=>{postMessage({Pb:"callHandler",Yb:f,args:g})},"print"==f&&(oa=h[f]),"printErr"==f&&(p=h[f]);x=d.dc;qa();r=d.ec;wa();xa()}else if("run"===c){ya(d.Ob);za(d.Ob,0,0,1,0,0);Aa();Ba(d.Ob);va||=!0;try{Ca(d.bc,d.Tb)}catch(e){if("unwind"!=
|
| 8 |
+
e)throw e;}}else"setimmediate"!==d.target&&("checkMailbox"===c?va&&Da():c&&(p(`worker: received unknown command ${c}`),p(d)))}catch(e){throw Ea(),e;}}self.onmessage=a}var z,A,Fa,C,D,Ga,G,H,Ha=!1;function qa(){var a=x.buffer;h.HEAP8=z=new Int8Array(a);Fa=new Int16Array(a);h.HEAPU8=A=new Uint8Array(a);new Uint16Array(a);h.HEAP32=C=new Int32Array(a);h.HEAPU32=D=new Uint32Array(a);Ga=new Float32Array(a);G=new Float64Array(a);H=new BigInt64Array(a);new BigUint64Array(a)}
|
| 9 |
+
function Ia(){Ha=!0;n?ua():I.Ta()}function J(a){a="Aborted("+a+")";p(a);pa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");sa?.(a);throw a;}var Ja;async function Ka(a){if(!q)try{var b=await ha(a);return new Uint8Array(b)}catch{}if(a==Ja&&q)a=new Uint8Array(q);else if(ia)a=ia(a);else throw"both async and sync fetching of the wasm failed";return a}
|
| 10 |
+
async function La(a,b){try{var d=await Ka(a);return await WebAssembly.instantiate(d,b)}catch(c){p(`failed to asynchronously prepare wasm: ${c}`),J(c)}}async function Na(a){var b=Ja;if(!q&&!ja(b)&&!m)try{var d=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(d,a)}catch(c){p(`wasm streaming compile failed: ${c}`),p("falling back to ArrayBuffer instantiation")}return La(b,a)}
|
| 11 |
+
function Oa(){Pa={T:Qa,f:Ra,w:Sa,e:Ta,k:Ua,h:Va,L:Wa,b:Xa,G:Ya,ta:Za,j:$a,M:ab,Ja:bb,pa:cb,ra:db,Ka:eb,Ha:fb,Aa:gb,Ga:hb,Z:ib,qa:jb,na:kb,Ia:lb,oa:mb,Pa:nb,Da:ob,la:pb,ua:qb,ia:rb,U:sb,Ca:Ba,Ma:tb,xa:ub,ya:vb,za:wb,va:xb,wa:yb,ja:zb,Ra:Ab,Oa:Bb,W:Cb,V:Db,Na:Eb,F:Fb,La:Gb,ma:Hb,u:Ib,H:Jb,R:Kb,ka:Lb,ba:Mb,Sa:Nb,Ea:Ob,Fa:Pb,sa:Qb,I:Rb,Y:Sb,Ba:Tb,X:Ub,$:Vb,N:Wb,aa:Xb,O:Yb,v:Zb,d:$b,m:ac,n:bc,r:cc,ca:dc,E:ec,o:fc,P:gc,C:hc,J:ic,da:jc,ea:kc,z:lc,Q:mc,fa:nc,y:oc,D:pc,c:qc,q:rc,i:sc,_:tc,l:uc,p:vc,s:wc,t:xc,
|
| 12 |
+
x:yc,S:zc,A:Ac,K:Bc,B:Cc,ga:Dc,ha:Ec,g:Fc,a:x,Qa:Gc};return{a:Pa}}
|
| 13 |
+
async function wa(){function a(c,e){I=c.exports;I=Hc();Ic.push(I.vb);c=I;h._OrtInit=c.Ua;h._OrtGetLastError=c.Va;h._OrtCreateSessionOptions=c.Wa;h._OrtAppendExecutionProvider=c.Xa;h._OrtAddFreeDimensionOverride=c.Ya;h._OrtAddSessionConfigEntry=c.Za;h._OrtReleaseSessionOptions=c._a;h._OrtCreateSession=c.$a;h._OrtReleaseSession=c.ab;h._OrtGetInputOutputCount=c.bb;h._OrtGetInputOutputMetadata=c.cb;h._OrtFree=c.db;h._OrtCreateTensor=c.eb;h._OrtGetTensorData=c.fb;h._OrtReleaseTensor=c.gb;h._OrtCreateRunOptions=
|
| 14 |
+
c.hb;h._OrtAddRunConfigEntry=c.ib;h._OrtReleaseRunOptions=c.jb;h._OrtCreateBinding=c.kb;h._OrtBindInput=c.lb;h._OrtBindOutput=c.mb;h._OrtClearBoundOutputs=c.nb;h._OrtReleaseBinding=c.ob;h._OrtRunWithBinding=c.pb;h._OrtRun=c.qb;h._OrtEndProfiling=c.rb;Jc=c.sb;Kc=h._free=c.tb;Lc=h._malloc=c.ub;za=c.xb;Ea=c.yb;Mc=c.zb;Nc=c.Ab;Oc=c.Bb;Pc=c.Cb;Qc=c.Db;K=c.Eb;L=c.Fb;Rc=c.Gb;M=c.Hb;Sc=c.Ib;N=c.Jb;Tc=c.Kb;Uc=c.Lb;Vc=c.Mb;Wc=c.Nb;Xc=c.wb;r=e;return I}var b=Oa();if(h.instantiateWasm)return new Promise(c=>{h.instantiateWasm(b,
|
| 15 |
+
(e,f)=>{c(a(e,f))})});if(n){var d=new WebAssembly.Instance(r,Oa());return a(d,r)}Ja??=h.locateFile?h.locateFile?h.locateFile("ort-wasm-simd-threaded.wasm",fa):fa+"ort-wasm-simd-threaded.wasm":(new URL("ort-wasm-simd-threaded.wasm",import.meta.url)).href;return function(c){return a(c.instance,c.module)}(await Na(b))}class Yc{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}
|
| 16 |
+
var Zc=a=>{a.terminate();a.onmessage=()=>{}},$c=[],O=0,P=null,cd=a=>{0==Q.length&&(ad(),bd(Q[0]));var b=Q.pop();if(!b)return 6;R.push(b);S[a.Ob]=b;b.Ob=a.Ob;var d={Pb:"run",bc:a.ac,Tb:a.Tb,Ob:a.Ob};m&&b.unref();b.postMessage(d,a.Xb);return 0},T=0,U=(a,b,...d)=>{var c=16*d.length,e=N(),f=Sc(c),g=f>>>3,l;for(l of d)"bigint"==typeof l?((v(),H)[g++>>>0]=1n,(v(),H)[g++>>>0]=l):((v(),H)[g++>>>0]=0n,(v(),G)[g++>>>0]=l);a=Mc(a,0,c,f,b);M(e);return a};
|
| 17 |
+
function Gc(a){if(n)return U(0,1,a);t=a;if(!(0<T)){for(var b of R)Zc(b);for(b of Q)Zc(b);Q=[];R=[];S={};pa=!0}da(a,new Yc(a))}function dd(a){if(n)return U(1,0,a);Qb(a)}var Qb=a=>{t=a;if(n)throw dd(a),"unwind";Gc(a)},Q=[],R=[],Ic=[],S={};function ed(){for(var a=h.numThreads-1;a--;)ad();$c.push(async()=>{var b=fd();O++;await b;O--;0==O&&P&&(b=P,P=null,b())})}var gd=a=>{var b=a.Ob;delete S[b];Q.push(a);R.splice(R.indexOf(a),1);a.Ob=0;Nc(b)};function Aa(){Ic.forEach(a=>a())}
|
| 18 |
+
var bd=a=>new Promise(b=>{a.onmessage=f=>{var g=f.data;f=g.Pb;if(g.Sb&&g.Sb!=Jc()){var l=S[g.Sb];l?l.postMessage(g,g.Xb):p(`Internal error! Worker sent a message "${f}" to target pthread ${g.Sb}, but that thread no longer exists!`)}else if("checkMailbox"===f)Da();else if("spawnThread"===f)cd(g);else if("cleanupThread"===f)hd(()=>{gd(S[g.cc])});else if("loaded"===f)a.loaded=!0,m&&!a.Ob&&a.unref(),b(a);else if("setimmediate"===g.target)a.postMessage(g);else if("uncaughtException"===f)a.onerror(g.error);
|
| 19 |
+
else if("callHandler"===f)h[g.Yb](...g.args);else f&&p(`worker sent an unknown command ${f}`)};a.onerror=f=>{p(`${"worker sent an error!"} ${f.filename}:${f.lineno}: ${f.message}`);throw f;};m&&(a.on("message",f=>a.onmessage({data:f})),a.on("error",f=>a.onerror(f)));var d=[],c=[],e;for(e of c)h.propertyIsEnumerable(e)&&d.push(e);a.postMessage({Pb:"load",Zb:d,dc:x,ec:r})});async function fd(){if(!n)return Promise.all(Q.map(bd))}
|
| 20 |
+
function ad(){var a=new Worker(new URL(import.meta.url),{type:"module",workerData:"em-pthread",name:"em-pthread"});Q.push(a)}function ya(a){var b=(v(),D)[a+52>>>2>>>0];a=(v(),D)[a+56>>>2>>>0];Rc(b,b-a);M(b)}var jd=[],V=a=>{var b=jd[a];b||(jd[a]=b=Xc.get(a));return b},Ca=(a,b)=>{T=0;a=V(a)(b);0<T?t=a:Oc(a)},x,kd=[],ld=0;function Ra(a){a>>>=0;var b=new md(a);0==(v(),z)[b.Qb+12>>>0]&&(nd(b,!0),ld--);od(b,!1);kd.push(b);return Wc(a)}
|
| 21 |
+
var W=0,Sa=()=>{K(0,0);var a=kd.pop();Tc(a.Ub);W=0};function nd(a,b){b=b?1:0;(v(),z)[a.Qb+12>>>0]=b}function od(a,b){b=b?1:0;(v(),z)[a.Qb+13>>>0]=b}class md{constructor(a){this.Ub=a;this.Qb=a-24}}var pd=a=>{var b=W;if(!b)return L(0),0;var d=new md(b);(v(),D)[d.Qb+16>>>2>>>0]=b;var c=(v(),D)[d.Qb+4>>>2>>>0];if(!c)return L(0),b;for(var e of a){if(0===e||e===c)break;if(Vc(e,c,d.Qb+16))return L(e),b}L(c);return b};function Ta(){return pd([])}function Ua(a){return pd([a>>>0])}
|
| 22 |
+
function Va(a,b,d,c){return pd([a>>>0,b>>>0,d>>>0,c>>>0])}var Wa=()=>{var a=kd.pop();a||J("no exception to throw");var b=a.Ub;0==(v(),z)[a.Qb+13>>>0]&&(kd.push(a),od(a,!0),nd(a,!1),ld++);Uc(b);W=b;throw W;};function Xa(a,b,d){a>>>=0;var c=new md(a);b>>>=0;d>>>=0;(v(),D)[c.Qb+16>>>2>>>0]=0;(v(),D)[c.Qb+4>>>2>>>0]=b;(v(),D)[c.Qb+8>>>2>>>0]=d;Uc(a);W=a;ld++;throw W;}var Ya=()=>ld;function qd(a,b,d,c){return n?U(2,1,a,b,d,c):Za(a,b,d,c)}
|
| 23 |
+
function Za(a,b,d,c){a>>>=0;b>>>=0;d>>>=0;c>>>=0;if(!globalThis.SharedArrayBuffer)return 6;var e=[];if(n&&0===e.length)return qd(a,b,d,c);a={ac:d,Ob:a,Tb:c,Xb:e};return n?(a.Pb="spawnThread",postMessage(a,e),0):cd(a)}function $a(a){W||=a>>>0;throw W;}
|
| 24 |
+
var rd=globalThis.TextDecoder&&new TextDecoder,sd=(a,b=0,d,c)=>{b>>>=0;var e=b;d=e+d;if(c)c=d;else{for(;a[e]&&!(e>=d);)++e;c=e}if(16<c-b&&a.buffer&&rd)return rd.decode(a.buffer instanceof ArrayBuffer?a.subarray(b,c):a.slice(b,c));for(e="";b<c;)if(d=a[b++],d&128){var f=a[b++]&63;if(192==(d&224))e+=String.fromCharCode((d&31)<<6|f);else{var g=a[b++]&63;d=224==(d&240)?(d&15)<<12|f<<6|g:(d&7)<<18|f<<12|g<<6|a[b++]&63;65536>d?e+=String.fromCharCode(d):(d-=65536,e+=String.fromCharCode(55296|d>>10,56320|
|
| 25 |
+
d&1023))}}else e+=String.fromCharCode(d);return e},td=(a,b,d)=>(a>>>=0)?sd((v(),A),a,b,d):"";function ab(a,b,d){return n?U(3,1,a,b,d):0}function bb(a,b){if(n)return U(4,1,a,b)}function cb(a,b){if(n)return U(5,1,a,b)}function db(a,b,d){if(n)return U(6,1,a,b,d)}function eb(a,b,d){return n?U(7,1,a,b,d):0}function fb(a,b){if(n)return U(8,1,a,b)}function gb(a,b,d){if(n)return U(9,1,a,b,d)}function hb(a,b,d,c){if(n)return U(10,1,a,b,d,c)}function ib(a,b,d,c){if(n)return U(11,1,a,b,d,c)}
|
| 26 |
+
function jb(a,b,d,c){if(n)return U(12,1,a,b,d,c)}function kb(a){if(n)return U(13,1,a)}function lb(a,b){if(n)return U(14,1,a,b)}function mb(a,b,d){if(n)return U(15,1,a,b,d)}var nb=()=>J("");function ob(a){za(a>>>0,!k,1,!aa,131072,!1);Aa()}
|
| 27 |
+
var hd=a=>{if(!pa)try{if(a(),!(0<T))try{n?Jc()&&Oc(t):Qb(t)}catch(b){b instanceof Yc||"unwind"==b||da(1,b)}}catch(b){b instanceof Yc||"unwind"==b||da(1,b)}},ud=!Atomics.waitAsync||globalThis.navigator?.userAgent&&91>Number((navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)||[])[2]);function Ba(a){a>>>=0;ud||(Atomics.waitAsync((v(),C),a>>>2,a).value.then(Da),a+=128,Atomics.store((v(),C),a>>>2,1))}var Da=()=>hd(()=>{var a=Jc();a&&(Ba(a),Qc())});
|
| 28 |
+
function pb(a,b){a>>>=0;a==b>>>0?setTimeout(Da):n?postMessage({Sb:a,Pb:"checkMailbox"}):(a=S[a])&&a.postMessage({Pb:"checkMailbox"})}var vd=[];function qb(a,b,d,c,e){b>>>=0;e>>>=0;vd.length=0;d=e>>>3;for(c=e+c>>>3;d<c;){var f;(v(),H)[d++>>>0]?f=(v(),H)[d++>>>0]:f=(v(),G)[d++>>>0];vd.push(f)}return(b?wd[b]:xd[a])(...vd)}var rb=()=>{T=0};function sb(a){a>>>=0;n?postMessage({Pb:"cleanupThread",cc:a}):gd(S[a])}function tb(a){m&&S[a>>>0].ref()}
|
| 29 |
+
function ub(a,b){a=-9007199254740992>a||9007199254740992<a?NaN:Number(a);b>>>=0;a=new Date(1E3*a);(v(),C)[b>>>2>>>0]=a.getUTCSeconds();(v(),C)[b+4>>>2>>>0]=a.getUTCMinutes();(v(),C)[b+8>>>2>>>0]=a.getUTCHours();(v(),C)[b+12>>>2>>>0]=a.getUTCDate();(v(),C)[b+16>>>2>>>0]=a.getUTCMonth();(v(),C)[b+20>>>2>>>0]=a.getUTCFullYear()-1900;(v(),C)[b+24>>>2>>>0]=a.getUTCDay();a=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0;(v(),C)[b+28>>>2>>>0]=a}
|
| 30 |
+
var yd=a=>0===a%4&&(0!==a%100||0===a%400),zd=[0,31,60,91,121,152,182,213,244,274,305,335],Ad=[0,31,59,90,120,151,181,212,243,273,304,334];
|
| 31 |
+
function vb(a,b){a=-9007199254740992>a||9007199254740992<a?NaN:Number(a);b>>>=0;a=new Date(1E3*a);(v(),C)[b>>>2>>>0]=a.getSeconds();(v(),C)[b+4>>>2>>>0]=a.getMinutes();(v(),C)[b+8>>>2>>>0]=a.getHours();(v(),C)[b+12>>>2>>>0]=a.getDate();(v(),C)[b+16>>>2>>>0]=a.getMonth();(v(),C)[b+20>>>2>>>0]=a.getFullYear()-1900;(v(),C)[b+24>>>2>>>0]=a.getDay();var d=(yd(a.getFullYear())?zd:Ad)[a.getMonth()]+a.getDate()-1|0;(v(),C)[b+28>>>2>>>0]=d;(v(),C)[b+36>>>2>>>0]=-(60*a.getTimezoneOffset());d=(new Date(a.getFullYear(),
|
| 32 |
+
6,1)).getTimezoneOffset();var c=(new Date(a.getFullYear(),0,1)).getTimezoneOffset();a=(d!=c&&a.getTimezoneOffset()==Math.min(c,d))|0;(v(),C)[b+32>>>2>>>0]=a}
|
| 33 |
+
function wb(a){a>>>=0;var b=new Date((v(),C)[a+20>>>2>>>0]+1900,(v(),C)[a+16>>>2>>>0],(v(),C)[a+12>>>2>>>0],(v(),C)[a+8>>>2>>>0],(v(),C)[a+4>>>2>>>0],(v(),C)[a>>>2>>>0],0),d=(v(),C)[a+32>>>2>>>0],c=b.getTimezoneOffset(),e=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),f=(new Date(b.getFullYear(),0,1)).getTimezoneOffset(),g=Math.min(f,e);0>d?(v(),C)[a+32>>>2>>>0]=Number(e!=f&&g==c):0<d!=(g==c)&&(e=Math.max(f,e),b.setTime(b.getTime()+6E4*((0<d?g:e)-c)));(v(),C)[a+24>>>2>>>0]=b.getDay();d=(yd(b.getFullYear())?
|
| 34 |
+
zd:Ad)[b.getMonth()]+b.getDate()-1|0;(v(),C)[a+28>>>2>>>0]=d;(v(),C)[a>>>2>>>0]=b.getSeconds();(v(),C)[a+4>>>2>>>0]=b.getMinutes();(v(),C)[a+8>>>2>>>0]=b.getHours();(v(),C)[a+12>>>2>>>0]=b.getDate();(v(),C)[a+16>>>2>>>0]=b.getMonth();(v(),C)[a+20>>>2>>>0]=b.getYear();a=b.getTime();return BigInt(isNaN(a)?-1:a/1E3)}function xb(a,b,d,c,e,f,g){return n?U(16,1,a,b,d,c,e,f,g):-52}function yb(a,b,d,c,e,f){if(n)return U(17,1,a,b,d,c,e,f)}var X={},Ib=()=>performance.timeOrigin+performance.now();
|
| 35 |
+
function zb(a,b){if(n)return U(18,1,a,b);X[a]&&(clearTimeout(X[a].id),delete X[a]);if(!b)return 0;var d=setTimeout(()=>{delete X[a];hd(()=>Pc(a,performance.timeOrigin+performance.now()))},b);X[a]={id:d,mc:b};return 0}
|
| 36 |
+
var Y=(a,b,d)=>{var c=(v(),A);b>>>=0;if(0<d){var e=b;d=b+d-1;for(var f=0;f<a.length;++f){var g=a.codePointAt(f);if(127>=g){if(b>=d)break;c[b++>>>0]=g}else if(2047>=g){if(b+1>=d)break;c[b++>>>0]=192|g>>6;c[b++>>>0]=128|g&63}else if(65535>=g){if(b+2>=d)break;c[b++>>>0]=224|g>>12;c[b++>>>0]=128|g>>6&63;c[b++>>>0]=128|g&63}else{if(b+3>=d)break;c[b++>>>0]=240|g>>18;c[b++>>>0]=128|g>>12&63;c[b++>>>0]=128|g>>6&63;c[b++>>>0]=128|g&63;f++}}c[b>>>0]=0;a=b-e}else a=0;return a};
|
| 37 |
+
function Ab(a,b,d,c){a>>>=0;b>>>=0;d>>>=0;c>>>=0;var e=(new Date).getFullYear(),f=(new Date(e,0,1)).getTimezoneOffset();e=(new Date(e,6,1)).getTimezoneOffset();var g=Math.max(f,e);(v(),D)[a>>>2>>>0]=60*g;(v(),C)[b>>>2>>>0]=Number(f!=e);b=l=>{var u=Math.abs(l);return`UTC${0<=l?"-":"+"}${String(Math.floor(u/60)).padStart(2,"0")}${String(u%60).padStart(2,"0")}`};a=b(f);b=b(e);e<f?(Y(a,d,17),Y(b,c,17)):(Y(a,c,17),Y(b,d,17))}var Eb=()=>Date.now(),Bd=1;
|
| 38 |
+
function Bb(a,b,d){d>>>=0;if(!(0<=a&&3>=a))return 28;if(0===a)a=Date.now();else if(Bd)a=performance.timeOrigin+performance.now();else return 52;a=Math.round(1E6*a);(v(),H)[d>>>3>>>0]=BigInt(a);return 0}var Cd=[];function Cb(a,b,d){a>>>=0;b>>>=0;d>>>=0;Cd.length=0;for(var c;c=(v(),A)[b++>>>0];){var e=105!=c;e&=112!=c;d+=e&&d%8?4:0;Cd.push(112==c?(v(),D)[d>>>2>>>0]:106==c?(v(),H)[d>>>3>>>0]:105==c?(v(),C)[d>>>2>>>0]:(v(),G)[d>>>3>>>0]);d+=e?8:4}return wd[a](...Cd)}var Db=()=>{};
|
| 39 |
+
function Fb(a,b){return p(td(a>>>0,b>>>0))}var Gb=()=>{T+=1;throw"unwind";};function Hb(){return 4294901760}var Jb=()=>m?require("os").cpus().length:navigator.hardwareConcurrency,Z={},Dd=a=>{for(var b=0,d=0;d<a.length;++d){var c=a.charCodeAt(d);127>=c?b++:2047>=c?b+=2:55296<=c&&57343>=c?(b+=4,++d):b+=3}return b},Ed=a=>{var b;return(b=/\bwasm-function\[\d+\]:(0x[0-9a-f]+)/.exec(a))?+b[1]:(b=/:(\d+):\d+(?:\)|$)/.exec(a))?2147483648|+b[1]:0},Fd=a=>{for(var b of a)(a=Ed(b))&&(Z[a]=b)};
|
| 40 |
+
function Mb(){var a=Error().stack.toString().split("\n");"Error"==a[0]&&a.shift();Fd(a);Z.Vb=Ed(a[3]);Z.$b=a;return Z.Vb}function Kb(a){a=Z[a>>>0];if(!a)return 0;var b;if(b=/^\s+at .*\.wasm\.(.*) \(.*\)$/.exec(a))a=b[1];else if(b=/^\s+at (.*) \(.*\)$/.exec(a))a=b[1];else if(b=/^(.+?)@/.exec(a))a=b[1];else return 0;Kc(Kb.Wb??0);b=Dd(a)+1;var d=Lc(b);d&&Y(a,d,b);Kb.Wb=d;return Kb.Wb}
|
| 41 |
+
function Lb(a){a>>>=0;var b=(v(),A).length;if(a<=b||4294901760<a)return!1;for(var d=1;4>=d;d*=2){var c=b*(1+.2/d);c=Math.min(c,a+100663296);a:{c=(Math.min(4294901760,65536*Math.ceil(Math.max(a,c)/65536))-x.buffer.byteLength+65535)/65536|0;try{x.grow(c);qa();var e=1;break a}catch(f){}e=void 0}if(e)return!0}return!1}
|
| 42 |
+
function Nb(a,b,d){a>>>=0;b>>>=0;if(Z.Vb==a)var c=Z.$b;else c=Error().stack.toString().split("\n"),"Error"==c[0]&&c.shift(),Fd(c);for(var e=3;c[e]&&Ed(c[e])!=a;)++e;for(a=0;a<d&&c[a+e];++a)(v(),C)[b+4*a>>>2>>>0]=Ed(c[a+e]);return a}
|
| 43 |
+
var Gd={},Id=()=>{if(!Hd){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8",_:ca||"./this.program"},b;for(b in Gd)void 0===Gd[b]?delete a[b]:a[b]=Gd[b];var d=[];for(b in a)d.push(`${b}=${a[b]}`);Hd=d}return Hd},Hd;function Ob(a,b){if(n)return U(19,1,a,b);a>>>=0;b>>>=0;var d=0,c=0,e;for(e of Id()){var f=b+d;(v(),D)[a+c>>>2>>>0]=f;d+=Y(e,f,Infinity)+1;c+=4}return 0}
|
| 44 |
+
function Pb(a,b){if(n)return U(20,1,a,b);a>>>=0;b>>>=0;var d=Id();(v(),D)[a>>>2>>>0]=d.length;a=0;for(var c of d)a+=Dd(c)+1;(v(),D)[b>>>2>>>0]=a;return 0}function Rb(a){return n?U(21,1,a):52}function Sb(a,b,d,c){return n?U(22,1,a,b,d,c):52}function Tb(a,b,d,c){return n?U(23,1,a,b,d,c):70}var Jd=[null,[],[]];
|
| 45 |
+
function Ub(a,b,d,c){if(n)return U(24,1,a,b,d,c);b>>>=0;d>>>=0;c>>>=0;for(var e=0,f=0;f<d;f++){var g=(v(),D)[b>>>2>>>0],l=(v(),D)[b+4>>>2>>>0];b+=8;for(var u=0;u<l;u++){var w=a,y=(v(),A)[g+u>>>0],B=Jd[w];0===y||10===y?((1===w?oa:p)(sd(B)),B.length=0):B.push(y)}e+=l}(v(),D)[c>>>2>>>0]=e;return 0}function Fc(a){return a>>>0}n||ed();n||(x=new WebAssembly.Memory({initial:256,maximum:65536,shared:!0}),qa());h.wasmBinary&&(q=h.wasmBinary);h.stackSave=()=>N();h.stackRestore=a=>M(a);h.stackAlloc=a=>Sc(a);
|
| 46 |
+
h.setValue=function(a,b,d="i8"){d.endsWith("*")&&(d="*");switch(d){case "i1":(v(),z)[a>>>0]=b;break;case "i8":(v(),z)[a>>>0]=b;break;case "i16":(v(),Fa)[a>>>1>>>0]=b;break;case "i32":(v(),C)[a>>>2>>>0]=b;break;case "i64":(v(),H)[a>>>3>>>0]=BigInt(b);break;case "float":(v(),Ga)[a>>>2>>>0]=b;break;case "double":(v(),G)[a>>>3>>>0]=b;break;case "*":(v(),D)[a>>>2>>>0]=b;break;default:J(`invalid type for setValue: ${d}`)}};
|
| 47 |
+
h.getValue=function(a,b="i8"){b.endsWith("*")&&(b="*");switch(b){case "i1":return(v(),z)[a>>>0];case "i8":return(v(),z)[a>>>0];case "i16":return(v(),Fa)[a>>>1>>>0];case "i32":return(v(),C)[a>>>2>>>0];case "i64":return(v(),H)[a>>>3>>>0];case "float":return(v(),Ga)[a>>>2>>>0];case "double":return(v(),G)[a>>>3>>>0];case "*":return(v(),D)[a>>>2>>>0];default:J(`invalid type for getValue: ${b}`)}};h.UTF8ToString=td;h.stringToUTF8=Y;h.lengthBytesUTF8=Dd;
|
| 48 |
+
var xd=[Gc,dd,qd,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,lb,mb,xb,yb,zb,Ob,Pb,Rb,Sb,Tb,Ub],wd={1011284:(a,b,d,c,e)=>{if("undefined"==typeof h||!h.Rb)return 1;a=td(Number(a>>>0));a.startsWith("./")&&(a=a.substring(2));a=h.Rb.get(a);if(!a)return 2;b=Number(b>>>0);d=Number(d>>>0);c=Number(c>>>0);if(b+d>a.byteLength)return 3;try{const f=a.subarray(b,b+d);switch(e){case 0:(v(),A).set(f,c>>>0);break;case 1:h.fc?h.fc(c,f):h.ic(c,f);break;default:return 4}return 0}catch{return 4}},1012108:()=>"undefined"!==typeof wasmOffsetConverter};
|
| 49 |
+
function Qa(){return"undefined"!==typeof wasmOffsetConverter}var Jc,Kc,Lc,za,Ea,Mc,Nc,Oc,Pc,Qc,K,L,Rc,M,Sc,N,Tc,Uc,Vc,Wc,Xc,Pa;function bc(a,b,d,c){var e=N();try{return V(a)(b,d,c)}catch(f){M(e);if(f!==f+0)throw f;K(1,0)}}function ac(a,b,d){var c=N();try{return V(a)(b,d)}catch(e){M(c);if(e!==e+0)throw e;K(1,0)}}function qc(a){var b=N();try{V(a)()}catch(d){M(b);if(d!==d+0)throw d;K(1,0)}}function $b(a,b){var d=N();try{return V(a)(b)}catch(c){M(d);if(c!==c+0)throw c;K(1,0)}}
|
| 50 |
+
function sc(a,b,d){var c=N();try{V(a)(b,d)}catch(e){M(c);if(e!==e+0)throw e;K(1,0)}}function rc(a,b){var d=N();try{V(a)(b)}catch(c){M(d);if(c!==c+0)throw c;K(1,0)}}function fc(a,b,d,c,e,f,g){var l=N();try{return V(a)(b,d,c,e,f,g)}catch(u){M(l);if(u!==u+0)throw u;K(1,0)}}function wc(a,b,d,c,e,f){var g=N();try{V(a)(b,d,c,e,f)}catch(l){M(g);if(l!==l+0)throw l;K(1,0)}}function uc(a,b,d,c){var e=N();try{V(a)(b,d,c)}catch(f){M(e);if(f!==f+0)throw f;K(1,0)}}
|
| 51 |
+
function vc(a,b,d,c,e){var f=N();try{V(a)(b,d,c,e)}catch(g){M(f);if(g!==g+0)throw g;K(1,0)}}function xc(a,b,d,c,e,f,g){var l=N();try{V(a)(b,d,c,e,f,g)}catch(u){M(l);if(u!==u+0)throw u;K(1,0)}}function Ec(a,b,d,c,e,f,g){var l=N();try{V(a)(b,d,c,e,f,g)}catch(u){M(l);if(u!==u+0)throw u;K(1,0)}}function Dc(a,b,d,c,e,f,g,l){var u=N();try{V(a)(b,d,c,e,f,g,l)}catch(w){M(u);if(w!==w+0)throw w;K(1,0)}}function cc(a,b,d,c,e){var f=N();try{return V(a)(b,d,c,e)}catch(g){M(f);if(g!==g+0)throw g;K(1,0)}}
|
| 52 |
+
function lc(a,b,d){var c=N();try{return V(a)(b,d)}catch(e){M(c);if(e!==e+0)throw e;K(1,0)}}function yc(a,b,d,c,e,f,g,l){var u=N();try{V(a)(b,d,c,e,f,g,l)}catch(w){M(u);if(w!==w+0)throw w;K(1,0)}}function Bc(a,b,d,c,e,f,g,l,u,w,y,B){var E=N();try{V(a)(b,d,c,e,f,g,l,u,w,y,B)}catch(F){M(E);if(F!==F+0)throw F;K(1,0)}}function oc(a,b,d){var c=N();try{return V(a)(b,d)}catch(e){M(c);if(e!==e+0)throw e;K(1,0);return 0n}}
|
| 53 |
+
function zc(a,b,d,c,e,f,g,l,u){var w=N();try{V(a)(b,d,c,e,f,g,l,u)}catch(y){M(w);if(y!==y+0)throw y;K(1,0)}}function Zb(a){var b=N();try{return V(a)()}catch(d){M(b);if(d!==d+0)throw d;K(1,0)}}function nc(a,b){var d=N();try{return V(a)(b)}catch(c){M(d);if(c!==c+0)throw c;K(1,0);return 0n}}function mc(a){var b=N();try{return V(a)()}catch(d){M(b);if(d!==d+0)throw d;K(1,0);return 0n}}function kc(a,b,d,c){var e=N();try{return V(a)(b,d,c)}catch(f){M(e);if(f!==f+0)throw f;K(1,0)}}
|
| 54 |
+
function jc(a,b,d,c,e){var f=N();try{return V(a)(b,d,c,e)}catch(g){M(f);if(g!==g+0)throw g;K(1,0)}}function ic(a,b,d,c,e,f){var g=N();try{return V(a)(b,d,c,e,f)}catch(l){M(g);if(l!==l+0)throw l;K(1,0)}}function ec(a,b,d,c,e,f){var g=N();try{return V(a)(b,d,c,e,f)}catch(l){M(g);if(l!==l+0)throw l;K(1,0)}}function dc(a,b,d,c,e,f){var g=N();try{return V(a)(b,d,c,e,f)}catch(l){M(g);if(l!==l+0)throw l;K(1,0)}}
|
| 55 |
+
function gc(a,b,d,c,e,f,g,l){var u=N();try{return V(a)(b,d,c,e,f,g,l)}catch(w){M(u);if(w!==w+0)throw w;K(1,0)}}function pc(a,b,d,c,e){var f=N();try{return V(a)(b,d,c,e)}catch(g){M(f);if(g!==g+0)throw g;K(1,0);return 0n}}function Yb(a,b,d,c){var e=N();try{return V(a)(b,d,c)}catch(f){M(e);if(f!==f+0)throw f;K(1,0)}}function Wb(a,b,d,c){var e=N();try{return V(a)(b,d,c)}catch(f){M(e);if(f!==f+0)throw f;K(1,0)}}
|
| 56 |
+
function hc(a,b,d,c,e,f,g,l,u,w,y,B){var E=N();try{return V(a)(b,d,c,e,f,g,l,u,w,y,B)}catch(F){M(E);if(F!==F+0)throw F;K(1,0)}}function Ac(a,b,d,c,e,f,g,l,u,w,y){var B=N();try{V(a)(b,d,c,e,f,g,l,u,w,y)}catch(E){M(B);if(E!==E+0)throw E;K(1,0)}}function Cc(a,b,d,c,e,f,g,l,u,w,y,B,E,F,Kd,Ld){var Md=N();try{V(a)(b,d,c,e,f,g,l,u,w,y,B,E,F,Kd,Ld)}catch(Ma){M(Md);if(Ma!==Ma+0)throw Ma;K(1,0)}}function Xb(a,b,d){var c=N();try{return V(a)(b,d)}catch(e){M(c);if(e!==e+0)throw e;K(1,0)}}
|
| 57 |
+
function Vb(a,b,d){var c=N();try{return V(a)(b,d)}catch(e){M(c);if(e!==e+0)throw e;K(1,0)}}function tc(a,b,d,c){var e=N();try{V(a)(b,d,c)}catch(f){M(e);if(f!==f+0)throw f;K(1,0)}}function Hc(){var a=I;a=Object.assign({},a);var b=c=>()=>c()>>>0,d=c=>e=>c(e)>>>0;a.sb=b(a.sb);a.ub=d(a.ub);a.Ib=d(a.Ib);a.Jb=b(a.Jb);a.Nb=d(a.Nb);return a}function xa(){if(0<O)P=xa;else if(n)ra?.(h),Ia();else{for(var a=$c;0<a.length;)a.shift()(h);0<O?P=xa:(h.calledRun=!0,pa||(Ia(),ra?.(h)))}}var I;
|
| 58 |
+
n||(I=await (wa()),xa());h.PTR_SIZE=4;Ha?moduleRtn=h:moduleRtn=new Promise((a,b)=>{ra=a;sa=b});
|
| 59 |
+
;return moduleRtn}export default ortWasmThreaded;var isPthread=globalThis.self?.name?.startsWith("em-pthread");var isNode=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";if(isNode)isPthread=(await import("worker_threads")).workerData==="em-pthread";isPthread&&ortWasmThreaded();
|
ort-wasm-simd-threaded.wasm
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ec8580a9d7b9476ceee52e10a7f94124e4dc71a019d666ed6d4726697c109a4d
|
| 3 |
+
size 13961845
|
ort.wasm.min.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*!
|
| 2 |
+
* ONNX Runtime Web v1.29.0
|
| 3 |
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
| 4 |
+
* Licensed under the MIT License.
|
| 5 |
+
*/
|
| 6 |
+
"use strict";var ort=(()=>{var Je=Object.defineProperty;var On=Object.getOwnPropertyDescriptor;var Ln=Object.getOwnPropertyNames;var Pn=Object.prototype.hasOwnProperty;var qe=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var E=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(o){throw n=[o],o}};var Se=(e,t)=>{for(var n in t)Je(e,n,{get:t[n],enumerable:!0})},Dn=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Ln(t))!Pn.call(e,r)&&r!==n&&Je(e,r,{get:()=>t[r],enumerable:!(o=On(t,r))||o.enumerable});return e};var Ye=e=>Dn(Je({},"__esModule",{value:!0}),e);var Te,K,se,_n,bt,Ze=E(()=>{"use strict";Te=new Map,K=[],se=(e,t,n)=>{if(t&&typeof t.init=="function"&&typeof t.createInferenceSessionHandler=="function"){let o=Te.get(e);if(o===void 0)Te.set(e,{backend:t,priority:n});else{if(o.priority>n)return;if(o.priority===n&&o.backend!==t)throw new Error(`cannot register backend "${e}" using priority ${n}`)}if(n>=0){let r=K.indexOf(e);r!==-1&&K.splice(r,1);for(let i=0;i<K.length;i++)if(Te.get(K[i]).priority<=n){K.splice(i,0,e);return}K.push(e)}return}throw new TypeError("not a valid backend")},_n=async e=>{let t=Te.get(e);if(!t)return"backend not found.";if(t.initialized)return t.backend;if(t.aborted)return t.error;{let n=!!t.initPromise;try{return n||(t.initPromise=t.backend.init(e)),await t.initPromise,t.initialized=!0,t.backend}catch(o){return n||(t.error=`${o}`,t.aborted=!0),t.error}finally{delete t.initPromise}}},bt=async e=>{let t=e.executionProviders||[],n=t.map(u=>typeof u=="string"?u:u.name),o=n.length===0?K:n,r,i=[],s=new Set;for(let u of o){let f=await _n(u);typeof f=="string"?i.push({name:u,err:f}):(r||(r=f),r===f&&s.add(u))}if(!r)throw new Error(`no available backend found. ERR: ${i.map(u=>`[${u.name}] ${u.err}`).join(", ")}`);for(let{name:u,err:f}of i)n.includes(u)&&console.warn(`removing requested execution provider "${u}" from session options because it is not available: ${f}`);let a=t.filter(u=>s.has(typeof u=="string"?u:u.name));return[r,new Proxy(e,{get:(u,f)=>f==="executionProviders"?a:Reflect.get(u,f)})]}});var yt=E(()=>{"use strict";Ze()});var gt,Et=E(()=>{"use strict";gt="1.29.0"});var St,D,Xe=E(()=>{"use strict";Et();St="warning",D={wasm:{},webgl:{},webgpu:{},versions:{common:gt},set logLevel(e){if(e!==void 0){if(typeof e!="string"||["verbose","info","warning","error","fatal"].indexOf(e)===-1)throw new Error(`Unsupported logging level: ${e}`);St=e}},get logLevel(){return St}};Object.defineProperty(D,"logLevel",{enumerable:!0})});var B,Tt=E(()=>{"use strict";Xe();B=D});var It,At,Bt=E(()=>{"use strict";It=(e,t)=>{let n=typeof document<"u"?document.createElement("canvas"):new OffscreenCanvas(1,1);n.width=e.dims[3],n.height=e.dims[2];let o=n.getContext("2d");if(o!=null){let r,i;t?.tensorLayout!==void 0&&t.tensorLayout==="NHWC"?(r=e.dims[2],i=e.dims[3]):(r=e.dims[3],i=e.dims[2]);let s=t?.format!==void 0?t.format:"RGB",a=t?.norm,u,f;a===void 0||a.mean===void 0?u=[255,255,255,255]:typeof a.mean=="number"?u=[a.mean,a.mean,a.mean,a.mean]:(u=[a.mean[0],a.mean[1],a.mean[2],0],a.mean[3]!==void 0&&(u[3]=a.mean[3])),a===void 0||a.bias===void 0?f=[0,0,0,0]:typeof a.bias=="number"?f=[a.bias,a.bias,a.bias,a.bias]:(f=[a.bias[0],a.bias[1],a.bias[2],0],a.bias[3]!==void 0&&(f[3]=a.bias[3]));let l=i*r,c=0,d=l,p=l*2,h=-1;s==="RGBA"?(c=0,d=l,p=l*2,h=l*3):s==="RGB"?(c=0,d=l,p=l*2):s==="RBG"&&(c=0,p=l,d=l*2);for(let b=0;b<i;b++)for(let A=0;A<r;A++){let m=(e.data[c++]-f[0])*u[0],w=(e.data[d++]-f[1])*u[1],O=(e.data[p++]-f[2])*u[2],g=h===-1?255:(e.data[h++]-f[3])*u[3];o.fillStyle="rgba("+m+","+w+","+O+","+g+")",o.fillRect(A,b,1,1)}if("toDataURL"in n)return n.toDataURL();throw new Error("toDataURL is not supported")}else throw new Error("Can not access image data")},At=(e,t)=>{let n=typeof document<"u"?document.createElement("canvas").getContext("2d"):new OffscreenCanvas(1,1).getContext("2d"),o;if(n!=null){let r,i,s;t?.tensorLayout!==void 0&&t.tensorLayout==="NHWC"?(r=e.dims[2],i=e.dims[1],s=e.dims[3]):(r=e.dims[3],i=e.dims[2],s=e.dims[1]);let a=t!==void 0&&t.format!==void 0?t.format:"RGB",u=t?.norm,f,l;u===void 0||u.mean===void 0?f=[255,255,255,255]:typeof u.mean=="number"?f=[u.mean,u.mean,u.mean,u.mean]:(f=[u.mean[0],u.mean[1],u.mean[2],255],u.mean[3]!==void 0&&(f[3]=u.mean[3])),u===void 0||u.bias===void 0?l=[0,0,0,0]:typeof u.bias=="number"?l=[u.bias,u.bias,u.bias,u.bias]:(l=[u.bias[0],u.bias[1],u.bias[2],0],u.bias[3]!==void 0&&(l[3]=u.bias[3]));let c=i*r;if(t!==void 0&&(t.format!==void 0&&s===4&&t.format!=="RGBA"||s===3&&t.format!=="RGB"&&t.format!=="BGR"))throw new Error("Tensor format doesn't match input tensor dims");let d=4,p=0,h=1,b=2,A=3,m=0,w=c,O=c*2,g=-1;a==="RGBA"?(m=0,w=c,O=c*2,g=c*3):a==="RGB"?(m=0,w=c,O=c*2):a==="RBG"&&(m=0,O=c,w=c*2),o=n.createImageData(r,i);for(let T=0;T<i*r;p+=d,h+=d,b+=d,A+=d,T++)o.data[p]=(e.data[m++]-l[0])*f[0],o.data[h]=(e.data[w++]-l[1])*f[1],o.data[b]=(e.data[O++]-l[2])*f[2],o.data[A]=g===-1?255:(e.data[g++]-l[3])*f[3]}else throw new Error("Can not access image data");return o}});var Ke,Ot,Lt,Pt,Dt,_t,Ut=E(()=>{"use strict";Ie();Ke=(e,t)=>{if(e===void 0)throw new Error("Image buffer must be defined");if(t.height===void 0||t.width===void 0)throw new Error("Image height and width must be defined");if(t.tensorLayout==="NHWC")throw new Error("NHWC Tensor layout is not supported yet");let{height:n,width:o}=t,r=t.norm??{mean:255,bias:0},i,s;typeof r.mean=="number"?i=[r.mean,r.mean,r.mean,r.mean]:i=[r.mean[0],r.mean[1],r.mean[2],r.mean[3]??255],typeof r.bias=="number"?s=[r.bias,r.bias,r.bias,r.bias]:s=[r.bias[0],r.bias[1],r.bias[2],r.bias[3]??0];let a=t.format!==void 0?t.format:"RGBA",u=t.tensorFormat!==void 0&&t.tensorFormat!==void 0?t.tensorFormat:"RGB",f=n*o,l=u==="RGBA"?new Float32Array(f*4):new Float32Array(f*3),c=4,d=0,p=1,h=2,b=3,A=0,m=f,w=f*2,O=-1;a==="RGB"&&(c=3,d=0,p=1,h=2,b=-1),u==="RGBA"?O=f*3:u==="RBG"?(A=0,w=f,m=f*2):u==="BGR"&&(w=0,m=f,A=f*2);for(let T=0;T<f;T++,d+=c,h+=c,p+=c,b+=c)l[A++]=(e[d]+s[0])/i[0],l[m++]=(e[p]+s[1])/i[1],l[w++]=(e[h]+s[2])/i[2],O!==-1&&b!==-1&&(l[O++]=(e[b]+s[3])/i[3]);return u==="RGBA"?new v("float32",l,[1,4,n,o]):new v("float32",l,[1,3,n,o])},Ot=async(e,t)=>{let n=typeof HTMLImageElement<"u"&&e instanceof HTMLImageElement,o=typeof ImageData<"u"&&e instanceof ImageData,r=typeof ImageBitmap<"u"&&e instanceof ImageBitmap,i=typeof e=="string",s,a=t??{},u=()=>{if(typeof document<"u")return document.createElement("canvas");if(typeof OffscreenCanvas<"u")return new OffscreenCanvas(1,1);throw new Error("Canvas is not supported")},f=l=>typeof HTMLCanvasElement<"u"&&l instanceof HTMLCanvasElement||l instanceof OffscreenCanvas?l.getContext("2d"):null;if(n){let l=u();l.width=e.width,l.height=e.height;let c=f(l);if(c!=null){let d=e.height,p=e.width;if(t!==void 0&&t.resizedHeight!==void 0&&t.resizedWidth!==void 0&&(d=t.resizedHeight,p=t.resizedWidth),t!==void 0){if(a=t,t.tensorFormat!==void 0)throw new Error("Image input config format must be RGBA for HTMLImageElement");a.tensorFormat="RGBA",a.height=d,a.width=p}else a.tensorFormat="RGBA",a.height=d,a.width=p;c.drawImage(e,0,0),s=c.getImageData(0,0,p,d).data}else throw new Error("Can not access image data")}else if(o){let l,c;if(t!==void 0&&t.resizedWidth!==void 0&&t.resizedHeight!==void 0?(l=t.resizedHeight,c=t.resizedWidth):(l=e.height,c=e.width),t!==void 0&&(a=t),a.format="RGBA",a.height=l,a.width=c,t!==void 0){let d=u();d.width=c,d.height=l;let p=f(d);if(p!=null)p.putImageData(e,0,0),s=p.getImageData(0,0,c,l).data;else throw new Error("Can not access image data")}else s=e.data}else if(r){if(t===void 0)throw new Error("Please provide image config with format for Imagebitmap");let l=u();l.width=e.width,l.height=e.height;let c=f(l);if(c!=null){let d=e.height,p=e.width;return c.drawImage(e,0,0,p,d),s=c.getImageData(0,0,p,d).data,a.height=d,a.width=p,Ke(s,a)}else throw new Error("Can not access image data")}else{if(i)return new Promise((l,c)=>{let d=u(),p=f(d);if(!e||!p)return c();let h=new Image;h.crossOrigin="Anonymous",h.src=e,h.onload=()=>{d.width=h.width,d.height=h.height,p.drawImage(h,0,0,d.width,d.height);let b=p.getImageData(0,0,d.width,d.height);a.height=d.height,a.width=d.width,l(Ke(b.data,a))}});throw new Error("Input data provided is not supported - aborted tensor creation")}if(s!==void 0)return Ke(s,a);throw new Error("Input data provided is not supported - aborted tensor creation")},Lt=(e,t)=>{let{width:n,height:o,download:r,dispose:i}=t,s=[1,o,n,4];return new v({location:"texture",type:"float32",texture:e,dims:s,download:r,dispose:i})},Pt=(e,t)=>{let{dataType:n,dims:o,download:r,dispose:i}=t;return new v({location:"gpu-buffer",type:n??"float32",gpuBuffer:e,dims:o,download:r,dispose:i})},Dt=(e,t)=>{let{dataType:n,dims:o,download:r,dispose:i}=t;return new v({location:"ml-tensor",type:n??"float32",mlTensor:e,dims:o,download:r,dispose:i})},_t=(e,t,n)=>new v({location:"cpu-pinned",type:e,data:t,dims:n??[t.length]})});var Q,me,xt,vt,Ct=E(()=>{"use strict";Q=new Map([["float32",Float32Array],["uint8",Uint8Array],["int8",Int8Array],["uint16",Uint16Array],["int16",Int16Array],["int32",Int32Array],["bool",Uint8Array],["float64",Float64Array],["uint32",Uint32Array],["int4",Uint8Array],["uint4",Uint8Array]]),me=new Map([[Float32Array,"float32"],[Uint8Array,"uint8"],[Int8Array,"int8"],[Uint16Array,"uint16"],[Int16Array,"int16"],[Int32Array,"int32"],[Float64Array,"float64"],[Uint32Array,"uint32"]]),xt=!1,vt=()=>{if(!xt){xt=!0;let e=typeof BigInt64Array<"u"&&BigInt64Array.from,t=typeof BigUint64Array<"u"&&BigUint64Array.from,n=globalThis.Float16Array,o=typeof n<"u"&&n.from;e&&(Q.set("int64",BigInt64Array),me.set(BigInt64Array,"int64")),t&&(Q.set("uint64",BigUint64Array),me.set(BigUint64Array,"uint64")),o?(Q.set("float16",n),me.set(n,"float16")):Q.set("float16",Uint16Array)}}});var Mt,Rt,Nt=E(()=>{"use strict";Ie();Mt=e=>{let t=1;for(let n=0;n<e.length;n++){let o=e[n];if(typeof o!="number"||!Number.isSafeInteger(o))throw new TypeError(`dims[${n}] must be an integer, got: ${o}`);if(o<0)throw new RangeError(`dims[${n}] must be a non-negative integer, got: ${o}`);t*=o}return t},Rt=(e,t)=>{switch(e.location){case"cpu":return new v(e.type,e.data,t);case"cpu-pinned":return new v({location:"cpu-pinned",data:e.data,type:e.type,dims:t});case"texture":return new v({location:"texture",texture:e.texture,type:e.type,dims:t});case"gpu-buffer":return new v({location:"gpu-buffer",gpuBuffer:e.gpuBuffer,type:e.type,dims:t});case"ml-tensor":return new v({location:"ml-tensor",mlTensor:e.mlTensor,type:e.type,dims:t});default:throw new Error(`tensorReshape: tensor location ${e.location} is not supported`)}}});var v,Ie=E(()=>{"use strict";Bt();Ut();Ct();Nt();v=class{constructor(t,n,o){vt();let r,i;if(typeof t=="object"&&"location"in t)switch(this.dataLocation=t.location,r=t.type,i=t.dims,t.location){case"cpu-pinned":{let a=Q.get(r);if(!a)throw new TypeError(`unsupported type "${r}" to create tensor from pinned buffer`);if(!(t.data instanceof a))throw new TypeError(`buffer should be of type ${a.name}`);this.cpuData=t.data;break}case"texture":{if(r!=="float32")throw new TypeError(`unsupported type "${r}" to create tensor from texture`);this.gpuTextureData=t.texture,this.downloader=t.download,this.disposer=t.dispose;break}case"gpu-buffer":{if(r!=="float32"&&r!=="float16"&&r!=="int32"&&r!=="int64"&&r!=="uint32"&&r!=="uint8"&&r!=="bool"&&r!=="uint4"&&r!=="int4")throw new TypeError(`unsupported type "${r}" to create tensor from gpu buffer`);this.gpuBufferData=t.gpuBuffer,this.downloader=t.download,this.disposer=t.dispose;break}case"ml-tensor":{if(r!=="float32"&&r!=="float16"&&r!=="int32"&&r!=="int64"&&r!=="uint32"&&r!=="uint64"&&r!=="int8"&&r!=="uint8"&&r!=="bool"&&r!=="uint4"&&r!=="int4")throw new TypeError(`unsupported type "${r}" to create tensor from MLTensor`);this.mlTensorData=t.mlTensor,this.downloader=t.download,this.disposer=t.dispose;break}default:throw new Error(`Tensor constructor: unsupported location '${this.dataLocation}'`)}else{let a,u;if(typeof t=="string")if(r=t,u=o,t==="string"){if(!Array.isArray(n))throw new TypeError("A string tensor's data must be a string array.");a=n}else{let f=Q.get(t);if(f===void 0)throw new TypeError(`Unsupported tensor type: ${t}.`);if(Array.isArray(n)){if(t==="float16"&&f===Uint16Array||t==="uint4"||t==="int4")throw new TypeError(`Creating a ${t} tensor from number array is not supported. Please use ${f.name} as data.`);t==="uint64"||t==="int64"?a=f.from(n,BigInt):a=f.from(n)}else if(n instanceof f)a=n;else if(n instanceof Uint8ClampedArray)if(t==="uint8")a=Uint8Array.from(n);else throw new TypeError("A Uint8ClampedArray tensor's data must be type of uint8");else if(t==="float16"&&n instanceof Uint16Array&&f!==Uint16Array)a=new globalThis.Float16Array(n.buffer,n.byteOffset,n.length);else throw new TypeError(`A ${r} tensor's data must be type of ${f}`)}else if(u=n,Array.isArray(t)){if(t.length===0)throw new TypeError("Tensor type cannot be inferred from an empty array.");let f=typeof t[0];if(f==="string")r="string",a=t;else if(f==="boolean")r="bool",a=Uint8Array.from(t);else throw new TypeError(`Invalid element type of data array: ${f}.`)}else if(t instanceof Uint8ClampedArray)r="uint8",a=Uint8Array.from(t);else{let f=me.get(t.constructor);if(f===void 0)throw new TypeError(`Unsupported type for tensor data: ${t.constructor}.`);r=f,a=t}if(u===void 0)u=[a.length];else if(!Array.isArray(u))throw new TypeError("A tensor's dims must be a number array");i=u,this.cpuData=a,this.dataLocation="cpu"}let s=Mt(i);if(this.cpuData&&s!==this.cpuData.length&&!((r==="uint4"||r==="int4")&&Math.ceil(s/2)===this.cpuData.length))throw new Error(`Tensor's size(${s}) does not match data length(${this.cpuData.length}).`);this.type=r,this.dims=i,this.size=s}static async fromImage(t,n){return Ot(t,n)}static fromTexture(t,n){return Lt(t,n)}static fromGpuBuffer(t,n){return Pt(t,n)}static fromMLTensor(t,n){return Dt(t,n)}static fromPinnedBuffer(t,n,o){return _t(t,n,o)}toDataURL(t){return It(this,t)}toImageData(t){return At(this,t)}get data(){if(this.ensureValid(),!this.cpuData)throw new Error("The data is not on CPU. Use `getData()` to download GPU data to CPU, or use `texture` or `gpuBuffer` property to access the GPU data directly.");return this.cpuData}get location(){return this.dataLocation}get texture(){if(this.ensureValid(),!this.gpuTextureData)throw new Error("The data is not stored as a WebGL texture.");return this.gpuTextureData}get gpuBuffer(){if(this.ensureValid(),!this.gpuBufferData)throw new Error("The data is not stored as a WebGPU buffer.");return this.gpuBufferData}get mlTensor(){if(this.ensureValid(),!this.mlTensorData)throw new Error("The data is not stored as a WebNN MLTensor.");return this.mlTensorData}async getData(t){switch(this.ensureValid(),this.dataLocation){case"cpu":case"cpu-pinned":return this.data;case"texture":case"gpu-buffer":case"ml-tensor":{if(!this.downloader)throw new Error("The current tensor is not created with a specified data downloader.");if(this.isDownloading)throw new Error("The current tensor is being downloaded.");try{this.isDownloading=!0;let n=await this.downloader();return this.downloader=void 0,this.dataLocation="cpu",this.cpuData=n,t&&this.disposer&&(this.disposer(),this.disposer=void 0),n}finally{this.isDownloading=!1}}default:throw new Error(`cannot get data from location: ${this.dataLocation}`)}}dispose(){if(this.isDownloading)throw new Error("The current tensor is being downloaded.");this.disposer&&(this.disposer(),this.disposer=void 0),this.cpuData=void 0,this.gpuTextureData=void 0,this.gpuBufferData=void 0,this.mlTensorData=void 0,this.downloader=void 0,this.isDownloading=void 0,this.dataLocation="none"}ensureValid(){if(this.dataLocation==="none")throw new Error("The tensor is disposed.")}reshape(t){if(this.ensureValid(),this.downloader||this.disposer)throw new Error("Cannot reshape a tensor that owns GPU resource.");return Rt(this,t)}}});var k,Qe=E(()=>{"use strict";Ie();k=v});var et,Ft,J,q,Y,Z,tt=E(()=>{"use strict";Xe();et=(e,t)=>{(typeof D.trace>"u"?!D.wasm.trace:!D.trace)||console.timeStamp(`${e}::ORT::${t}`)},Ft=(e,t)=>{let n=new Error().stack?.split(/\r\n|\r|\n/g)||[],o=!1;for(let r=0;r<n.length;r++){if(o&&!n[r].includes("TRACE_FUNC")){let i=`FUNC_${e}::${n[r].trim().split(" ")[1]}`;t&&(i+=`::${t}`),et("CPU",i);return}n[r].includes("TRACE_FUNC")&&(o=!0)}},J=e=>{(typeof D.trace>"u"?!D.wasm.trace:!D.trace)||Ft("BEGIN",e)},q=e=>{(typeof D.trace>"u"?!D.wasm.trace:!D.trace)||Ft("END",e)},Y=e=>{(typeof D.trace>"u"?!D.wasm.trace:!D.trace)||console.time(`ORT::${e}`)},Z=e=>{(typeof D.trace>"u"?!D.wasm.trace:!D.trace)||console.timeEnd(`ORT::${e}`)}});var Ae,kt=E(()=>{"use strict";Ze();Qe();tt();Ae=class e{constructor(t){this.handler=t}async run(t,n,o){J(),Y("InferenceSession.run");let r={},i={};if(typeof t!="object"||t===null||t instanceof k||Array.isArray(t))throw new TypeError("'feeds' must be an object that use input names as keys and OnnxValue as corresponding values.");let s=!0;if(typeof n=="object"){if(n===null)throw new TypeError("Unexpected argument[1]: cannot be null.");if(n instanceof k)throw new TypeError("'fetches' cannot be a Tensor");if(Array.isArray(n)){if(n.length===0)throw new TypeError("'fetches' cannot be an empty array.");s=!1;for(let f of n){if(typeof f!="string")throw new TypeError("'fetches' must be a string array or an object.");if(this.outputNames.indexOf(f)===-1)throw new RangeError(`'fetches' contains invalid output name: ${f}.`);r[f]=null}if(typeof o=="object"&&o!==null)i=o;else if(typeof o<"u")throw new TypeError("'options' must be an object.")}else{let f=!1,l=Object.getOwnPropertyNames(n);for(let c of this.outputNames)if(l.indexOf(c)!==-1){let d=n[c];(d===null||d instanceof k)&&(f=!0,s=!1,r[c]=d)}if(f){if(typeof o=="object"&&o!==null)i=o;else if(typeof o<"u")throw new TypeError("'options' must be an object.")}else i=n}}else if(typeof n<"u")throw new TypeError("Unexpected argument[1]: must be 'fetches' or 'options'.");for(let f of this.inputNames)if(typeof t[f]>"u")throw new Error(`input '${f}' is missing in 'feeds'.`);if(s)for(let f of this.outputNames)r[f]=null;let a=await this.handler.run(t,r,i),u={};for(let f in a)if(Object.hasOwnProperty.call(a,f)){let l=a[f];l instanceof k?u[f]=l:u[f]=new k(l.type,l.data,l.dims)}return Z("InferenceSession.run"),q(),u}async release(){return this.handler.dispose()}static async create(t,n,o,r){J(),Y("InferenceSession.create");let i,s={};if(typeof t=="string"){if(i=t,typeof n=="object"&&n!==null)s=n;else if(typeof n<"u")throw new TypeError("'options' must be an object.")}else if(t instanceof Uint8Array){if(i=t,typeof n=="object"&&n!==null)s=n;else if(typeof n<"u")throw new TypeError("'options' must be an object.")}else if(t instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&t instanceof SharedArrayBuffer){let l=t,c=0,d=t.byteLength;if(typeof n=="object"&&n!==null)s=n;else if(typeof n=="number"){if(c=n,!Number.isSafeInteger(c))throw new RangeError("'byteOffset' must be an integer.");if(c<0||c>=l.byteLength)throw new RangeError(`'byteOffset' is out of range [0, ${l.byteLength}).`);if(d=t.byteLength-c,typeof o=="number"){if(d=o,!Number.isSafeInteger(d))throw new RangeError("'byteLength' must be an integer.");if(d<=0||c+d>l.byteLength)throw new RangeError(`'byteLength' is out of range (0, ${l.byteLength-c}].`);if(typeof r=="object"&&r!==null)s=r;else if(typeof r<"u")throw new TypeError("'options' must be an object.")}else if(typeof o<"u")throw new TypeError("'byteLength' must be a number.")}else if(typeof n<"u")throw new TypeError("'options' must be an object.");i=new Uint8Array(l,c,d)}else throw new TypeError("Unexpected argument[0]: must be 'path' or 'buffer'.");let[a,u]=await bt(s),f=await a.createInferenceSessionHandler(i,u);return Z("InferenceSession.create"),q(),new e(f)}startProfiling(){this.handler.startProfiling()}endProfiling(){this.handler.endProfiling()}get inputNames(){return this.handler.inputNames}get outputNames(){return this.handler.outputNames}get inputMetadata(){return this.handler.inputMetadata}get outputMetadata(){return this.handler.outputMetadata}}});var Wt,Gt=E(()=>{"use strict";kt();Wt=Ae});var $t=E(()=>{"use strict"});var zt=E(()=>{"use strict"});var Ht=E(()=>{"use strict"});var jt=E(()=>{"use strict"});var nt={};Se(nt,{InferenceSession:()=>Wt,TRACE:()=>et,TRACE_EVENT_BEGIN:()=>Y,TRACE_EVENT_END:()=>Z,TRACE_FUNC_BEGIN:()=>J,TRACE_FUNC_END:()=>q,Tensor:()=>k,env:()=>B,registerBackend:()=>se});var X=E(()=>{"use strict";yt();Tt();Gt();Qe();$t();zt();tt();Ht();jt()});var Be=E(()=>{"use strict"});var Yt={};Se(Yt,{default:()=>Un});var Jt,qt,Un,Zt=E(()=>{"use strict";rt();ee();Oe();Jt="ort-wasm-proxy-worker",qt=globalThis.self?.name===Jt;qt&&(self.onmessage=e=>{let{type:t,in:n}=e.data;try{switch(t){case"init-wasm":Le(n.wasm).then(()=>{Pe(n).then(()=>{postMessage({type:t})},o=>{postMessage({type:t,err:o})})},o=>{postMessage({type:t,err:o})});break;case"init-ep":{let{epName:o,env:r}=n;De(r,o).then(()=>{postMessage({type:t})},i=>{postMessage({type:t,err:i})});break}case"copy-from":{let{buffer:o}=n,r=we(o);postMessage({type:t,out:r});break}case"create":{let{model:o,options:r}=n;_e(o,r).then(i=>{postMessage({type:t,out:i})},i=>{postMessage({type:t,err:i})});break}case"release":Ue(n),postMessage({type:t});break;case"run":{let{sessionId:o,inputIndices:r,inputs:i,outputIndices:s,options:a}=n;xe(o,r,i,s,new Array(s.length).fill(null),a).then(u=>{u.some(f=>f[3]!=="cpu")?postMessage({type:t,err:"Proxy does not support non-cpu tensor location."}):postMessage({type:t,out:u},Ce([...i,...u]))},u=>{postMessage({type:t,err:u})});break}case"end-profiling":ve(n),postMessage({type:t});break;default:}}catch(o){postMessage({type:t,err:o})}});Un=qt?null:e=>new Worker(e??R,{type:"classic",name:Jt})});var xn,vn,R,Me,ot,Cn,Mn,Qt,Rn,Xt,en,Kt,tn,Oe=E(()=>{"use strict";Be();xn=typeof location>"u"?void 0:location.origin,vn=()=>{if(!!1)return typeof document<"u"?document.currentScript?.src:typeof self<"u"?self.location?.href:void 0},R=vn(),Me=()=>{if(R&&!R.startsWith("blob:"))return R.substring(0,R.lastIndexOf("/")+1)},ot=(e,t)=>{try{let n=t??R;return(n?new URL(e,n):new URL(e)).origin===xn}catch{return!1}},Cn=(e,t)=>{let n=t??R;try{return(n?new URL(e,n):new URL(e)).href}catch{return}},Mn=(e,t)=>`${t??"./"}${e}`,Qt=async e=>{let n=await(await fetch(e,{credentials:"same-origin"})).blob();return URL.createObjectURL(n)},Rn=async e=>(await import(/*webpackIgnore:true*/ /*@vite-ignore*/e)).default,Xt=(Zt(),Ye(Yt)).default,en=async()=>{if(!R)throw new Error("Failed to load proxy worker: cannot determine the script source URL.");if(ot(R))return[void 0,Xt()];let e=await Qt(R);return[e,Xt(e)]},Kt=void 0,tn=async(e,t,n,o)=>{let r=Kt&&!(e||t);if(r)if(R)r=ot(R)||o&&!n;else if(o&&!n)r=!0;else throw new Error("cannot determine the script source URL.");if(r)return[void 0,Kt];{let i="ort-wasm-simd-threaded.mjs",s=e??Cn(i,t),a=!!1&&n&&s&&!ot(s,t),u=a?await Qt(s):s??Mn(i,t);return[a?u:void 0,await Rn(u)]}}});var st,it,Re,nn,Nn,Fn,kn,Le,I,ee=E(()=>{"use strict";Oe();it=!1,Re=!1,nn=!1,Nn=()=>{if(typeof SharedArrayBuffer>"u")return!1;try{return typeof MessageChannel<"u"&&new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]))}catch{return!1}},Fn=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,30,1,28,0,65,0,253,15,253,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,253,186,1,26,11]))}catch{return!1}},kn=()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,5,1,96,0,1,123,3,2,1,0,10,19,1,17,0,65,1,253,15,65,2,253,15,65,3,253,15,253,147,2,11]))}catch{return!1}},Le=async e=>{if(it)return Promise.resolve();if(Re)throw new Error("multiple calls to 'initializeWebAssembly()' detected.");if(nn)throw new Error("previous call to 'initializeWebAssembly()' failed.");Re=!0;let t=e.initTimeout,n=e.numThreads;if(e.simd!==!1){if(e.simd==="relaxed"){if(!kn())throw new Error("Relaxed WebAssembly SIMD is not supported in the current environment.")}else if(!Fn())throw new Error("WebAssembly SIMD is not supported in the current environment.")}let o=Nn();n>1&&!o&&(typeof self<"u"&&!self.crossOriginIsolated&&console.warn("env.wasm.numThreads is set to "+n+", but this will not work unless you enable crossOriginIsolated mode. See https://web.dev/cross-origin-isolation-guide/ for more info."),console.warn("WebAssembly multi-threading is not supported in the current environment. Falling back to single-threading."),e.numThreads=n=1);let r=e.wasmPaths,i=typeof r=="string"?r:void 0,s=r?.mjs,a=s?.href??s,u=r?.wasm,f=u?.href??u,l=e.wasmBinary,[c,d]=await tn(a,i,n>1,!!l||!!f),p=!1,h=[];if(t>0&&h.push(new Promise(b=>{setTimeout(()=>{p=!0,b()},t)})),h.push(new Promise((b,A)=>{let m={numThreads:n};if(l)m.wasmBinary=l,m.locateFile=w=>w;else if(f||i)m.locateFile=w=>f??i+w;else if(a&&a.indexOf("blob:")!==0)m.locateFile=w=>new URL(w,a).href;else if(c){let w=Me();w&&(m.locateFile=O=>w+O)}d(m).then(w=>{Re=!1,it=!0,st=w,b(),c&&URL.revokeObjectURL(c)},w=>{Re=!1,nn=!0,A(w)})})),await Promise.race(h),p)throw new Error(`WebAssembly backend initializing failed due to timeout: ${t}ms`)},I=()=>{if(it&&st)return st;throw new Error("WebAssembly is not initialized yet.")}});var N,he,S,Ne=E(()=>{"use strict";ee();N=(e,t)=>{let n=I(),o=n.lengthBytesUTF8(e)+1,r=n._malloc(o);return n.stringToUTF8(e,r,o),t.push(r),r},he=(e,t,n,o)=>{if(typeof e=="object"&&e!==null){if(n.has(e))throw new Error("Circular reference in options");n.add(e)}Object.entries(e).forEach(([r,i])=>{let s=t?t+r:r;if(typeof i=="object")he(i,s+".",n,o);else if(typeof i=="string"||typeof i=="number")o(s,i.toString());else if(typeof i=="boolean")o(s,i?"1":"0");else throw new Error(`Can't handle extra config type: ${typeof i}`)})},S=e=>{let t=I(),n=t.stackSave();try{let o=t.PTR_SIZE,r=t.stackAlloc(2*o);t._OrtGetLastError(r,r+o);let i=Number(t.getValue(r,o===4?"i32":"i64")),s=t.getValue(r+o,"*"),a=s?t.UTF8ToString(s):"";throw new Error(`${e} ERROR_CODE: ${i}, ERROR_MESSAGE: ${a}`)}finally{t.stackRestore(n)}}});var rn,on=E(()=>{"use strict";ee();Ne();rn=e=>{let t=I(),n=0,o=[],r=e||{};try{if(e?.logSeverityLevel===void 0)r.logSeverityLevel=2;else if(typeof e.logSeverityLevel!="number"||!Number.isInteger(e.logSeverityLevel)||e.logSeverityLevel<0||e.logSeverityLevel>4)throw new Error(`log severity level is not valid: ${e.logSeverityLevel}`);if(e?.logVerbosityLevel===void 0)r.logVerbosityLevel=0;else if(typeof e.logVerbosityLevel!="number"||!Number.isInteger(e.logVerbosityLevel))throw new Error(`log verbosity level is not valid: ${e.logVerbosityLevel}`);e?.terminate===void 0&&(r.terminate=!1);let i=0;return e?.tag!==void 0&&(i=N(e.tag,o)),n=t._OrtCreateRunOptions(r.logSeverityLevel,r.logVerbosityLevel,!!r.terminate,i),n===0&&S("Can't create run options."),e?.extra!==void 0&&he(e.extra,"",new WeakSet,(s,a)=>{let u=N(s,o),f=N(a,o);t._OrtAddRunConfigEntry(n,u,f)!==0&&S(`Can't set a run config entry: ${s} - ${a}.`)}),[n,o]}catch(i){throw n!==0&&t._OrtReleaseRunOptions(n),o.forEach(s=>t._free(s)),i}}});var Wn,Gn,$n,ie,zn,sn,an=E(()=>{"use strict";ee();Ne();Wn=e=>{switch(e){case"disabled":return 0;case"basic":return 1;case"extended":return 2;case"layout":return 3;case"all":return 99;default:throw new Error(`unsupported graph optimization level: ${e}`)}},Gn=e=>{switch(e){case"sequential":return 0;case"parallel":return 1;default:throw new Error(`unsupported execution mode: ${e}`)}},$n=e=>{e.extra||(e.extra={}),e.extra.session||(e.extra.session={});let t=e.extra.session;t.use_ort_model_bytes_directly||(t.use_ort_model_bytes_directly="1"),e.executionProviders&&e.executionProviders.some(n=>(typeof n=="string"?n:n.name)==="webgpu")&&(e.enableMemPattern=!1)},ie=(e,t,n,o)=>{let r=N(t,o),i=N(n,o);I()._OrtAddSessionConfigEntry(e,r,i)!==0&&S(`Can't set a session config entry: ${t} - ${n}.`)},zn=async(e,t,n)=>{let o=t.executionProviders;for(let r of o){let i=typeof r=="string"?r:r.name,s=[];switch(i){case"webnn":if(i="WEBNN",ie(e,"session.disable_quant_qdq","1",n),ie(e,"session.disable_qdq_constant_folding","1",n),typeof r!="string"){let d=r?.deviceType;d&&ie(e,"deviceType",d,n)}break;case"webgpu":if(i="JS",typeof r!="string"){let c=r;if(c?.preferredLayout){if(c.preferredLayout!=="NCHW"&&c.preferredLayout!=="NHWC")throw new Error(`preferredLayout must be either 'NCHW' or 'NHWC': ${c.preferredLayout}`);ie(e,"preferredLayout",c.preferredLayout,n)}}break;case"wasm":case"cpu":continue;default:throw new Error(`not supported execution provider: ${i}`)}let a=N(i,n),u=s.length,f=0,l=0;if(u>0){f=I()._malloc(u*I().PTR_SIZE),n.push(f),l=I()._malloc(u*I().PTR_SIZE),n.push(l);for(let c=0;c<u;c++)I().setValue(f+c*I().PTR_SIZE,s[c][0],"*"),I().setValue(l+c*I().PTR_SIZE,s[c][1],"*")}await I()._OrtAppendExecutionProvider(e,a,f,l,u)!==0&&S(`Can't append execution provider: ${i}.`)}},sn=async e=>{let t=I(),n=0,o=[],r=e||{};$n(r);try{let i=Wn(r.graphOptimizationLevel??"all"),s=Gn(r.executionMode??"sequential"),a=typeof r.logId=="string"?N(r.logId,o):0,u=r.logSeverityLevel??2;if(!Number.isInteger(u)||u<0||u>4)throw new Error(`log severity level is not valid: ${u}`);let f=r.logVerbosityLevel??0;if(!Number.isInteger(f)||f<0||f>4)throw new Error(`log verbosity level is not valid: ${f}`);let l=typeof r.optimizedModelFilePath=="string"?N(r.optimizedModelFilePath,o):0;if(n=t._OrtCreateSessionOptions(i,!!r.enableCpuMemArena,!!r.enableMemPattern,s,!!r.enableProfiling,0,a,u,f,l),n===0&&S("Can't create session options."),r.executionProviders&&await zn(n,r,o),r.enableGraphCapture!==void 0){if(typeof r.enableGraphCapture!="boolean")throw new Error(`enableGraphCapture must be a boolean value: ${r.enableGraphCapture}`);ie(n,"enableGraphCapture",r.enableGraphCapture.toString(),o)}if(r.freeDimensionOverrides)for(let[c,d]of Object.entries(r.freeDimensionOverrides)){if(typeof c!="string")throw new Error(`free dimension override name must be a string: ${c}`);if(typeof d!="number"||!Number.isInteger(d)||d<0)throw new Error(`free dimension override value must be a non-negative integer: ${d}`);let p=N(c,o);t._OrtAddFreeDimensionOverride(n,p,d)!==0&&S(`Can't set a free dimension override: ${c} - ${d}.`)}return r.extra!==void 0&&he(r.extra,"",new WeakSet,(c,d)=>{ie(n,c,d,o)}),[n,o]}catch(i){throw n!==0&&t._OrtReleaseSessionOptions(n)!==0&&S("Can't release session options."),o.forEach(s=>t._free(s)),i}}});var ae,Fe,ue,un,fn,ke,We,cn,at=E(()=>{"use strict";ae=e=>{switch(e){case"int8":return 3;case"uint8":return 2;case"bool":return 9;case"int16":return 5;case"uint16":return 4;case"int32":return 6;case"uint32":return 12;case"float16":return 10;case"float32":return 1;case"float64":return 11;case"string":return 8;case"int64":return 7;case"uint64":return 13;case"int4":return 22;case"uint4":return 21;default:throw new Error(`unsupported data type: ${e}`)}},Fe=e=>{switch(e){case 3:return"int8";case 2:return"uint8";case 9:return"bool";case 5:return"int16";case 4:return"uint16";case 6:return"int32";case 12:return"uint32";case 10:return"float16";case 1:return"float32";case 11:return"float64";case 8:return"string";case 7:return"int64";case 13:return"uint64";case 22:return"int4";case 21:return"uint4";default:throw new Error(`unsupported data type: ${e}`)}},ue=(e,t)=>{let n=[-1,4,1,1,2,2,4,8,-1,1,2,8,4,8,-1,-1,-1,-1,-1,-1,-1,.5,.5][e],o=typeof t=="number"?t:t.reduce((r,i)=>r*i,1);return n>0?Math.ceil(o*n):void 0},un=e=>{switch(e){case"float16":return typeof Float16Array<"u"?Float16Array:Uint16Array;case"float32":return Float32Array;case"uint8":return Uint8Array;case"int8":return Int8Array;case"uint16":return Uint16Array;case"int16":return Int16Array;case"int32":return Int32Array;case"bool":return Uint8Array;case"float64":return Float64Array;case"uint32":return Uint32Array;case"int64":return BigInt64Array;case"uint64":return BigUint64Array;default:throw new Error(`unsupported type: ${e}`)}},fn=e=>{switch(e){case"verbose":return 0;case"info":return 1;case"warning":return 2;case"error":return 3;case"fatal":return 4;default:throw new Error(`unsupported logging level: ${e}`)}},ke=e=>e==="float32"||e==="float16"||e==="int32"||e==="int64"||e==="uint32"||e==="uint8"||e==="bool"||e==="uint4"||e==="int4",We=e=>e==="float32"||e==="float16"||e==="int32"||e==="int64"||e==="uint32"||e==="uint64"||e==="int8"||e==="uint8"||e==="bool"||e==="uint4"||e==="int4",cn=e=>{switch(e){case"none":return 0;case"cpu":return 1;case"cpu-pinned":return 2;case"texture":return 3;case"gpu-buffer":return 4;case"ml-tensor":return 5;default:throw new Error(`unsupported data location: ${e}`)}}});var be,ut=E(()=>{"use strict";Be();be=async e=>{if(typeof e=="string")if(!1)try{let{readFile:t}=qe("node:fs/promises");return new Uint8Array(await t(e))}catch(t){if(t.code==="ERR_FS_FILE_TOO_LARGE"){let{createReadStream:n}=qe("node:fs"),o=n(e),r=[];for await(let i of o)r.push(i);return new Uint8Array(Buffer.concat(r))}throw t}else{let t=await fetch(e);if(!t.ok)throw new Error(`failed to load external data file: ${e}`);let n=t.headers.get("Content-Length"),o=n?parseInt(n,10):0;if(o<1073741824)return new Uint8Array(await t.arrayBuffer());{if(!t.body)throw new Error(`failed to load external data file: ${e}, no response body.`);let r=t.body.getReader(),i;try{i=new ArrayBuffer(o)}catch(a){if(a instanceof RangeError){let u=Math.ceil(o/65536);i=new WebAssembly.Memory({initial:u,maximum:u}).buffer}else throw a}let s=0;for(;;){let{done:a,value:u}=await r.read();if(a)break;let f=u.byteLength;new Uint8Array(i,s,f).set(u),s+=f}return new Uint8Array(i,0,o)}}else return e instanceof Blob?new Uint8Array(await e.arrayBuffer()):e instanceof Uint8Array?e:new Uint8Array(e)}});var Hn,Pe,De,fe,jn,dn,we,_e,Ue,ln,xe,ve,Ce,rt=E(()=>{"use strict";X();on();an();at();ee();Ne();ut();Hn=(e,t)=>{I()._OrtInit(e,t)!==0&&S("Can't initialize onnxruntime.")},Pe=async e=>{Hn(e.wasm.numThreads,fn(e.logLevel))},De=async(e,t)=>{I().asyncInit?.();let n=e.webgpu.adapter;if(t==="webgpu"){if(typeof navigator>"u"||!navigator.gpu)throw new Error("WebGPU is not supported in current environment");if(n){if(typeof n.limits!="object"||typeof n.features!="object"||typeof n.requestDevice!="function")throw new Error("Invalid GPU adapter set in `env.webgpu.adapter`. It must be a GPUAdapter object.")}else{let o=e.webgpu.powerPreference;if(o!==void 0&&o!=="low-power"&&o!=="high-performance")throw new Error(`Invalid powerPreference setting: "${o}"`);let r=e.webgpu.forceFallbackAdapter;if(r!==void 0&&typeof r!="boolean")throw new Error(`Invalid forceFallbackAdapter setting: "${r}"`);if(n=await navigator.gpu.requestAdapter({powerPreference:o,forceFallbackAdapter:r}),!n)throw new Error('Failed to get GPU adapter. You may need to enable flag "--enable-unsafe-webgpu" if you are using Chrome.')}}if(t==="webnn"&&(typeof navigator>"u"||!navigator.ml))throw new Error("WebNN is not supported in current environment")},fe=new Map,jn=e=>{let t=I(),n=t.stackSave();try{let o=t.PTR_SIZE,r=t.stackAlloc(2*o);t._OrtGetInputOutputCount(e,r,r+o)!==0&&S("Can't get session input/output count.");let s=o===4?"i32":"i64";return[Number(t.getValue(r,s)),Number(t.getValue(r+o,s))]}finally{t.stackRestore(n)}},dn=(e,t)=>{let n=I(),o=n.stackSave(),r=0;try{let i=n.PTR_SIZE,s=n.stackAlloc(2*i);n._OrtGetInputOutputMetadata(e,t,s,s+i)!==0&&S("Can't get session input/output metadata.");let u=Number(n.getValue(s,"*"));r=Number(n.getValue(s+i,"*"));let f=n.HEAP32[r/4];if(f===0)return[u,0];let l=n.HEAPU32[r/4+1],c=[];for(let d=0;d<l;d++){let p=Number(n.getValue(r+8+d*i,"*"));c.push(p!==0?n.UTF8ToString(p):Number(n.getValue(r+8+(d+l)*i,"*")))}return[u,f,c]}finally{n.stackRestore(o),r!==0&&n._OrtFree(r)}},we=e=>{let t=I(),n=t._malloc(e.byteLength);if(n===0)throw new Error(`Can't create a session. failed to allocate a buffer of size ${e.byteLength}.`);return t.HEAPU8.set(e,n),[n,e.byteLength]},_e=async(e,t)=>{let n,o,r=I();Array.isArray(e)?[n,o]=e:e.buffer===r.HEAPU8.buffer?[n,o]=[e.byteOffset,e.byteLength]:[n,o]=we(e);let i=0,s=0,a=0,u=[],f=[],l=[];try{if([s,u]=await sn(t),t?.externalData&&r.mountExternalData){let g=[];for(let T of t.externalData){let x=typeof T=="string"?T:T.path,M=typeof T=="string"?T:T.data;g.push(be(M).then(_=>{r.mountExternalData(x,_)}))}await Promise.all(g)}for(let g of t?.executionProviders??[])if((typeof g=="string"?g:g.name)==="webnn"){if(r.shouldTransferToMLTensor=!1,typeof g!="string"){let x=g,M=x?.context,_=x?.gpuDevice,le=x?.deviceType,re=x?.powerPreference;M?r.currentContext=M:_?r.currentContext=await r.webnnCreateMLContext(_):r.currentContext=await r.webnnCreateMLContext({deviceType:le,powerPreference:re})}else r.currentContext=await r.webnnCreateMLContext();break}i=await r._OrtCreateSession(n,o,s),r.webgpuOnCreateSession?.(i),i===0&&S("Can't create a session."),r.jsepOnCreateSession?.(),r.currentContext&&(r.webnnRegisterMLContext(i,r.currentContext),r.currentContext=void 0,r.shouldTransferToMLTensor=!0);let[c,d]=jn(i),p=!!t?.enableGraphCapture,h=[],b=[],A=[],m=[],w=[];for(let g=0;g<c;g++){let[T,x,M]=dn(i,g);T===0&&S("Can't get an input name."),f.push(T);let _=r.UTF8ToString(T);h.push(_),A.push(x===0?{name:_,isTensor:!1}:{name:_,isTensor:!0,type:Fe(x),shape:M})}for(let g=0;g<d;g++){let[T,x,M]=dn(i,g+c);T===0&&S("Can't get an output name."),l.push(T);let _=r.UTF8ToString(T);b.push(_),m.push(x===0?{name:_,isTensor:!1}:{name:_,isTensor:!0,type:Fe(x),shape:M})}return fe.set(i,[i,f,l,null,p,!1]),[i,h,b,A,m]}catch(c){throw f.forEach(d=>r._OrtFree(d)),l.forEach(d=>r._OrtFree(d)),a!==0&&r._OrtReleaseBinding(a)!==0&&S("Can't release IO binding."),i!==0&&r._OrtReleaseSession(i)!==0&&S("Can't release session."),c}finally{r._free(n),s!==0&&r._OrtReleaseSessionOptions(s)!==0&&S("Can't release session options."),u.forEach(c=>r._free(c)),r.unmountExternalData?.()}},Ue=e=>{let t=I(),n=fe.get(e);if(!n)throw new Error(`cannot release session. invalid session id: ${e}`);let[o,r,i,s,a]=n;s&&(a&&t._OrtClearBoundOutputs(s.handle)!==0&&S("Can't clear bound outputs."),t._OrtReleaseBinding(s.handle)!==0&&S("Can't release IO binding.")),t.jsepOnReleaseSession?.(e),t.webnnOnReleaseSession?.(e),t.webgpuOnReleaseSession?.(e),r.forEach(u=>t._OrtFree(u)),i.forEach(u=>t._OrtFree(u)),t._OrtReleaseSession(o)!==0&&S("Can't release session."),fe.delete(e)},ln=async(e,t,n,o,r,i,s=!1)=>{if(!e){t.push(0);return}let a=I(),u=a.PTR_SIZE,f=e[0],l=e[1],c=e[3],d=c,p,h;if(f==="string"&&(c==="gpu-buffer"||c==="ml-tensor"))throw new Error("String tensor is not supported on GPU.");if(s&&c!=="gpu-buffer")throw new Error(`External buffer must be provided for input/output index ${i} when enableGraphCapture is true.`);if(c==="gpu-buffer"){let m=e[2].gpuBuffer;h=ue(ae(f),l);{let w=a.jsepRegisterBuffer;if(!w)throw new Error('Tensor location "gpu-buffer" is not supported without using WebGPU.');p=w(o,i,m,h)}}else if(c==="ml-tensor"){let m=e[2].mlTensor;h=ue(ae(f),l);let w=a.webnnRegisterMLTensor;if(!w)throw new Error('Tensor location "ml-tensor" is not supported without using WebNN.');p=w(o,m,ae(f),l)}else{let m=e[2];if(Array.isArray(m)){h=u*m.length,p=a._malloc(h),n.push(p);for(let w=0;w<m.length;w++){if(typeof m[w]!="string")throw new TypeError(`tensor data at index ${w} is not a string`);a.setValue(p+w*u,N(m[w],n),"*")}}else{let w=a.webnnIsGraphInput,O=a.webnnIsGraphOutput;if(f!=="string"&&w&&O){let g=a.UTF8ToString(r);if(w(o,g)||O(o,g)){let T=ae(f);h=ue(T,l),d="ml-tensor";let x=a.webnnCreateTemporaryTensor,M=a.webnnUploadTensor;if(!x||!M)throw new Error('Tensor location "ml-tensor" is not supported without using WebNN.');let _=await x(o,T,l);M(_,new Uint8Array(m.buffer,m.byteOffset,m.byteLength)),p=_}else h=m.byteLength,p=a._malloc(h),n.push(p),a.HEAPU8.set(new Uint8Array(m.buffer,m.byteOffset,h),p)}else h=m.byteLength,p=a._malloc(h),n.push(p),a.HEAPU8.set(new Uint8Array(m.buffer,m.byteOffset,h),p)}}let b=a.stackSave(),A=a.stackAlloc(4*l.length);try{l.forEach((w,O)=>a.setValue(A+O*u,w,u===4?"i32":"i64"));let m=a._OrtCreateTensor(ae(f),p,h,A,l.length,cn(d));m===0&&S(`Can't create tensor for input/output. session=${o}, index=${i}.`),t.push(m)}finally{a.stackRestore(b)}},xe=async(e,t,n,o,r,i)=>{let s=I(),a=s.PTR_SIZE,u=fe.get(e);if(!u)throw new Error(`cannot run inference. invalid session id: ${e}`);let f=u[0],l=u[1],c=u[2],d=u[3],p=u[4],h=u[5],b=t.length,A=o.length,m=0,w=[],O=[],g=[],T=[],x=[],M=s.stackSave(),_=s.stackAlloc(b*a),le=s.stackAlloc(b*a),re=s.stackAlloc(A*a),lt=s.stackAlloc(A*a);try{[m,w]=rn(i),Y("wasm prepareInputOutputTensor");for(let y=0;y<b;y++)await ln(n[y],O,T,e,l[t[y]],t[y],p);for(let y=0;y<A;y++)await ln(r[y],g,T,e,c[o[y]],b+o[y],p);Z("wasm prepareInputOutputTensor");for(let y=0;y<b;y++)s.setValue(_+y*a,O[y],"*"),s.setValue(le+y*a,l[t[y]],"*");for(let y=0;y<A;y++)s.setValue(re+y*a,g[y],"*"),s.setValue(lt+y*a,c[o[y]],"*");s.jsepOnRunStart?.(f),s.webnnOnRunStart?.(f);let F;F=await s._OrtRun(f,le,_,b,lt,A,re,m),F!==0&&S("failed to call OrtRun().");let z=[],pt=[];Y("wasm ProcessOutputTensor");for(let y=0;y<A;y++){let G=Number(s.getValue(re+y*a,"*"));if(G===g[y]||x.includes(g[y])){z.push(r[y]),G!==g[y]&&s._OrtReleaseTensor(G)!==0&&S("Can't release tensor.");continue}let mt=s.stackSave(),$=s.stackAlloc(4*a),oe=!1,P,C=0;try{s._OrtGetTensorData(G,$,$+a,$+2*a,$+3*a)!==0&&S(`Can't access output tensor data on index ${y}.`);let Ve=a===4?"i32":"i64",ge=Number(s.getValue($,Ve));C=s.getValue($+a,"*");let wt=s.getValue($+a*2,"*"),Bn=Number(s.getValue($+a*3,Ve)),H=[];for(let U=0;U<Bn;U++)H.push(Number(s.getValue(wt+U*a,Ve)));s._OrtFree(wt)!==0&&S("Can't free memory for tensor dims.");let j=H.reduce((U,L)=>U*L,1);P=Fe(ge);let pe=d?.outputPreferredLocations[o[y]];if(P==="string"){if(pe==="gpu-buffer"||pe==="ml-tensor")throw new Error("String tensor is not supported on GPU.");let U=[];for(let L=0;L<j;L++){let V=s.getValue(C+L*a,"*"),Ee=s.getValue(C+(L+1)*a,"*"),ht=L===j-1?void 0:Ee-V;U.push(s.UTF8ToString(V,ht))}z.push([P,H,U,"cpu"])}else if(pe==="gpu-buffer"&&j>0){let U=s.jsepGetBuffer;if(!U)throw new Error('preferredLocation "gpu-buffer" is not supported without using WebGPU.');let L=U(C),V=ue(ge,j);if(V===void 0||!ke(P))throw new Error(`Unsupported data type: ${P}`);oe=!0,z.push([P,H,{gpuBuffer:L,download:s.jsepCreateDownloader(L,V,P),dispose:()=>{s._OrtReleaseTensor(G)!==0&&S("Can't release tensor.")}},"gpu-buffer"])}else if(pe==="ml-tensor"&&j>0){let U=s.webnnEnsureTensor,L=s.webnnIsGraphInputOutputTypeSupported;if(!U||!L)throw new Error('preferredLocation "ml-tensor" is not supported without using WebNN.');if(ue(ge,j)===void 0||!We(P))throw new Error(`Unsupported data type: ${P}`);if(!L(e,P,!1))throw new Error(`preferredLocation "ml-tensor" for ${P} output is not supported by current WebNN Context.`);let Ee=await U(e,C,ge,H,!1);oe=!0,z.push([P,H,{mlTensor:Ee,download:s.webnnCreateMLTensorDownloader(C,P),dispose:()=>{s.webnnReleaseTensorId(C),s._OrtReleaseTensor(G)}},"ml-tensor"])}else if(pe==="ml-tensor-cpu-output"&&j>0){let U=s.webnnCreateMLTensorDownloader(C,P)(),L=z.length;oe=!0,pt.push((async()=>{let V=[L,await U];return s.webnnReleaseTensorId(C),s._OrtReleaseTensor(G),V})()),z.push([P,H,[],"cpu"])}else{let U=un(P),L=new U(j);new Uint8Array(L.buffer,L.byteOffset,L.byteLength).set(s.HEAPU8.subarray(C,C+L.byteLength)),z.push([P,H,L,"cpu"])}}finally{s.stackRestore(mt),P==="string"&&C&&s._free(C),oe||s._OrtReleaseTensor(G)}}d&&!p&&(s._OrtClearBoundOutputs(d.handle)!==0&&S("Can't clear bound outputs."),fe.set(e,[f,l,c,d,p,!1]));for(let[y,G]of await Promise.all(pt))z[y][2]=G;return Z("wasm ProcessOutputTensor"),z}finally{s.webnnOnRunEnd?.(f),s.stackRestore(M),O.forEach(F=>s._OrtReleaseTensor(F)),g.forEach(F=>s._OrtReleaseTensor(F)),T.forEach(F=>s._free(F)),m!==0&&s._OrtReleaseRunOptions(m),w.forEach(F=>s._free(F))}},ve=e=>{let t=I(),n=fe.get(e);if(!n)throw new Error("invalid session id");let o=n[0],r=t._OrtEndProfiling(o);r===0&&S("Can't get an profile file name."),t._OrtFree(r)},Ce=e=>{let t=[];for(let n of e){let o=n[2];!Array.isArray(o)&&"buffer"in o&&t.push(o.buffer)}return t}});var ne,W,ye,$e,ze,Ge,ft,ct,ce,de,Jn,pn,mn,wn,hn,bn,yn,gn,dt=E(()=>{"use strict";X();rt();ee();Oe();ne=()=>!!B.wasm.proxy&&typeof document<"u",ye=!1,$e=!1,ze=!1,ct=new Map,ce=(e,t)=>{let n=ct.get(e);n?n.push(t):ct.set(e,[t])},de=()=>{if(ye||!$e||ze||!W)throw new Error("worker not ready")},Jn=e=>{switch(e.data.type){case"init-wasm":ye=!1,e.data.err?(ze=!0,ft[1](e.data.err)):($e=!0,ft[0]()),Ge&&(URL.revokeObjectURL(Ge),Ge=void 0);break;case"init-ep":case"copy-from":case"create":case"release":case"run":case"end-profiling":{let t=ct.get(e.data.type);e.data.err?t.shift()[1](e.data.err):t.shift()[0](e.data.out);break}default:}},pn=async()=>{if(!$e){if(ye)throw new Error("multiple calls to 'initWasm()' detected.");if(ze)throw new Error("previous call to 'initWasm()' failed.");if(ye=!0,ne())return new Promise((e,t)=>{W?.terminate(),en().then(([n,o])=>{try{W=o,W.onerror=i=>t(i),W.onmessage=Jn,ft=[e,t];let r={type:"init-wasm",in:B};if(!r.in.wasm.wasmPaths&&n){let i=Me();i&&(r.in.wasm.wasmPaths=i)}W.postMessage(r),Ge=n}catch(r){t(r)}},t)});try{await Le(B.wasm),await Pe(B),$e=!0}catch(e){throw ze=!0,e}finally{ye=!1}}},mn=async e=>{if(ne())return de(),new Promise((t,n)=>{ce("init-ep",[t,n]);let o={type:"init-ep",in:{epName:e,env:B}};W.postMessage(o)});await De(B,e)},wn=async e=>ne()?(de(),new Promise((t,n)=>{ce("copy-from",[t,n]);let o={type:"copy-from",in:{buffer:e}};W.postMessage(o,[e.buffer])})):we(e),hn=async(e,t)=>{if(ne()){if(t?.preferredOutputLocation)throw new Error('session option "preferredOutputLocation" is not supported for proxy.');return de(),new Promise((n,o)=>{ce("create",[n,o]);let r={type:"create",in:{model:e,options:{...t}}},i=[];e instanceof Uint8Array&&i.push(e.buffer),W.postMessage(r,i)})}else return _e(e,t)},bn=async e=>{if(ne())return de(),new Promise((t,n)=>{ce("release",[t,n]);let o={type:"release",in:e};W.postMessage(o)});Ue(e)},yn=async(e,t,n,o,r,i)=>{if(ne()){if(n.some(s=>s[3]!=="cpu"))throw new Error("input tensor on GPU is not supported for proxy.");if(r.some(s=>s))throw new Error("pre-allocated output tensor is not supported for proxy.");return de(),new Promise((s,a)=>{ce("run",[s,a]);let u=n,f={type:"run",in:{sessionId:e,inputIndices:t,inputs:u,outputIndices:o,options:i}};W.postMessage(f,Ce(u))})}else return xe(e,t,n,o,r,i)},gn=async e=>{if(ne())return de(),new Promise((t,n)=>{ce("end-profiling",[t,n]);let o={type:"end-profiling",in:e};W.postMessage(o)});ve(e)}});var En,qn,He,Sn=E(()=>{"use strict";X();dt();at();Be();ut();En=(e,t)=>{switch(e.location){case"cpu":return[e.type,e.dims,e.data,"cpu"];case"gpu-buffer":return[e.type,e.dims,{gpuBuffer:e.gpuBuffer},"gpu-buffer"];case"ml-tensor":return[e.type,e.dims,{mlTensor:e.mlTensor},"ml-tensor"];default:throw new Error(`invalid data location: ${e.location} for ${t()}`)}},qn=e=>{switch(e[3]){case"cpu":return new k(e[0],e[2],e[1]);case"gpu-buffer":{let t=e[0];if(!ke(t))throw new Error(`not supported data type: ${t} for deserializing GPU tensor`);let{gpuBuffer:n,download:o,dispose:r}=e[2];return k.fromGpuBuffer(n,{dataType:t,dims:e[1],download:o,dispose:r})}case"ml-tensor":{let t=e[0];if(!We(t))throw new Error(`not supported data type: ${t} for deserializing MLTensor tensor`);let{mlTensor:n,download:o,dispose:r}=e[2];return k.fromMLTensor(n,{dataType:t,dims:e[1],download:o,dispose:r})}default:throw new Error(`invalid data location: ${e[3]}`)}},He=class{async fetchModelAndCopyToWasmMemory(t){return wn(await be(t))}async loadModel(t,n){J();let o;typeof t=="string"?o=await this.fetchModelAndCopyToWasmMemory(t):o=t,[this.sessionId,this.inputNames,this.outputNames,this.inputMetadata,this.outputMetadata]=await hn(o,n),q()}async dispose(){return bn(this.sessionId)}async run(t,n,o){J();let r=[],i=[];Object.entries(t).forEach(d=>{let p=d[0],h=d[1],b=this.inputNames.indexOf(p);if(b===-1)throw new Error(`invalid input '${p}'`);r.push(h),i.push(b)});let s=[],a=[];Object.entries(n).forEach(d=>{let p=d[0],h=d[1],b=this.outputNames.indexOf(p);if(b===-1)throw new Error(`invalid output '${p}'`);s.push(h),a.push(b)});let u=r.map((d,p)=>En(d,()=>`input "${this.inputNames[i[p]]}"`)),f=s.map((d,p)=>d?En(d,()=>`output "${this.outputNames[a[p]]}"`):null),l=await yn(this.sessionId,i,u,a,f,o),c={};for(let d=0;d<l.length;d++)c[this.outputNames[a[d]]]=s[d]??qn(l[d]);return q(),c}startProfiling(){}endProfiling(){gn(this.sessionId)}}});var In={};Se(In,{OnnxruntimeWebAssemblyBackend:()=>je,initializeFlags:()=>Tn,wasmBackend:()=>Yn});var Tn,je,Yn,An=E(()=>{"use strict";X();dt();Sn();Tn=()=>{(typeof B.wasm.initTimeout!="number"||B.wasm.initTimeout<0)&&(B.wasm.initTimeout=0);let e=B.wasm.simd;if(typeof e!="boolean"&&e!==void 0&&e!=="fixed"&&e!=="relaxed"&&(console.warn(`Property "env.wasm.simd" is set to unknown value "${e}". Reset it to \`false\` and ignore SIMD feature checking.`),B.wasm.simd=!1),typeof B.wasm.proxy!="boolean"&&(B.wasm.proxy=!1),typeof B.wasm.trace!="boolean"&&(B.wasm.trace=!1),typeof B.wasm.numThreads!="number"||!Number.isInteger(B.wasm.numThreads)||B.wasm.numThreads<=0)if(typeof self<"u"&&!self.crossOriginIsolated)B.wasm.numThreads=1;else{let t=typeof navigator>"u"?qe("node:os").cpus().length:navigator.hardwareConcurrency;B.wasm.numThreads=Math.min(4,Math.ceil((t||1)/2))}},je=class{async init(t){Tn(),await pn(),await mn(t)}async createInferenceSessionHandler(t,n){let o=new He;return await o.loadModel(t,n),o}},Yn=new je});var Xn={};Se(Xn,{InferenceSession:()=>Wt,TRACE:()=>et,TRACE_EVENT_BEGIN:()=>Y,TRACE_EVENT_END:()=>Z,TRACE_FUNC_BEGIN:()=>J,TRACE_FUNC_END:()=>q,Tensor:()=>k,default:()=>Zn,env:()=>B,registerBackend:()=>se});X();X();X();var Vt="1.29.0";var Zn=nt;{let e=(An(),Ye(In)).wasmBackend;se("cpu",e,10),se("wasm",e,10)}Object.defineProperty(B.versions,"web",{value:Vt,enumerable:!0});return Ye(Xn);})();
|
| 7 |
+
typeof exports=="object"&&typeof module=="object"&&(module.exports=ort);
|
| 8 |
+
//# sourceMappingURL=ort.wasm.min.js.map
|
ort.wasm.min.js.map
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
pnc-worker.js
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* global ort */
|
| 2 |
+
|
| 3 |
+
function signedAsset(path) {
|
| 4 |
+
const base = new URL(self.location.href);
|
| 5 |
+
const url = new URL(path, base);
|
| 6 |
+
const signature = base.searchParams.get("__sign");
|
| 7 |
+
if (signature && url.origin === base.origin) url.searchParams.set("__sign", signature);
|
| 8 |
+
return url.href;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
importScripts(signedAsset("ort.wasm.min.js"));
|
| 12 |
+
|
| 13 |
+
ort.env.wasm.numThreads = 1;
|
| 14 |
+
ort.env.wasm.proxy = false;
|
| 15 |
+
ort.env.wasm.wasmPaths = {
|
| 16 |
+
mjs: signedAsset("ort-wasm-simd-threaded.mjs"),
|
| 17 |
+
wasm: signedAsset("ort-wasm-simd-threaded.wasm"),
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
let initialization = null;
|
| 21 |
+
let session = null;
|
| 22 |
+
let vocabulary = null;
|
| 23 |
+
let labels = null;
|
| 24 |
+
let maximumLength = 256;
|
| 25 |
+
const INFERENCE_WINDOW_TOKENS = 192;
|
| 26 |
+
let pendingRequest = null;
|
| 27 |
+
let processing = false;
|
| 28 |
+
|
| 29 |
+
async function sha256(bytes) {
|
| 30 |
+
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
| 31 |
+
return Array.from(new Uint8Array(digest), (value) => value.toString(16).padStart(2, "0")).join("");
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
async function fetchVerified(file, completedBytes, totalBytes) {
|
| 35 |
+
const response = await fetch(signedAsset(file.url), {cache: "force-cache"});
|
| 36 |
+
if (!response.ok || !response.body) {
|
| 37 |
+
throw new Error(`Kunne ikke hente ${file.path} (${response.status})`);
|
| 38 |
+
}
|
| 39 |
+
const reader = response.body.getReader();
|
| 40 |
+
const chunks = [];
|
| 41 |
+
let loaded = 0;
|
| 42 |
+
while (true) {
|
| 43 |
+
const {done, value} = await reader.read();
|
| 44 |
+
if (done) break;
|
| 45 |
+
chunks.push(value);
|
| 46 |
+
loaded += value.byteLength;
|
| 47 |
+
self.postMessage({
|
| 48 |
+
type: "pnc-progress",
|
| 49 |
+
file: file.path,
|
| 50 |
+
loaded,
|
| 51 |
+
fileBytes: file.bytes,
|
| 52 |
+
overall: Math.min(1, (completedBytes + loaded) / totalBytes),
|
| 53 |
+
});
|
| 54 |
+
}
|
| 55 |
+
const bytes = new Uint8Array(loaded);
|
| 56 |
+
let offset = 0;
|
| 57 |
+
for (const chunk of chunks) {
|
| 58 |
+
bytes.set(chunk, offset);
|
| 59 |
+
offset += chunk.byteLength;
|
| 60 |
+
}
|
| 61 |
+
if (loaded !== file.bytes) {
|
| 62 |
+
throw new Error(`${file.path} har forkert størrelse (${loaded} bytes)`);
|
| 63 |
+
}
|
| 64 |
+
if (await sha256(bytes) !== file.sha256) {
|
| 65 |
+
throw new Error(`${file.path} fejlede SHA-256-kontrol`);
|
| 66 |
+
}
|
| 67 |
+
return bytes;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
async function initialize(configUrl) {
|
| 71 |
+
if (session) return;
|
| 72 |
+
const response = await fetch(signedAsset(configUrl), {cache: "no-cache"});
|
| 73 |
+
if (!response.ok) throw new Error("Kunne ikke hente PnC-konfigurationen");
|
| 74 |
+
const rootConfig = await response.json();
|
| 75 |
+
const config = rootConfig.pnc;
|
| 76 |
+
if (!config?.files?.length) throw new Error("PnC mangler i modelkonfigurationen");
|
| 77 |
+
|
| 78 |
+
const totalBytes = config.files.reduce((sum, file) => sum + file.bytes, 0);
|
| 79 |
+
let completedBytes = 0;
|
| 80 |
+
const downloaded = new Map();
|
| 81 |
+
for (const file of config.files) {
|
| 82 |
+
const bytes = await fetchVerified(file, completedBytes, totalBytes);
|
| 83 |
+
downloaded.set(file.path, bytes);
|
| 84 |
+
completedBytes += bytes.byteLength;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
const tokenizer = JSON.parse(new TextDecoder().decode(downloaded.get("tokenizer.json")));
|
| 88 |
+
const modelConfig = JSON.parse(new TextDecoder().decode(downloaded.get("config.json")));
|
| 89 |
+
vocabulary = tokenizer.model.vocab;
|
| 90 |
+
labels = modelConfig.id2label;
|
| 91 |
+
// Shorter context restores sentence stops in long, continuous dictation.
|
| 92 |
+
maximumLength = Math.min(config.maxLength || 256, INFERENCE_WINDOW_TOKENS);
|
| 93 |
+
session = await ort.InferenceSession.create(downloaded.get("pnc.int8.onnx"), {
|
| 94 |
+
executionProviders: ["wasm"],
|
| 95 |
+
graphOptimizationLevel: "all",
|
| 96 |
+
});
|
| 97 |
+
self.postMessage({type: "pnc-ready", bytes: totalBytes, model: config.name});
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
function splitBasicToken(word) {
|
| 101 |
+
const parts = [];
|
| 102 |
+
let current = "";
|
| 103 |
+
const flush = () => {
|
| 104 |
+
if (current) parts.push(current);
|
| 105 |
+
current = "";
|
| 106 |
+
};
|
| 107 |
+
for (const character of Array.from(word)) {
|
| 108 |
+
if (/\s/u.test(character)) {
|
| 109 |
+
flush();
|
| 110 |
+
} else if (/[\p{P}\p{S}]/u.test(character)) {
|
| 111 |
+
flush();
|
| 112 |
+
parts.push(character);
|
| 113 |
+
} else if (!/[\p{Cc}\p{Cf}]/u.test(character)) {
|
| 114 |
+
current += character;
|
| 115 |
+
}
|
| 116 |
+
}
|
| 117 |
+
flush();
|
| 118 |
+
return parts;
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
function wordPiece(token) {
|
| 122 |
+
const characters = Array.from(token);
|
| 123 |
+
if (!characters.length) return [];
|
| 124 |
+
if (characters.length > 100) return [vocabulary["[UNK]"]];
|
| 125 |
+
const pieces = [];
|
| 126 |
+
let start = 0;
|
| 127 |
+
while (start < characters.length) {
|
| 128 |
+
let end = characters.length;
|
| 129 |
+
let identifier;
|
| 130 |
+
while (start < end) {
|
| 131 |
+
const candidate = `${start ? "##" : ""}${characters.slice(start, end).join("")}`;
|
| 132 |
+
if (Object.hasOwn(vocabulary, candidate)) {
|
| 133 |
+
identifier = vocabulary[candidate];
|
| 134 |
+
break;
|
| 135 |
+
}
|
| 136 |
+
end -= 1;
|
| 137 |
+
}
|
| 138 |
+
if (identifier === undefined) return [vocabulary["[UNK]"]];
|
| 139 |
+
pieces.push(identifier);
|
| 140 |
+
start = end;
|
| 141 |
+
}
|
| 142 |
+
return pieces;
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
function encodeWords(words) {
|
| 146 |
+
const identifiers = [vocabulary["[CLS]"]];
|
| 147 |
+
const wordIds = [null];
|
| 148 |
+
words.forEach((word, wordIndex) => {
|
| 149 |
+
const basicTokens = splitBasicToken(word);
|
| 150 |
+
const pieces = basicTokens.length
|
| 151 |
+
? basicTokens.flatMap((token) => wordPiece(token))
|
| 152 |
+
: [vocabulary["[UNK]"]];
|
| 153 |
+
for (const identifier of pieces) {
|
| 154 |
+
identifiers.push(identifier);
|
| 155 |
+
wordIds.push(wordIndex);
|
| 156 |
+
}
|
| 157 |
+
});
|
| 158 |
+
identifiers.push(vocabulary["[SEP]"]);
|
| 159 |
+
wordIds.push(null);
|
| 160 |
+
return {identifiers, wordIds};
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
function encodedLength(words) {
|
| 164 |
+
return encodeWords(words).identifiers.length;
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
function maximumWindowEnd(words, start) {
|
| 168 |
+
let low = start + 1;
|
| 169 |
+
let high = Math.min(words.length, start + maximumLength);
|
| 170 |
+
while (low < high) {
|
| 171 |
+
const middle = Math.floor((low + high + 1) / 2);
|
| 172 |
+
if (encodedLength(words.slice(start, middle)) <= maximumLength) {
|
| 173 |
+
low = middle;
|
| 174 |
+
} else {
|
| 175 |
+
high = middle - 1;
|
| 176 |
+
}
|
| 177 |
+
}
|
| 178 |
+
return low;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
function capitalize(word) {
|
| 182 |
+
const characters = Array.from(word);
|
| 183 |
+
if (!characters.length) return word;
|
| 184 |
+
return characters[0].toLocaleUpperCase("da-DK")
|
| 185 |
+
+ characters.slice(1).join("").toLocaleLowerCase("da-DK");
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
function capitalizeInitial(word) {
|
| 189 |
+
const characters = Array.from(word);
|
| 190 |
+
const index = characters.findIndex((character) => /\p{L}/u.test(character));
|
| 191 |
+
if (index < 0) return word;
|
| 192 |
+
characters[index] = characters[index].toLocaleUpperCase("da-DK");
|
| 193 |
+
return characters.join("");
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
function stabilizeRenderedWords(words) {
|
| 197 |
+
if (!words.length) return [];
|
| 198 |
+
const output = [...words];
|
| 199 |
+
output[0] = capitalizeInitial(output[0]);
|
| 200 |
+
for (let index = 0; index < output.length - 1; index += 1) {
|
| 201 |
+
if (!/[.!?]+$/u.test(output[index])) continue;
|
| 202 |
+
if (/\p{L}\.\p{L}/u.test(output[index])) continue; // f.eks.
|
| 203 |
+
if (/\p{Lu}/u.test(output[index + 1])) continue; // CPR, iPhone
|
| 204 |
+
output[index + 1] = capitalizeInitial(output[index + 1]);
|
| 205 |
+
}
|
| 206 |
+
return output;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
async function predictWindow(words) {
|
| 210 |
+
const {identifiers, wordIds} = encodeWords(words);
|
| 211 |
+
const shape = [1, identifiers.length];
|
| 212 |
+
const inputIds = BigInt64Array.from(identifiers, (value) => BigInt(value));
|
| 213 |
+
const attentionMask = new BigInt64Array(identifiers.length).fill(1n);
|
| 214 |
+
const output = await session.run({
|
| 215 |
+
input_ids: new ort.Tensor("int64", inputIds, shape),
|
| 216 |
+
attention_mask: new ort.Tensor("int64", attentionMask, shape),
|
| 217 |
+
});
|
| 218 |
+
const logits = output.logits;
|
| 219 |
+
const labelCount = logits.dims.at(-1);
|
| 220 |
+
const rendered = [...words];
|
| 221 |
+
const seen = new Set();
|
| 222 |
+
wordIds.forEach((wordIndex, tokenIndex) => {
|
| 223 |
+
if (wordIndex === null || seen.has(wordIndex)) return;
|
| 224 |
+
seen.add(wordIndex);
|
| 225 |
+
let prediction = 0;
|
| 226 |
+
let best = -Infinity;
|
| 227 |
+
for (let labelIndex = 0; labelIndex < labelCount; labelIndex += 1) {
|
| 228 |
+
const value = logits.data[tokenIndex * labelCount + labelIndex];
|
| 229 |
+
if (value > best) {
|
| 230 |
+
best = value;
|
| 231 |
+
prediction = labelIndex;
|
| 232 |
+
}
|
| 233 |
+
}
|
| 234 |
+
const label = labels[String(prediction)];
|
| 235 |
+
const upper = label.endsWith("|U");
|
| 236 |
+
const mark = upper ? label.slice(0, -2) : label;
|
| 237 |
+
rendered[wordIndex] = `${upper ? capitalize(words[wordIndex]) : words[wordIndex]}${mark === "O" ? "" : mark}`;
|
| 238 |
+
});
|
| 239 |
+
return rendered;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
async function punctuateWords(words) {
|
| 243 |
+
if (!words.length) return [];
|
| 244 |
+
const output = [];
|
| 245 |
+
let nextWord = 0;
|
| 246 |
+
const overlapWords = 24;
|
| 247 |
+
while (nextWord < words.length) {
|
| 248 |
+
let contextStart = Math.max(0, nextWord - overlapWords);
|
| 249 |
+
let windowEnd = maximumWindowEnd(words, contextStart);
|
| 250 |
+
if (windowEnd <= nextWord) {
|
| 251 |
+
contextStart = nextWord;
|
| 252 |
+
windowEnd = maximumWindowEnd(words, contextStart);
|
| 253 |
+
}
|
| 254 |
+
const rendered = await predictWindow(words.slice(contextStart, windowEnd));
|
| 255 |
+
const emitEnd = windowEnd === words.length
|
| 256 |
+
? windowEnd
|
| 257 |
+
: Math.max(nextWord + 1, windowEnd - overlapWords);
|
| 258 |
+
output.push(...rendered.slice(nextWord - contextStart, emitEnd - contextStart));
|
| 259 |
+
nextWord = emitEnd;
|
| 260 |
+
}
|
| 261 |
+
if (output.length !== words.length) throw new Error("PnC ændrede antallet af ord");
|
| 262 |
+
return output;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
async function punctuateSegments(segments) {
|
| 266 |
+
const counts = [];
|
| 267 |
+
const sourceWords = [];
|
| 268 |
+
segments.forEach((segment) => {
|
| 269 |
+
const words = Array.isArray(segment.words) && segment.words.length
|
| 270 |
+
? segment.words.map((word) => word.text)
|
| 271 |
+
: String(segment.text || "").trim().split(/\s+/).filter(Boolean);
|
| 272 |
+
counts.push(words.length);
|
| 273 |
+
sourceWords.push(...words);
|
| 274 |
+
});
|
| 275 |
+
const renderedWords = stabilizeRenderedWords(await punctuateWords(sourceWords));
|
| 276 |
+
let offset = 0;
|
| 277 |
+
return segments.map((segment, segmentIndex) => {
|
| 278 |
+
const rendered = renderedWords.slice(offset, offset + counts[segmentIndex]);
|
| 279 |
+
offset += counts[segmentIndex];
|
| 280 |
+
const words = Array.isArray(segment.words) && segment.words.length
|
| 281 |
+
? segment.words.map((word, wordIndex) => ({...word, text: rendered[wordIndex]}))
|
| 282 |
+
: segment.words;
|
| 283 |
+
return {
|
| 284 |
+
...segment,
|
| 285 |
+
rawText: segment.rawText || segment.text,
|
| 286 |
+
text: rendered.join(" "),
|
| 287 |
+
words,
|
| 288 |
+
};
|
| 289 |
+
});
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
async function drainRequests() {
|
| 293 |
+
if (processing) return;
|
| 294 |
+
processing = true;
|
| 295 |
+
try {
|
| 296 |
+
while (pendingRequest) {
|
| 297 |
+
const request = pendingRequest;
|
| 298 |
+
pendingRequest = null;
|
| 299 |
+
await initialization;
|
| 300 |
+
const segments = await punctuateSegments(request.segments);
|
| 301 |
+
self.postMessage({type: "pnc-result", requestId: request.requestId, segments});
|
| 302 |
+
}
|
| 303 |
+
} catch (error) {
|
| 304 |
+
self.postMessage({
|
| 305 |
+
type: "pnc-error",
|
| 306 |
+
message: error instanceof Error ? error.message : String(error),
|
| 307 |
+
});
|
| 308 |
+
} finally {
|
| 309 |
+
processing = false;
|
| 310 |
+
}
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
self.onmessage = (event) => {
|
| 314 |
+
const message = event.data || {};
|
| 315 |
+
if (message.type === "init") {
|
| 316 |
+
initialization ||= initialize(message.configUrl || "model-config.json");
|
| 317 |
+
initialization.catch((error) => self.postMessage({
|
| 318 |
+
type: "pnc-error",
|
| 319 |
+
message: error instanceof Error ? error.message : String(error),
|
| 320 |
+
}));
|
| 321 |
+
} else if (message.type === "punctuate") {
|
| 322 |
+
initialization ||= initialize(message.configUrl || "model-config.json");
|
| 323 |
+
pendingRequest = message;
|
| 324 |
+
drainRequests();
|
| 325 |
+
}
|
| 326 |
+
};
|
sherpa-onnx-asr.js
ADDED
|
@@ -0,0 +1,2011 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
function freeConfig(config, Module) {
|
| 2 |
+
if ('buffer' in config) {
|
| 3 |
+
Module._free(config.buffer);
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
if ('config' in config) {
|
| 7 |
+
freeConfig(config.config, Module)
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
if ('transducer' in config) {
|
| 11 |
+
freeConfig(config.transducer, Module)
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
if ('paraformer' in config) {
|
| 15 |
+
freeConfig(config.paraformer, Module)
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
if ('zipformer2Ctc' in config) {
|
| 19 |
+
freeConfig(config.zipformer2Ctc, Module)
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
if ('feat' in config) {
|
| 23 |
+
freeConfig(config.feat, Module)
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
if ('model' in config) {
|
| 27 |
+
freeConfig(config.model, Module)
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
if ('nemoCtc' in config) {
|
| 31 |
+
freeConfig(config.nemoCtc, Module)
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
if ('toneCtc' in config) {
|
| 35 |
+
freeConfig(config.toneCtc, Module)
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
if ('whisper' in config) {
|
| 39 |
+
freeConfig(config.whisper, Module)
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
if ('fireRedAsr' in config) {
|
| 43 |
+
freeConfig(config.fireRedAsr, Module)
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
if ('dolphin' in config) {
|
| 47 |
+
freeConfig(config.dolphin, Module)
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
if ('zipformerCtc' in config) {
|
| 51 |
+
freeConfig(config.zipformerCtc, Module)
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
if ('wenetCtc' in config) {
|
| 55 |
+
freeConfig(config.wenetCtc, Module)
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
if ('omnilingual' in config) {
|
| 59 |
+
freeConfig(config.omnilingual, Module)
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
if ('medasr' in config) {
|
| 63 |
+
freeConfig(config.medasr, Module)
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
if ('fireRedAsrCtc' in config) {
|
| 67 |
+
freeConfig(config.fireRedAsrCtc, Module)
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
if ('qwen3Asr' in config) {
|
| 71 |
+
freeConfig(config.qwen3Asr, Module)
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
if ('cohereTranscribe' in config) {
|
| 75 |
+
freeConfig(config.cohereTranscribe, Module)
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
if ('funasrNano' in config) {
|
| 79 |
+
freeConfig(config.funasrNano, Module)
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
if ('moonshine' in config) {
|
| 83 |
+
freeConfig(config.moonshine, Module)
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
if ('tdnn' in config) {
|
| 87 |
+
freeConfig(config.tdnn, Module)
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
if ('senseVoice' in config) {
|
| 91 |
+
freeConfig(config.senseVoice, Module)
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
if ('canary' in config) {
|
| 95 |
+
freeConfig(config.canary, Module)
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
if ('lm' in config) {
|
| 99 |
+
freeConfig(config.lm, Module)
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
if ('ctcFstDecoder' in config) {
|
| 103 |
+
freeConfig(config.ctcFstDecoder, Module)
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
if ('hr' in config) {
|
| 107 |
+
freeConfig(config.hr, Module)
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
Module._free(config.ptr);
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
// The user should free the returned pointers
|
| 114 |
+
function initSherpaOnnxOnlineTransducerModelConfig(config, Module) {
|
| 115 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 116 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 117 |
+
const joinerLen = Module.lengthBytesUTF8(config.joiner || '') + 1;
|
| 118 |
+
|
| 119 |
+
const n = encoderLen + decoderLen + joinerLen;
|
| 120 |
+
|
| 121 |
+
const buffer = Module._malloc(n);
|
| 122 |
+
|
| 123 |
+
const len = 3 * 4; // 3 pointers
|
| 124 |
+
const ptr = Module._malloc(len);
|
| 125 |
+
|
| 126 |
+
let offset = 0;
|
| 127 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 128 |
+
offset += encoderLen;
|
| 129 |
+
|
| 130 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 131 |
+
offset += decoderLen;
|
| 132 |
+
|
| 133 |
+
Module.stringToUTF8(config.joiner || '', buffer + offset, joinerLen);
|
| 134 |
+
|
| 135 |
+
offset = 0;
|
| 136 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 137 |
+
offset += encoderLen;
|
| 138 |
+
|
| 139 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 140 |
+
offset += decoderLen;
|
| 141 |
+
|
| 142 |
+
Module.setValue(ptr + 8, buffer + offset, 'i8*');
|
| 143 |
+
|
| 144 |
+
return {
|
| 145 |
+
buffer: buffer,
|
| 146 |
+
ptr: ptr,
|
| 147 |
+
len: len,
|
| 148 |
+
};
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
function initSherpaOnnxOnlineParaformerModelConfig(config, Module) {
|
| 152 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 153 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 154 |
+
|
| 155 |
+
const n = encoderLen + decoderLen;
|
| 156 |
+
const buffer = Module._malloc(n);
|
| 157 |
+
|
| 158 |
+
const len = 2 * 4; // 2 pointers
|
| 159 |
+
const ptr = Module._malloc(len);
|
| 160 |
+
|
| 161 |
+
let offset = 0;
|
| 162 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 163 |
+
offset += encoderLen;
|
| 164 |
+
|
| 165 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 166 |
+
|
| 167 |
+
offset = 0;
|
| 168 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 169 |
+
offset += encoderLen;
|
| 170 |
+
|
| 171 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 172 |
+
|
| 173 |
+
return {
|
| 174 |
+
buffer: buffer,
|
| 175 |
+
ptr: ptr,
|
| 176 |
+
len: len,
|
| 177 |
+
};
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
function initSherpaOnnxOnlineZipformer2CtcModelConfig(config, Module) {
|
| 181 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 182 |
+
const buffer = Module._malloc(n);
|
| 183 |
+
|
| 184 |
+
const len = 1 * 4; // 1 pointer
|
| 185 |
+
const ptr = Module._malloc(len);
|
| 186 |
+
|
| 187 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 188 |
+
|
| 189 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 190 |
+
|
| 191 |
+
return {
|
| 192 |
+
buffer: buffer,
|
| 193 |
+
ptr: ptr,
|
| 194 |
+
len: len,
|
| 195 |
+
};
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
function initSherpaOnnxOnlineNemoCtcModelConfig(config, Module) {
|
| 199 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 200 |
+
const buffer = Module._malloc(n);
|
| 201 |
+
|
| 202 |
+
const len = 1 * 4; // 1 pointer
|
| 203 |
+
const ptr = Module._malloc(len);
|
| 204 |
+
|
| 205 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 206 |
+
|
| 207 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 208 |
+
|
| 209 |
+
return {
|
| 210 |
+
buffer: buffer,
|
| 211 |
+
ptr: ptr,
|
| 212 |
+
len: len,
|
| 213 |
+
};
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
function initSherpaOnnxOnlineToneCtcModelConfig(config, Module) {
|
| 217 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 218 |
+
const buffer = Module._malloc(n);
|
| 219 |
+
|
| 220 |
+
const len = 1 * 4; // 1 pointer
|
| 221 |
+
const ptr = Module._malloc(len);
|
| 222 |
+
|
| 223 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 224 |
+
|
| 225 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 226 |
+
|
| 227 |
+
return {
|
| 228 |
+
buffer: buffer,
|
| 229 |
+
ptr: ptr,
|
| 230 |
+
len: len,
|
| 231 |
+
};
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
function initSherpaOnnxOnlineModelConfig(config, Module) {
|
| 235 |
+
if (!('transducer' in config)) {
|
| 236 |
+
config.transducer = {
|
| 237 |
+
encoder: '',
|
| 238 |
+
decoder: '',
|
| 239 |
+
joiner: '',
|
| 240 |
+
};
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
if (!('paraformer' in config)) {
|
| 244 |
+
config.paraformer = {
|
| 245 |
+
encoder: '',
|
| 246 |
+
decoder: '',
|
| 247 |
+
};
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
if (!('zipformer2Ctc' in config)) {
|
| 251 |
+
config.zipformer2Ctc = {
|
| 252 |
+
model: '',
|
| 253 |
+
};
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
if (!('nemoCtc' in config)) {
|
| 257 |
+
config.nemoCtc = {
|
| 258 |
+
model: '',
|
| 259 |
+
};
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
if (!('toneCtc' in config)) {
|
| 263 |
+
config.toneCtc = {
|
| 264 |
+
model: '',
|
| 265 |
+
};
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
if (!('tokensBuf' in config)) {
|
| 269 |
+
config.tokensBuf = '';
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
if (!('tokensBufSize' in config)) {
|
| 273 |
+
config.tokensBufSize = 0;
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
const transducer =
|
| 277 |
+
initSherpaOnnxOnlineTransducerModelConfig(config.transducer, Module);
|
| 278 |
+
|
| 279 |
+
const paraformer =
|
| 280 |
+
initSherpaOnnxOnlineParaformerModelConfig(config.paraformer, Module);
|
| 281 |
+
|
| 282 |
+
const zipformer2Ctc = initSherpaOnnxOnlineZipformer2CtcModelConfig(
|
| 283 |
+
config.zipformer2Ctc, Module);
|
| 284 |
+
|
| 285 |
+
const nemoCtc =
|
| 286 |
+
initSherpaOnnxOnlineNemoCtcModelConfig(config.nemoCtc, Module);
|
| 287 |
+
|
| 288 |
+
const toneCtc =
|
| 289 |
+
initSherpaOnnxOnlineToneCtcModelConfig(config.toneCtc, Module);
|
| 290 |
+
|
| 291 |
+
const len = transducer.len + paraformer.len + zipformer2Ctc.len + 9 * 4 +
|
| 292 |
+
nemoCtc.len + toneCtc.len;
|
| 293 |
+
|
| 294 |
+
const ptr = Module._malloc(len);
|
| 295 |
+
|
| 296 |
+
let offset = 0;
|
| 297 |
+
Module._CopyHeap(transducer.ptr, transducer.len, ptr + offset);
|
| 298 |
+
offset += transducer.len;
|
| 299 |
+
|
| 300 |
+
Module._CopyHeap(paraformer.ptr, paraformer.len, ptr + offset);
|
| 301 |
+
offset += paraformer.len;
|
| 302 |
+
|
| 303 |
+
Module._CopyHeap(zipformer2Ctc.ptr, zipformer2Ctc.len, ptr + offset);
|
| 304 |
+
offset += zipformer2Ctc.len;
|
| 305 |
+
|
| 306 |
+
const tokensLen = Module.lengthBytesUTF8(config.tokens || '') + 1;
|
| 307 |
+
const providerLen = Module.lengthBytesUTF8(config.provider || 'cpu') + 1;
|
| 308 |
+
const modelTypeLen = Module.lengthBytesUTF8(config.modelType || '') + 1;
|
| 309 |
+
const modelingUnitLen = Module.lengthBytesUTF8(config.modelingUnit || '') + 1;
|
| 310 |
+
const bpeVocabLen = Module.lengthBytesUTF8(config.bpeVocab || '') + 1;
|
| 311 |
+
const tokensBufLen = Module.lengthBytesUTF8(config.tokensBuf || '') + 1;
|
| 312 |
+
|
| 313 |
+
const bufferLen = tokensLen + providerLen + modelTypeLen + modelingUnitLen +
|
| 314 |
+
bpeVocabLen + tokensBufLen;
|
| 315 |
+
const buffer = Module._malloc(bufferLen);
|
| 316 |
+
|
| 317 |
+
offset = 0;
|
| 318 |
+
Module.stringToUTF8(config.tokens || '', buffer, tokensLen);
|
| 319 |
+
offset += tokensLen;
|
| 320 |
+
|
| 321 |
+
Module.stringToUTF8(config.provider || 'cpu', buffer + offset, providerLen);
|
| 322 |
+
offset += providerLen;
|
| 323 |
+
|
| 324 |
+
Module.stringToUTF8(config.modelType || '', buffer + offset, modelTypeLen);
|
| 325 |
+
offset += modelTypeLen;
|
| 326 |
+
|
| 327 |
+
Module.stringToUTF8(
|
| 328 |
+
config.modelingUnit || '', buffer + offset, modelingUnitLen);
|
| 329 |
+
offset += modelingUnitLen;
|
| 330 |
+
|
| 331 |
+
Module.stringToUTF8(config.bpeVocab || '', buffer + offset, bpeVocabLen);
|
| 332 |
+
offset += bpeVocabLen;
|
| 333 |
+
|
| 334 |
+
Module.stringToUTF8(config.tokensBuf || '', buffer + offset, tokensBufLen);
|
| 335 |
+
offset += tokensBufLen;
|
| 336 |
+
|
| 337 |
+
offset = transducer.len + paraformer.len + zipformer2Ctc.len;
|
| 338 |
+
Module.setValue(ptr + offset, buffer, 'i8*'); // tokens
|
| 339 |
+
offset += 4;
|
| 340 |
+
|
| 341 |
+
Module.setValue(ptr + offset, config.numThreads || 1, 'i32');
|
| 342 |
+
offset += 4;
|
| 343 |
+
|
| 344 |
+
Module.setValue(ptr + offset, buffer + tokensLen, 'i8*'); // provider
|
| 345 |
+
offset += 4;
|
| 346 |
+
|
| 347 |
+
Module.setValue(ptr + offset, config.debug ?? 1, 'i32');
|
| 348 |
+
offset += 4;
|
| 349 |
+
|
| 350 |
+
Module.setValue(
|
| 351 |
+
ptr + offset, buffer + tokensLen + providerLen, 'i8*'); // modelType
|
| 352 |
+
offset += 4;
|
| 353 |
+
|
| 354 |
+
Module.setValue(
|
| 355 |
+
ptr + offset, buffer + tokensLen + providerLen + modelTypeLen,
|
| 356 |
+
'i8*'); // modelingUnit
|
| 357 |
+
offset += 4;
|
| 358 |
+
|
| 359 |
+
Module.setValue(
|
| 360 |
+
ptr + offset,
|
| 361 |
+
buffer + tokensLen + providerLen + modelTypeLen + modelingUnitLen,
|
| 362 |
+
'i8*'); // bpeVocab
|
| 363 |
+
offset += 4;
|
| 364 |
+
|
| 365 |
+
Module.setValue(
|
| 366 |
+
ptr + offset,
|
| 367 |
+
buffer + tokensLen + providerLen + modelTypeLen + modelingUnitLen +
|
| 368 |
+
bpeVocabLen,
|
| 369 |
+
'i8*'); // tokens_buf
|
| 370 |
+
offset += 4;
|
| 371 |
+
|
| 372 |
+
Module.setValue(ptr + offset, config.tokensBufSize || 0, 'i32');
|
| 373 |
+
offset += 4;
|
| 374 |
+
|
| 375 |
+
Module._CopyHeap(nemoCtc.ptr, nemoCtc.len, ptr + offset);
|
| 376 |
+
offset += nemoCtc.len;
|
| 377 |
+
|
| 378 |
+
Module._CopyHeap(toneCtc.ptr, toneCtc.len, ptr + offset);
|
| 379 |
+
offset += toneCtc.len;
|
| 380 |
+
|
| 381 |
+
return {
|
| 382 |
+
buffer: buffer,
|
| 383 |
+
ptr: ptr,
|
| 384 |
+
len: len,
|
| 385 |
+
transducer: transducer,
|
| 386 |
+
paraformer: paraformer,
|
| 387 |
+
zipformer2Ctc: zipformer2Ctc,
|
| 388 |
+
nemoCtc: nemoCtc,
|
| 389 |
+
toneCtc: toneCtc,
|
| 390 |
+
};
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
function initSherpaOnnxFeatureConfig(config, Module) {
|
| 394 |
+
const len = 2 * 4; // 2 pointers
|
| 395 |
+
const ptr = Module._malloc(len);
|
| 396 |
+
|
| 397 |
+
Module.setValue(ptr, config.sampleRate || 16000, 'i32');
|
| 398 |
+
Module.setValue(ptr + 4, config.featureDim || 80, 'i32');
|
| 399 |
+
return {ptr: ptr, len: len};
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
function initSherpaOnnxHomophoneReplacerConfig(config, Module) {
|
| 403 |
+
const len = 3 * 4;
|
| 404 |
+
const ptr = Module._malloc(len);
|
| 405 |
+
|
| 406 |
+
const dictDir = '';
|
| 407 |
+
|
| 408 |
+
const dictDirLen = Module.lengthBytesUTF8(dictDir) + 1;
|
| 409 |
+
const lexiconLen = Module.lengthBytesUTF8(config.lexicon || '') + 1;
|
| 410 |
+
const ruleFstsLen = Module.lengthBytesUTF8(config.ruleFsts || '') + 1;
|
| 411 |
+
|
| 412 |
+
const bufferLen = dictDirLen + lexiconLen + ruleFstsLen;
|
| 413 |
+
|
| 414 |
+
const buffer = Module._malloc(bufferLen);
|
| 415 |
+
let offset = 0
|
| 416 |
+
Module.stringToUTF8(dictDir, buffer + offset, dictDirLen);
|
| 417 |
+
offset += dictDirLen;
|
| 418 |
+
|
| 419 |
+
Module.stringToUTF8(config.lexicon || '', buffer + offset, lexiconLen);
|
| 420 |
+
offset += lexiconLen;
|
| 421 |
+
|
| 422 |
+
Module.stringToUTF8(config.ruleFsts || '', buffer + offset, ruleFstsLen);
|
| 423 |
+
offset += ruleFstsLen;
|
| 424 |
+
|
| 425 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 426 |
+
Module.setValue(ptr + 4, buffer + dictDirLen, 'i8*');
|
| 427 |
+
Module.setValue(ptr + 8, buffer + dictDirLen + lexiconLen, 'i8*');
|
| 428 |
+
|
| 429 |
+
return {ptr: ptr, len: len, buffer: buffer};
|
| 430 |
+
}
|
| 431 |
+
|
| 432 |
+
function initSherpaOnnxOnlineCtcFstDecoderConfig(config, Module) {
|
| 433 |
+
const len = 2 * 4;
|
| 434 |
+
const ptr = Module._malloc(len);
|
| 435 |
+
|
| 436 |
+
const graphLen = Module.lengthBytesUTF8(config.graph || '') + 1;
|
| 437 |
+
const buffer = Module._malloc(graphLen);
|
| 438 |
+
Module.stringToUTF8(config.graph, buffer, graphLen);
|
| 439 |
+
|
| 440 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 441 |
+
Module.setValue(ptr + 4, config.maxActive || 3000, 'i32');
|
| 442 |
+
return {ptr: ptr, len: len, buffer: buffer};
|
| 443 |
+
}
|
| 444 |
+
|
| 445 |
+
function initSherpaOnnxOnlineRecognizerConfig(config, Module) {
|
| 446 |
+
if (!('featConfig' in config)) {
|
| 447 |
+
config.featConfig = {
|
| 448 |
+
sampleRate: 16000,
|
| 449 |
+
featureDim: 80,
|
| 450 |
+
};
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
if (!('ctcFstDecoderConfig' in config)) {
|
| 454 |
+
config.ctcFstDecoderConfig = {
|
| 455 |
+
graph: '',
|
| 456 |
+
maxActive: 3000,
|
| 457 |
+
};
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
if (!('hotwordsBuf' in config)) {
|
| 461 |
+
config.hotwordsBuf = '';
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
if (!('hotwordsBufSize' in config)) {
|
| 465 |
+
config.hotwordsBufSize = 0;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
if (!('hr' in config)) {
|
| 469 |
+
config.hr = {
|
| 470 |
+
lexicon: '',
|
| 471 |
+
ruleFsts: '',
|
| 472 |
+
};
|
| 473 |
+
}
|
| 474 |
+
|
| 475 |
+
const feat = initSherpaOnnxFeatureConfig(config.featConfig, Module);
|
| 476 |
+
const model = initSherpaOnnxOnlineModelConfig(config.modelConfig, Module);
|
| 477 |
+
const ctcFstDecoder = initSherpaOnnxOnlineCtcFstDecoderConfig(
|
| 478 |
+
config.ctcFstDecoderConfig, Module)
|
| 479 |
+
const hr = initSherpaOnnxHomophoneReplacerConfig(config.hr, Module);
|
| 480 |
+
|
| 481 |
+
const len = feat.len + model.len + 8 * 4 + ctcFstDecoder.len + 5 * 4 + hr.len;
|
| 482 |
+
const ptr = Module._malloc(len);
|
| 483 |
+
|
| 484 |
+
let offset = 0;
|
| 485 |
+
Module._CopyHeap(feat.ptr, feat.len, ptr + offset);
|
| 486 |
+
offset += feat.len;
|
| 487 |
+
|
| 488 |
+
Module._CopyHeap(model.ptr, model.len, ptr + offset);
|
| 489 |
+
offset += model.len;
|
| 490 |
+
|
| 491 |
+
const decodingMethodLen =
|
| 492 |
+
Module.lengthBytesUTF8(config.decodingMethod || 'greedy_search') + 1;
|
| 493 |
+
const hotwordsFileLen = Module.lengthBytesUTF8(config.hotwordsFile || '') + 1;
|
| 494 |
+
const ruleFstsFileLen = Module.lengthBytesUTF8(config.ruleFsts || '') + 1;
|
| 495 |
+
const ruleFarsFileLen = Module.lengthBytesUTF8(config.ruleFars || '') + 1;
|
| 496 |
+
const hotwordsBufLen = Module.lengthBytesUTF8(config.hotwordsBuf || '') + 1;
|
| 497 |
+
const bufferLen = decodingMethodLen + hotwordsFileLen + ruleFstsFileLen +
|
| 498 |
+
ruleFarsFileLen + hotwordsBufLen;
|
| 499 |
+
const buffer = Module._malloc(bufferLen);
|
| 500 |
+
|
| 501 |
+
offset = 0;
|
| 502 |
+
Module.stringToUTF8(
|
| 503 |
+
config.decodingMethod || 'greedy_search', buffer, decodingMethodLen);
|
| 504 |
+
offset += decodingMethodLen;
|
| 505 |
+
|
| 506 |
+
Module.stringToUTF8(
|
| 507 |
+
config.hotwordsFile || '', buffer + offset, hotwordsFileLen);
|
| 508 |
+
offset += hotwordsFileLen;
|
| 509 |
+
|
| 510 |
+
Module.stringToUTF8(config.ruleFsts || '', buffer + offset, ruleFstsFileLen);
|
| 511 |
+
offset += ruleFstsFileLen;
|
| 512 |
+
|
| 513 |
+
Module.stringToUTF8(config.ruleFars || '', buffer + offset, ruleFarsFileLen);
|
| 514 |
+
offset += ruleFarsFileLen;
|
| 515 |
+
|
| 516 |
+
Module.stringToUTF8(
|
| 517 |
+
config.hotwordsBuf || '', buffer + offset, hotwordsBufLen);
|
| 518 |
+
offset += hotwordsBufLen;
|
| 519 |
+
|
| 520 |
+
offset = feat.len + model.len;
|
| 521 |
+
Module.setValue(ptr + offset, buffer, 'i8*'); // decoding method
|
| 522 |
+
offset += 4;
|
| 523 |
+
|
| 524 |
+
Module.setValue(ptr + offset, config.maxActivePaths || 4, 'i32');
|
| 525 |
+
offset += 4;
|
| 526 |
+
|
| 527 |
+
Module.setValue(ptr + offset, config.enableEndpoint || 0, 'i32');
|
| 528 |
+
offset += 4;
|
| 529 |
+
|
| 530 |
+
Module.setValue(ptr + offset, config.rule1MinTrailingSilence || 2.4, 'float');
|
| 531 |
+
offset += 4;
|
| 532 |
+
|
| 533 |
+
Module.setValue(ptr + offset, config.rule2MinTrailingSilence || 1.2, 'float');
|
| 534 |
+
offset += 4;
|
| 535 |
+
|
| 536 |
+
Module.setValue(ptr + offset, config.rule3MinUtteranceLength || 20, 'float');
|
| 537 |
+
offset += 4;
|
| 538 |
+
|
| 539 |
+
Module.setValue(ptr + offset, buffer + decodingMethodLen, 'i8*');
|
| 540 |
+
offset += 4;
|
| 541 |
+
|
| 542 |
+
Module.setValue(ptr + offset, config.hotwordsScore || 1.5, 'float');
|
| 543 |
+
offset += 4;
|
| 544 |
+
|
| 545 |
+
Module._CopyHeap(ctcFstDecoder.ptr, ctcFstDecoder.len, ptr + offset);
|
| 546 |
+
offset += ctcFstDecoder.len;
|
| 547 |
+
|
| 548 |
+
Module.setValue(
|
| 549 |
+
ptr + offset, buffer + decodingMethodLen + hotwordsFileLen, 'i8*');
|
| 550 |
+
offset += 4;
|
| 551 |
+
|
| 552 |
+
Module.setValue(
|
| 553 |
+
ptr + offset,
|
| 554 |
+
buffer + decodingMethodLen + hotwordsFileLen + ruleFstsFileLen, 'i8*');
|
| 555 |
+
offset += 4;
|
| 556 |
+
|
| 557 |
+
Module.setValue(ptr + offset, config.blankPenalty || 0, 'float');
|
| 558 |
+
offset += 4;
|
| 559 |
+
|
| 560 |
+
Module.setValue(
|
| 561 |
+
ptr + offset,
|
| 562 |
+
buffer + decodingMethodLen + hotwordsFileLen + ruleFstsFileLen +
|
| 563 |
+
ruleFarsFileLen,
|
| 564 |
+
'i8*');
|
| 565 |
+
offset += 4;
|
| 566 |
+
|
| 567 |
+
Module.setValue(ptr + offset, config.hotwordsBufSize || 0, 'i32');
|
| 568 |
+
offset += 4;
|
| 569 |
+
|
| 570 |
+
Module._CopyHeap(hr.ptr, hr.len, ptr + offset);
|
| 571 |
+
offset += hr.len;
|
| 572 |
+
|
| 573 |
+
return {
|
| 574 |
+
buffer: buffer,
|
| 575 |
+
ptr: ptr,
|
| 576 |
+
len: len,
|
| 577 |
+
feat: feat,
|
| 578 |
+
model: model,
|
| 579 |
+
ctcFstDecoder: ctcFstDecoder,
|
| 580 |
+
hr: hr,
|
| 581 |
+
};
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
function createOnlineRecognizer(Module, myConfig) {
|
| 585 |
+
const onlineTransducerModelConfig = {
|
| 586 |
+
encoder: '',
|
| 587 |
+
decoder: '',
|
| 588 |
+
joiner: '',
|
| 589 |
+
};
|
| 590 |
+
|
| 591 |
+
const onlineParaformerModelConfig = {
|
| 592 |
+
encoder: '',
|
| 593 |
+
decoder: '',
|
| 594 |
+
};
|
| 595 |
+
|
| 596 |
+
const onlineZipformer2CtcModelConfig = {
|
| 597 |
+
model: '',
|
| 598 |
+
};
|
| 599 |
+
|
| 600 |
+
const onlineNemoCtcModelConfig = {
|
| 601 |
+
model: '',
|
| 602 |
+
};
|
| 603 |
+
|
| 604 |
+
const onlineToneCtcModelConfig = {
|
| 605 |
+
model: '',
|
| 606 |
+
};
|
| 607 |
+
|
| 608 |
+
let type = 0;
|
| 609 |
+
|
| 610 |
+
switch (type) {
|
| 611 |
+
case 0:
|
| 612 |
+
// transducer
|
| 613 |
+
onlineTransducerModelConfig.encoder = './encoder.onnx';
|
| 614 |
+
onlineTransducerModelConfig.decoder = './decoder.onnx';
|
| 615 |
+
onlineTransducerModelConfig.joiner = './joiner.onnx';
|
| 616 |
+
break;
|
| 617 |
+
case 1:
|
| 618 |
+
// paraformer
|
| 619 |
+
onlineParaformerModelConfig.encoder = './encoder.onnx';
|
| 620 |
+
onlineParaformerModelConfig.decoder = './decoder.onnx';
|
| 621 |
+
break;
|
| 622 |
+
case 2:
|
| 623 |
+
// zipformer2Ctc
|
| 624 |
+
onlineZipformer2CtcModelConfig.model = './encoder.onnx';
|
| 625 |
+
break;
|
| 626 |
+
case 3:
|
| 627 |
+
// nemoCtc
|
| 628 |
+
onlineNemoCtcModelConfig.model = './nemo-ctc.onnx';
|
| 629 |
+
break;
|
| 630 |
+
case 4:
|
| 631 |
+
// toneCtc
|
| 632 |
+
onlineToneCtcModelConfig.model = './tone-ctc.onnx';
|
| 633 |
+
break;
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
|
| 637 |
+
const onlineModelConfig = {
|
| 638 |
+
transducer: onlineTransducerModelConfig,
|
| 639 |
+
paraformer: onlineParaformerModelConfig,
|
| 640 |
+
zipformer2Ctc: onlineZipformer2CtcModelConfig,
|
| 641 |
+
nemoCtc: onlineNemoCtcModelConfig,
|
| 642 |
+
toneCtc: onlineToneCtcModelConfig,
|
| 643 |
+
tokens: './tokens.txt',
|
| 644 |
+
numThreads: 1,
|
| 645 |
+
provider: 'cpu',
|
| 646 |
+
debug: 1,
|
| 647 |
+
modelType: '',
|
| 648 |
+
modelingUnit: 'cjkchar',
|
| 649 |
+
bpeVocab: '',
|
| 650 |
+
};
|
| 651 |
+
|
| 652 |
+
const featureConfig = {
|
| 653 |
+
sampleRate: 16000, // it is ignored when toneCtc is used
|
| 654 |
+
featureDim: 80, // it is ignored when toneCtc is used
|
| 655 |
+
};
|
| 656 |
+
|
| 657 |
+
let recognizerConfig = {
|
| 658 |
+
featConfig: featureConfig,
|
| 659 |
+
modelConfig: onlineModelConfig,
|
| 660 |
+
decodingMethod: 'greedy_search',
|
| 661 |
+
maxActivePaths: 4,
|
| 662 |
+
enableEndpoint: 1,
|
| 663 |
+
rule1MinTrailingSilence: 2.4,
|
| 664 |
+
rule2MinTrailingSilence: 1.2,
|
| 665 |
+
rule3MinUtteranceLength: 20,
|
| 666 |
+
hotwordsFile: '',
|
| 667 |
+
hotwordsScore: 1.5,
|
| 668 |
+
ctcFstDecoderConfig: {
|
| 669 |
+
graph: '',
|
| 670 |
+
maxActive: 3000,
|
| 671 |
+
},
|
| 672 |
+
ruleFsts: '',
|
| 673 |
+
ruleFars: '',
|
| 674 |
+
};
|
| 675 |
+
if (myConfig) {
|
| 676 |
+
recognizerConfig = myConfig;
|
| 677 |
+
}
|
| 678 |
+
|
| 679 |
+
return new OnlineRecognizer(recognizerConfig, Module);
|
| 680 |
+
}
|
| 681 |
+
|
| 682 |
+
function initSherpaOnnxOfflineTransducerModelConfig(config, Module) {
|
| 683 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 684 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 685 |
+
const joinerLen = Module.lengthBytesUTF8(config.joiner || '') + 1;
|
| 686 |
+
|
| 687 |
+
const n = encoderLen + decoderLen + joinerLen;
|
| 688 |
+
|
| 689 |
+
const buffer = Module._malloc(n);
|
| 690 |
+
|
| 691 |
+
const len = 3 * 4; // 3 pointers
|
| 692 |
+
const ptr = Module._malloc(len);
|
| 693 |
+
|
| 694 |
+
let offset = 0;
|
| 695 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 696 |
+
offset += encoderLen;
|
| 697 |
+
|
| 698 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 699 |
+
offset += decoderLen;
|
| 700 |
+
|
| 701 |
+
Module.stringToUTF8(config.joiner || '', buffer + offset, joinerLen);
|
| 702 |
+
|
| 703 |
+
offset = 0;
|
| 704 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 705 |
+
offset += encoderLen;
|
| 706 |
+
|
| 707 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 708 |
+
offset += decoderLen;
|
| 709 |
+
|
| 710 |
+
Module.setValue(ptr + 8, buffer + offset, 'i8*');
|
| 711 |
+
|
| 712 |
+
return {
|
| 713 |
+
buffer: buffer,
|
| 714 |
+
ptr: ptr,
|
| 715 |
+
len: len,
|
| 716 |
+
};
|
| 717 |
+
}
|
| 718 |
+
|
| 719 |
+
function initSherpaOnnxOfflineParaformerModelConfig(config, Module) {
|
| 720 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 721 |
+
|
| 722 |
+
const buffer = Module._malloc(n);
|
| 723 |
+
|
| 724 |
+
const len = 1 * 4; // 1 pointer
|
| 725 |
+
const ptr = Module._malloc(len);
|
| 726 |
+
|
| 727 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 728 |
+
|
| 729 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 730 |
+
|
| 731 |
+
return {
|
| 732 |
+
buffer: buffer,
|
| 733 |
+
ptr: ptr,
|
| 734 |
+
len: len,
|
| 735 |
+
};
|
| 736 |
+
}
|
| 737 |
+
|
| 738 |
+
function initSherpaOnnxOfflineNemoEncDecCtcModelConfig(config, Module) {
|
| 739 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 740 |
+
|
| 741 |
+
const buffer = Module._malloc(n);
|
| 742 |
+
|
| 743 |
+
const len = 1 * 4; // 1 pointer
|
| 744 |
+
const ptr = Module._malloc(len);
|
| 745 |
+
|
| 746 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 747 |
+
|
| 748 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 749 |
+
|
| 750 |
+
return {
|
| 751 |
+
buffer: buffer,
|
| 752 |
+
ptr: ptr,
|
| 753 |
+
len: len,
|
| 754 |
+
};
|
| 755 |
+
}
|
| 756 |
+
|
| 757 |
+
function initSherpaOnnxOfflineDolphinModelConfig(config, Module) {
|
| 758 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 759 |
+
|
| 760 |
+
const buffer = Module._malloc(n);
|
| 761 |
+
|
| 762 |
+
const len = 1 * 4; // 1 pointer
|
| 763 |
+
const ptr = Module._malloc(len);
|
| 764 |
+
|
| 765 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 766 |
+
|
| 767 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 768 |
+
|
| 769 |
+
return {
|
| 770 |
+
buffer: buffer,
|
| 771 |
+
ptr: ptr,
|
| 772 |
+
len: len,
|
| 773 |
+
};
|
| 774 |
+
}
|
| 775 |
+
|
| 776 |
+
function initSherpaOnnxOfflineZipformerCtcModelConfig(config, Module) {
|
| 777 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 778 |
+
|
| 779 |
+
const buffer = Module._malloc(n);
|
| 780 |
+
|
| 781 |
+
const len = 1 * 4; // 1 pointer
|
| 782 |
+
const ptr = Module._malloc(len);
|
| 783 |
+
|
| 784 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 785 |
+
|
| 786 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 787 |
+
|
| 788 |
+
return {
|
| 789 |
+
buffer: buffer,
|
| 790 |
+
ptr: ptr,
|
| 791 |
+
len: len,
|
| 792 |
+
};
|
| 793 |
+
}
|
| 794 |
+
|
| 795 |
+
function initSherpaOnnxOfflineWenetCtcModelConfig(config, Module) {
|
| 796 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 797 |
+
|
| 798 |
+
const buffer = Module._malloc(n);
|
| 799 |
+
|
| 800 |
+
const len = 1 * 4; // 1 pointer
|
| 801 |
+
const ptr = Module._malloc(len);
|
| 802 |
+
|
| 803 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 804 |
+
|
| 805 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 806 |
+
|
| 807 |
+
return {
|
| 808 |
+
buffer: buffer,
|
| 809 |
+
ptr: ptr,
|
| 810 |
+
len: len,
|
| 811 |
+
};
|
| 812 |
+
}
|
| 813 |
+
|
| 814 |
+
function initSherpaOnnxOfflineOmnilingualAsrCtcModelConfig(config, Module) {
|
| 815 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 816 |
+
|
| 817 |
+
const buffer = Module._malloc(n);
|
| 818 |
+
|
| 819 |
+
const len = 1 * 4; // 1 pointer
|
| 820 |
+
const ptr = Module._malloc(len);
|
| 821 |
+
|
| 822 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 823 |
+
|
| 824 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 825 |
+
|
| 826 |
+
return {
|
| 827 |
+
buffer: buffer,
|
| 828 |
+
ptr: ptr,
|
| 829 |
+
len: len,
|
| 830 |
+
};
|
| 831 |
+
}
|
| 832 |
+
|
| 833 |
+
function initSherpaOnnxOfflineMedAsrCtcModelConfig(config, Module) {
|
| 834 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 835 |
+
|
| 836 |
+
const buffer = Module._malloc(n);
|
| 837 |
+
|
| 838 |
+
const len = 1 * 4; // 1 pointer
|
| 839 |
+
const ptr = Module._malloc(len);
|
| 840 |
+
|
| 841 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 842 |
+
|
| 843 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 844 |
+
|
| 845 |
+
return {
|
| 846 |
+
buffer: buffer,
|
| 847 |
+
ptr: ptr,
|
| 848 |
+
len: len,
|
| 849 |
+
};
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
function initSherpaOnnxOfflineFireRedAsrCtcModelConfig(config, Module) {
|
| 853 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 854 |
+
|
| 855 |
+
const buffer = Module._malloc(n);
|
| 856 |
+
|
| 857 |
+
const len = 1 * 4; // 1 pointer
|
| 858 |
+
const ptr = Module._malloc(len);
|
| 859 |
+
|
| 860 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 861 |
+
|
| 862 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 863 |
+
|
| 864 |
+
return {
|
| 865 |
+
buffer: buffer,
|
| 866 |
+
ptr: ptr,
|
| 867 |
+
len: len,
|
| 868 |
+
};
|
| 869 |
+
}
|
| 870 |
+
|
| 871 |
+
function initSherpaOnnxOfflineFunAsrNanoModelConfig(config, Module) {
|
| 872 |
+
const encoderAdaptorLen =
|
| 873 |
+
Module.lengthBytesUTF8(config.encoderAdaptor || '') + 1;
|
| 874 |
+
const llmLen = Module.lengthBytesUTF8(config.llm || '') + 1;
|
| 875 |
+
const embeddingLen = Module.lengthBytesUTF8(config.embedding || '') + 1;
|
| 876 |
+
const tokenizerLen = Module.lengthBytesUTF8(config.tokenizer || '') + 1;
|
| 877 |
+
const systemPromptLen =
|
| 878 |
+
Module.lengthBytesUTF8(
|
| 879 |
+
config.systemPrompt || 'You are a helpful assistant.') +
|
| 880 |
+
1;
|
| 881 |
+
const userPromptLen =
|
| 882 |
+
Module.lengthBytesUTF8(config.userPrompt || '语音转写:') + 1;
|
| 883 |
+
const languageLen = Module.lengthBytesUTF8(config.language || '') + 1;
|
| 884 |
+
const hotwordsLen = Module.lengthBytesUTF8(config.hotwords || '') + 1;
|
| 885 |
+
|
| 886 |
+
const n = encoderAdaptorLen + llmLen + embeddingLen + tokenizerLen +
|
| 887 |
+
systemPromptLen + userPromptLen + languageLen + hotwordsLen;
|
| 888 |
+
|
| 889 |
+
const buffer = Module._malloc(n);
|
| 890 |
+
|
| 891 |
+
const len = 13 * 4; // 8 pointers + 3 int + 2 float
|
| 892 |
+
const ptr = Module._malloc(len);
|
| 893 |
+
|
| 894 |
+
let offset = 0;
|
| 895 |
+
Module.stringToUTF8(
|
| 896 |
+
config.encoderAdaptor || '', buffer + offset, encoderAdaptorLen);
|
| 897 |
+
offset += encoderAdaptorLen;
|
| 898 |
+
|
| 899 |
+
Module.stringToUTF8(config.llm || '', buffer + offset, llmLen);
|
| 900 |
+
offset += llmLen;
|
| 901 |
+
|
| 902 |
+
Module.stringToUTF8(config.embedding || '', buffer + offset, embeddingLen);
|
| 903 |
+
offset += embeddingLen;
|
| 904 |
+
|
| 905 |
+
Module.stringToUTF8(config.tokenizer || '', buffer + offset, tokenizerLen);
|
| 906 |
+
offset += tokenizerLen;
|
| 907 |
+
|
| 908 |
+
Module.stringToUTF8(
|
| 909 |
+
config.systemPrompt || 'You are a helpful assistant.', buffer + offset,
|
| 910 |
+
systemPromptLen);
|
| 911 |
+
offset += systemPromptLen;
|
| 912 |
+
|
| 913 |
+
Module.stringToUTF8(
|
| 914 |
+
config.userPrompt || '语音转写:', buffer + offset, userPromptLen);
|
| 915 |
+
offset += userPromptLen;
|
| 916 |
+
|
| 917 |
+
Module.stringToUTF8(config.language || '', buffer + offset, languageLen);
|
| 918 |
+
offset += languageLen;
|
| 919 |
+
|
| 920 |
+
Module.stringToUTF8(config.hotwords || '', buffer + offset, hotwordsLen);
|
| 921 |
+
offset += hotwordsLen;
|
| 922 |
+
|
| 923 |
+
offset = 0;
|
| 924 |
+
Module.setValue(ptr + 0 * 4, buffer + offset, 'i8*');
|
| 925 |
+
offset += encoderAdaptorLen;
|
| 926 |
+
|
| 927 |
+
Module.setValue(ptr + 1 * 4, buffer + offset, 'i8*');
|
| 928 |
+
offset += llmLen;
|
| 929 |
+
|
| 930 |
+
Module.setValue(ptr + 2 * 4, buffer + offset, 'i8*');
|
| 931 |
+
offset += embeddingLen;
|
| 932 |
+
|
| 933 |
+
Module.setValue(ptr + 3 * 4, buffer + offset, 'i8*');
|
| 934 |
+
offset += tokenizerLen;
|
| 935 |
+
|
| 936 |
+
Module.setValue(ptr + 4 * 4, buffer + offset, 'i8*');
|
| 937 |
+
offset += systemPromptLen;
|
| 938 |
+
|
| 939 |
+
Module.setValue(ptr + 5 * 4, buffer + offset, 'i8*');
|
| 940 |
+
offset += userPromptLen;
|
| 941 |
+
|
| 942 |
+
Module.setValue(ptr + 6 * 4, config.maxNewTokens || 512, 'i32');
|
| 943 |
+
Module.setValue(ptr + 7 * 4, config.temperature || 1e-6, 'float');
|
| 944 |
+
Module.setValue(ptr + 8 * 4, config.topP || 0.8, 'float');
|
| 945 |
+
Module.setValue(ptr + 9 * 4, config.seed || 42, 'i32');
|
| 946 |
+
Module.setValue(ptr + 10 * 4, buffer + offset, 'i8*');
|
| 947 |
+
offset += languageLen;
|
| 948 |
+
Module.setValue(ptr + 11 * 4, config.itn || 0, 'i32');
|
| 949 |
+
Module.setValue(ptr + 12 * 4, buffer + offset, 'i8*');
|
| 950 |
+
offset += hotwordsLen;
|
| 951 |
+
|
| 952 |
+
return {
|
| 953 |
+
buffer: buffer,
|
| 954 |
+
ptr: ptr,
|
| 955 |
+
len: len,
|
| 956 |
+
};
|
| 957 |
+
}
|
| 958 |
+
|
| 959 |
+
function initSherpaOnnxOfflineQwen3AsrModelConfig(config, Module) {
|
| 960 |
+
const convFrontendLen = Module.lengthBytesUTF8(config.convFrontend || '') + 1;
|
| 961 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 962 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 963 |
+
const tokenizerLen = Module.lengthBytesUTF8(config.tokenizer || '') + 1;
|
| 964 |
+
const hotwordsLen = Module.lengthBytesUTF8(config.hotwords || '') + 1;
|
| 965 |
+
|
| 966 |
+
const n = convFrontendLen + encoderLen + decoderLen + tokenizerLen +
|
| 967 |
+
hotwordsLen;
|
| 968 |
+
const buffer = Module._malloc(n);
|
| 969 |
+
|
| 970 |
+
const len = 10 * 4;
|
| 971 |
+
const ptr = Module._malloc(len);
|
| 972 |
+
|
| 973 |
+
let offset = 0;
|
| 974 |
+
Module.stringToUTF8(
|
| 975 |
+
config.convFrontend || '', buffer + offset, convFrontendLen);
|
| 976 |
+
offset += convFrontendLen;
|
| 977 |
+
|
| 978 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 979 |
+
offset += encoderLen;
|
| 980 |
+
|
| 981 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 982 |
+
offset += decoderLen;
|
| 983 |
+
|
| 984 |
+
Module.stringToUTF8(config.tokenizer || '', buffer + offset, tokenizerLen);
|
| 985 |
+
offset += tokenizerLen;
|
| 986 |
+
|
| 987 |
+
Module.stringToUTF8(config.hotwords || '', buffer + offset, hotwordsLen);
|
| 988 |
+
offset += hotwordsLen;
|
| 989 |
+
|
| 990 |
+
offset = 0;
|
| 991 |
+
Module.setValue(ptr + 0 * 4, buffer + offset, 'i8*');
|
| 992 |
+
offset += convFrontendLen;
|
| 993 |
+
|
| 994 |
+
Module.setValue(ptr + 1 * 4, buffer + offset, 'i8*');
|
| 995 |
+
offset += encoderLen;
|
| 996 |
+
|
| 997 |
+
Module.setValue(ptr + 2 * 4, buffer + offset, 'i8*');
|
| 998 |
+
offset += decoderLen;
|
| 999 |
+
|
| 1000 |
+
Module.setValue(ptr + 3 * 4, buffer + offset, 'i8*');
|
| 1001 |
+
offset += tokenizerLen;
|
| 1002 |
+
|
| 1003 |
+
Module.setValue(ptr + 4 * 4, config.maxTotalLen || 512, 'i32');
|
| 1004 |
+
Module.setValue(ptr + 5 * 4, config.maxNewTokens || 128, 'i32');
|
| 1005 |
+
Module.setValue(ptr + 6 * 4, config.temperature || 1e-6, 'float');
|
| 1006 |
+
Module.setValue(ptr + 7 * 4, config.topP || 0.8, 'float');
|
| 1007 |
+
Module.setValue(ptr + 8 * 4, config.seed || 42, 'i32');
|
| 1008 |
+
Module.setValue(ptr + 9 * 4, buffer + offset, 'i8*');
|
| 1009 |
+
offset += hotwordsLen;
|
| 1010 |
+
|
| 1011 |
+
return {
|
| 1012 |
+
buffer: buffer,
|
| 1013 |
+
ptr: ptr,
|
| 1014 |
+
len: len,
|
| 1015 |
+
};
|
| 1016 |
+
}
|
| 1017 |
+
|
| 1018 |
+
function initSherpaOnnxOfflineWhisperModelConfig(config, Module) {
|
| 1019 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 1020 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 1021 |
+
const languageLen = Module.lengthBytesUTF8(config.language || '') + 1;
|
| 1022 |
+
const taskLen = Module.lengthBytesUTF8(config.task || '') + 1;
|
| 1023 |
+
|
| 1024 |
+
const n = encoderLen + decoderLen + languageLen + taskLen;
|
| 1025 |
+
const buffer = Module._malloc(n);
|
| 1026 |
+
|
| 1027 |
+
const len = 7 * 4; // 4 pointers + 3 int32
|
| 1028 |
+
const ptr = Module._malloc(len);
|
| 1029 |
+
|
| 1030 |
+
let offset = 0;
|
| 1031 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 1032 |
+
offset += encoderLen;
|
| 1033 |
+
|
| 1034 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 1035 |
+
offset += decoderLen;
|
| 1036 |
+
|
| 1037 |
+
Module.stringToUTF8(config.language || '', buffer + offset, languageLen);
|
| 1038 |
+
offset += languageLen;
|
| 1039 |
+
|
| 1040 |
+
Module.stringToUTF8(config.task || '', buffer + offset, taskLen);
|
| 1041 |
+
|
| 1042 |
+
offset = 0;
|
| 1043 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 1044 |
+
offset += encoderLen;
|
| 1045 |
+
|
| 1046 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 1047 |
+
offset += decoderLen;
|
| 1048 |
+
|
| 1049 |
+
Module.setValue(ptr + 8, buffer + offset, 'i8*');
|
| 1050 |
+
offset += languageLen;
|
| 1051 |
+
|
| 1052 |
+
Module.setValue(ptr + 12, buffer + offset, 'i8*');
|
| 1053 |
+
offset += taskLen;
|
| 1054 |
+
|
| 1055 |
+
Module.setValue(ptr + 16, config.tailPaddings || 2000, 'i32');
|
| 1056 |
+
Module.setValue(ptr + 20, config.enableTokenTimestamps || 0, 'i32');
|
| 1057 |
+
Module.setValue(ptr + 24, config.enableSegmentTimestamps || 0, 'i32');
|
| 1058 |
+
|
| 1059 |
+
return {
|
| 1060 |
+
buffer: buffer,
|
| 1061 |
+
ptr: ptr,
|
| 1062 |
+
len: len,
|
| 1063 |
+
};
|
| 1064 |
+
}
|
| 1065 |
+
|
| 1066 |
+
function initSherpaOnnxOfflineCanaryModelConfig(config, Module) {
|
| 1067 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 1068 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 1069 |
+
const srcLangLen = Module.lengthBytesUTF8(config.srcLang || '') + 1;
|
| 1070 |
+
const tgtLangLen = Module.lengthBytesUTF8(config.tgtLang || '') + 1;
|
| 1071 |
+
|
| 1072 |
+
const n = encoderLen + decoderLen + srcLangLen + tgtLangLen;
|
| 1073 |
+
const buffer = Module._malloc(n);
|
| 1074 |
+
|
| 1075 |
+
const len = 5 * 4; // 4 pointers + 1 int32
|
| 1076 |
+
const ptr = Module._malloc(len);
|
| 1077 |
+
|
| 1078 |
+
let offset = 0;
|
| 1079 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 1080 |
+
offset += encoderLen;
|
| 1081 |
+
|
| 1082 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 1083 |
+
offset += decoderLen;
|
| 1084 |
+
|
| 1085 |
+
Module.stringToUTF8(config.srcLang || '', buffer + offset, srcLangLen);
|
| 1086 |
+
offset += srcLangLen;
|
| 1087 |
+
|
| 1088 |
+
Module.stringToUTF8(config.tgtLang || '', buffer + offset, tgtLangLen);
|
| 1089 |
+
offset += tgtLangLen;
|
| 1090 |
+
|
| 1091 |
+
offset = 0;
|
| 1092 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 1093 |
+
offset += encoderLen;
|
| 1094 |
+
|
| 1095 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 1096 |
+
offset += decoderLen;
|
| 1097 |
+
|
| 1098 |
+
Module.setValue(ptr + 8, buffer + offset, 'i8*');
|
| 1099 |
+
offset += srcLangLen;
|
| 1100 |
+
|
| 1101 |
+
Module.setValue(ptr + 12, buffer + offset, 'i8*');
|
| 1102 |
+
offset += tgtLangLen;
|
| 1103 |
+
|
| 1104 |
+
Module.setValue(ptr + 16, config.usePnc ?? 1, 'i32');
|
| 1105 |
+
|
| 1106 |
+
return {
|
| 1107 |
+
buffer: buffer,
|
| 1108 |
+
ptr: ptr,
|
| 1109 |
+
len: len,
|
| 1110 |
+
};
|
| 1111 |
+
}
|
| 1112 |
+
|
| 1113 |
+
function initSherpaOnnxOfflineMoonshineModelConfig(config, Module) {
|
| 1114 |
+
const preprocessorLen = Module.lengthBytesUTF8(config.preprocessor || '') + 1;
|
| 1115 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 1116 |
+
const uncachedDecoderLen =
|
| 1117 |
+
Module.lengthBytesUTF8(config.uncachedDecoder || '') + 1;
|
| 1118 |
+
const cachedDecoderLen =
|
| 1119 |
+
Module.lengthBytesUTF8(config.cachedDecoder || '') + 1;
|
| 1120 |
+
const mergedDecoderLen =
|
| 1121 |
+
Module.lengthBytesUTF8(config.mergedDecoder || '') + 1;
|
| 1122 |
+
|
| 1123 |
+
const n = preprocessorLen + encoderLen + uncachedDecoderLen +
|
| 1124 |
+
cachedDecoderLen + mergedDecoderLen;
|
| 1125 |
+
const buffer = Module._malloc(n);
|
| 1126 |
+
|
| 1127 |
+
const len = 5 * 4; // 5 pointers
|
| 1128 |
+
const ptr = Module._malloc(len);
|
| 1129 |
+
|
| 1130 |
+
let offset = 0;
|
| 1131 |
+
Module.stringToUTF8(
|
| 1132 |
+
config.preprocessor || '', buffer + offset, preprocessorLen);
|
| 1133 |
+
offset += preprocessorLen;
|
| 1134 |
+
|
| 1135 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 1136 |
+
offset += encoderLen;
|
| 1137 |
+
|
| 1138 |
+
Module.stringToUTF8(
|
| 1139 |
+
config.uncachedDecoder || '', buffer + offset, uncachedDecoderLen);
|
| 1140 |
+
offset += uncachedDecoderLen;
|
| 1141 |
+
|
| 1142 |
+
Module.stringToUTF8(
|
| 1143 |
+
config.cachedDecoder || '', buffer + offset, cachedDecoderLen);
|
| 1144 |
+
offset += cachedDecoderLen;
|
| 1145 |
+
|
| 1146 |
+
Module.stringToUTF8(
|
| 1147 |
+
config.mergedDecoder || '', buffer + offset, mergedDecoderLen);
|
| 1148 |
+
offset += mergedDecoderLen;
|
| 1149 |
+
|
| 1150 |
+
offset = 0;
|
| 1151 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 1152 |
+
offset += preprocessorLen;
|
| 1153 |
+
|
| 1154 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 1155 |
+
offset += encoderLen;
|
| 1156 |
+
|
| 1157 |
+
Module.setValue(ptr + 8, buffer + offset, 'i8*');
|
| 1158 |
+
offset += uncachedDecoderLen;
|
| 1159 |
+
|
| 1160 |
+
Module.setValue(ptr + 12, buffer + offset, 'i8*');
|
| 1161 |
+
offset += cachedDecoderLen;
|
| 1162 |
+
|
| 1163 |
+
Module.setValue(ptr + 16, buffer + offset, 'i8*');
|
| 1164 |
+
offset += mergedDecoderLen;
|
| 1165 |
+
|
| 1166 |
+
return {
|
| 1167 |
+
buffer: buffer,
|
| 1168 |
+
ptr: ptr,
|
| 1169 |
+
len: len,
|
| 1170 |
+
};
|
| 1171 |
+
}
|
| 1172 |
+
|
| 1173 |
+
function initSherpaOnnxOfflineFireRedAsrModelConfig(config, Module) {
|
| 1174 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 1175 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 1176 |
+
|
| 1177 |
+
const n = encoderLen + decoderLen;
|
| 1178 |
+
const buffer = Module._malloc(n);
|
| 1179 |
+
|
| 1180 |
+
const len = 2 * 4; // 2 pointers
|
| 1181 |
+
const ptr = Module._malloc(len);
|
| 1182 |
+
|
| 1183 |
+
let offset = 0;
|
| 1184 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 1185 |
+
offset += encoderLen;
|
| 1186 |
+
|
| 1187 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 1188 |
+
offset += decoderLen;
|
| 1189 |
+
|
| 1190 |
+
offset = 0;
|
| 1191 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 1192 |
+
offset += encoderLen;
|
| 1193 |
+
|
| 1194 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 1195 |
+
offset += decoderLen;
|
| 1196 |
+
|
| 1197 |
+
return {
|
| 1198 |
+
buffer: buffer,
|
| 1199 |
+
ptr: ptr,
|
| 1200 |
+
len: len,
|
| 1201 |
+
};
|
| 1202 |
+
}
|
| 1203 |
+
|
| 1204 |
+
function initSherpaOnnxOfflineTdnnModelConfig(config, Module) {
|
| 1205 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 1206 |
+
const buffer = Module._malloc(n);
|
| 1207 |
+
|
| 1208 |
+
const len = 1 * 4; // 1 pointer
|
| 1209 |
+
const ptr = Module._malloc(len);
|
| 1210 |
+
|
| 1211 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 1212 |
+
|
| 1213 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 1214 |
+
|
| 1215 |
+
return {
|
| 1216 |
+
buffer: buffer,
|
| 1217 |
+
ptr: ptr,
|
| 1218 |
+
len: len,
|
| 1219 |
+
};
|
| 1220 |
+
}
|
| 1221 |
+
|
| 1222 |
+
function initSherpaOnnxOfflineCohereTranscribeModelConfig(config, Module) {
|
| 1223 |
+
const encoderLen = Module.lengthBytesUTF8(config.encoder || '') + 1;
|
| 1224 |
+
const decoderLen = Module.lengthBytesUTF8(config.decoder || '') + 1;
|
| 1225 |
+
const languageLen = Module.lengthBytesUTF8(config.language || '') + 1;
|
| 1226 |
+
|
| 1227 |
+
const n = encoderLen + decoderLen + languageLen;
|
| 1228 |
+
const buffer = Module._malloc(n);
|
| 1229 |
+
|
| 1230 |
+
const len = 5 * 4; // 3 pointers + 2 ints
|
| 1231 |
+
const ptr = Module._malloc(len);
|
| 1232 |
+
|
| 1233 |
+
let offset = 0;
|
| 1234 |
+
Module.stringToUTF8(config.encoder || '', buffer + offset, encoderLen);
|
| 1235 |
+
offset += encoderLen;
|
| 1236 |
+
|
| 1237 |
+
Module.stringToUTF8(config.decoder || '', buffer + offset, decoderLen);
|
| 1238 |
+
offset += decoderLen;
|
| 1239 |
+
|
| 1240 |
+
Module.stringToUTF8(config.language || '', buffer + offset, languageLen);
|
| 1241 |
+
offset += languageLen;
|
| 1242 |
+
|
| 1243 |
+
offset = 0;
|
| 1244 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 1245 |
+
offset += encoderLen;
|
| 1246 |
+
|
| 1247 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 1248 |
+
offset += decoderLen;
|
| 1249 |
+
|
| 1250 |
+
Module.setValue(ptr + 8, buffer + offset, 'i8*');
|
| 1251 |
+
offset += languageLen;
|
| 1252 |
+
|
| 1253 |
+
Module.setValue(ptr + 12, config.usePunct ?? 1, 'i32');
|
| 1254 |
+
Module.setValue(ptr + 16, config.useItn ?? 1, 'i32');
|
| 1255 |
+
|
| 1256 |
+
return {
|
| 1257 |
+
buffer: buffer,
|
| 1258 |
+
ptr: ptr,
|
| 1259 |
+
len: len,
|
| 1260 |
+
};
|
| 1261 |
+
}
|
| 1262 |
+
|
| 1263 |
+
function initSherpaOnnxOfflineSenseVoiceModelConfig(config, Module) {
|
| 1264 |
+
const modelLen = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 1265 |
+
const languageLen = Module.lengthBytesUTF8(config.language || '') + 1;
|
| 1266 |
+
|
| 1267 |
+
// useItn is a integer with 4 bytes
|
| 1268 |
+
const n = modelLen + languageLen;
|
| 1269 |
+
const buffer = Module._malloc(n);
|
| 1270 |
+
|
| 1271 |
+
const len = 3 * 4; // 2 pointers + 1 int
|
| 1272 |
+
const ptr = Module._malloc(len);
|
| 1273 |
+
|
| 1274 |
+
let offset = 0;
|
| 1275 |
+
Module.stringToUTF8(config.model || '', buffer + offset, modelLen);
|
| 1276 |
+
offset += modelLen;
|
| 1277 |
+
|
| 1278 |
+
Module.stringToUTF8(config.language || '', buffer + offset, languageLen);
|
| 1279 |
+
offset += languageLen;
|
| 1280 |
+
|
| 1281 |
+
offset = 0;
|
| 1282 |
+
Module.setValue(ptr, buffer + offset, 'i8*');
|
| 1283 |
+
offset += modelLen;
|
| 1284 |
+
|
| 1285 |
+
Module.setValue(ptr + 4, buffer + offset, 'i8*');
|
| 1286 |
+
offset += languageLen;
|
| 1287 |
+
|
| 1288 |
+
Module.setValue(ptr + 8, config.useInverseTextNormalization ?? 0, 'i32');
|
| 1289 |
+
|
| 1290 |
+
return {
|
| 1291 |
+
buffer: buffer,
|
| 1292 |
+
ptr: ptr,
|
| 1293 |
+
len: len,
|
| 1294 |
+
};
|
| 1295 |
+
}
|
| 1296 |
+
|
| 1297 |
+
function initSherpaOnnxOfflineLMConfig(config, Module) {
|
| 1298 |
+
const n = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 1299 |
+
const buffer = Module._malloc(n);
|
| 1300 |
+
|
| 1301 |
+
const len = 2 * 4;
|
| 1302 |
+
const ptr = Module._malloc(len);
|
| 1303 |
+
|
| 1304 |
+
Module.stringToUTF8(config.model || '', buffer, n);
|
| 1305 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 1306 |
+
Module.setValue(ptr + 4, config.scale || 1, 'float');
|
| 1307 |
+
|
| 1308 |
+
return {
|
| 1309 |
+
buffer: buffer,
|
| 1310 |
+
ptr: ptr,
|
| 1311 |
+
len: len,
|
| 1312 |
+
};
|
| 1313 |
+
}
|
| 1314 |
+
|
| 1315 |
+
function initSherpaOnnxOfflineModelConfig(config, Module) {
|
| 1316 |
+
if (!('transducer' in config)) {
|
| 1317 |
+
config.transducer = {
|
| 1318 |
+
encoder: '',
|
| 1319 |
+
decoder: '',
|
| 1320 |
+
joiner: '',
|
| 1321 |
+
};
|
| 1322 |
+
}
|
| 1323 |
+
|
| 1324 |
+
if (!('paraformer' in config)) {
|
| 1325 |
+
config.paraformer = {
|
| 1326 |
+
model: '',
|
| 1327 |
+
};
|
| 1328 |
+
}
|
| 1329 |
+
|
| 1330 |
+
if (!('nemoCtc' in config)) {
|
| 1331 |
+
config.nemoCtc = {
|
| 1332 |
+
model: '',
|
| 1333 |
+
};
|
| 1334 |
+
}
|
| 1335 |
+
|
| 1336 |
+
if (!('dolphin' in config)) {
|
| 1337 |
+
config.dolphin = {
|
| 1338 |
+
model: '',
|
| 1339 |
+
};
|
| 1340 |
+
}
|
| 1341 |
+
|
| 1342 |
+
if (!('zipformerCtc' in config)) {
|
| 1343 |
+
config.zipformerCtc = {
|
| 1344 |
+
model: '',
|
| 1345 |
+
};
|
| 1346 |
+
}
|
| 1347 |
+
|
| 1348 |
+
if (!('wenetCtc' in config)) {
|
| 1349 |
+
config.wenetCtc = {
|
| 1350 |
+
model: '',
|
| 1351 |
+
};
|
| 1352 |
+
}
|
| 1353 |
+
|
| 1354 |
+
if (!('omnilingual' in config)) {
|
| 1355 |
+
config.omnilingual = {
|
| 1356 |
+
model: '',
|
| 1357 |
+
};
|
| 1358 |
+
}
|
| 1359 |
+
|
| 1360 |
+
if (!('medasr' in config)) {
|
| 1361 |
+
config.medasr = {
|
| 1362 |
+
model: '',
|
| 1363 |
+
};
|
| 1364 |
+
}
|
| 1365 |
+
|
| 1366 |
+
if (!('fireRedAsrCtc' in config)) {
|
| 1367 |
+
config.fireRedAsrCtc = {
|
| 1368 |
+
model: '',
|
| 1369 |
+
};
|
| 1370 |
+
}
|
| 1371 |
+
|
| 1372 |
+
if (!('qwen3Asr' in config)) {
|
| 1373 |
+
config.qwen3Asr = {
|
| 1374 |
+
convFrontend: '',
|
| 1375 |
+
encoder: '',
|
| 1376 |
+
decoder: '',
|
| 1377 |
+
tokenizer: '',
|
| 1378 |
+
maxTotalLen: 512,
|
| 1379 |
+
maxNewTokens: 128,
|
| 1380 |
+
temperature: 1e-6,
|
| 1381 |
+
topP: 0.8,
|
| 1382 |
+
seed: 42,
|
| 1383 |
+
hotwords: '',
|
| 1384 |
+
};
|
| 1385 |
+
}
|
| 1386 |
+
|
| 1387 |
+
if (!('cohereTranscribe' in config)) {
|
| 1388 |
+
config.cohereTranscribe = {
|
| 1389 |
+
encoder: '',
|
| 1390 |
+
decoder: '',
|
| 1391 |
+
language: '',
|
| 1392 |
+
usePunct: 1,
|
| 1393 |
+
useItn: 1,
|
| 1394 |
+
};
|
| 1395 |
+
}
|
| 1396 |
+
|
| 1397 |
+
if (!('funasrNano' in config)) {
|
| 1398 |
+
config.funasrNano = {
|
| 1399 |
+
encoderAdaptor: '',
|
| 1400 |
+
llm: '',
|
| 1401 |
+
embedding: '',
|
| 1402 |
+
tokenizer: '',
|
| 1403 |
+
systemPrompt: 'You are a helpful assistant.',
|
| 1404 |
+
userPrompt: '语音转写:',
|
| 1405 |
+
maxNewTokens: 512,
|
| 1406 |
+
temperature: 1e-6,
|
| 1407 |
+
topP: 0.8,
|
| 1408 |
+
seed: 42,
|
| 1409 |
+
language: '',
|
| 1410 |
+
itn: 0,
|
| 1411 |
+
hotwords: '',
|
| 1412 |
+
};
|
| 1413 |
+
}
|
| 1414 |
+
|
| 1415 |
+
if (!('whisper' in config)) {
|
| 1416 |
+
config.whisper = {
|
| 1417 |
+
encoder: '',
|
| 1418 |
+
decoder: '',
|
| 1419 |
+
language: '',
|
| 1420 |
+
task: '',
|
| 1421 |
+
tailPaddings: -1,
|
| 1422 |
+
enableTokenTimestamps: 0,
|
| 1423 |
+
enableSegmentTimestamps: 0,
|
| 1424 |
+
};
|
| 1425 |
+
}
|
| 1426 |
+
|
| 1427 |
+
if (!('moonshine' in config)) {
|
| 1428 |
+
config.moonshine = {
|
| 1429 |
+
preprocessor: '',
|
| 1430 |
+
encoder: '',
|
| 1431 |
+
uncachedDecoder: '',
|
| 1432 |
+
cachedDecoder: '',
|
| 1433 |
+
mergedDecoder: '',
|
| 1434 |
+
};
|
| 1435 |
+
}
|
| 1436 |
+
|
| 1437 |
+
if (!('fireRedAsr' in config)) {
|
| 1438 |
+
config.fireRedAsr = {
|
| 1439 |
+
encoder: '',
|
| 1440 |
+
decoder: '',
|
| 1441 |
+
};
|
| 1442 |
+
}
|
| 1443 |
+
|
| 1444 |
+
if (!('tdnn' in config)) {
|
| 1445 |
+
config.tdnn = {
|
| 1446 |
+
model: '',
|
| 1447 |
+
};
|
| 1448 |
+
}
|
| 1449 |
+
|
| 1450 |
+
if (!('senseVoice' in config)) {
|
| 1451 |
+
config.senseVoice = {
|
| 1452 |
+
model: '',
|
| 1453 |
+
language: '',
|
| 1454 |
+
useInverseTextNormalization: 0,
|
| 1455 |
+
};
|
| 1456 |
+
}
|
| 1457 |
+
|
| 1458 |
+
if (!('canary' in config)) {
|
| 1459 |
+
config.canary = {
|
| 1460 |
+
encoder: '',
|
| 1461 |
+
decoder: '',
|
| 1462 |
+
srcLang: '',
|
| 1463 |
+
tgtLang: '',
|
| 1464 |
+
usePnc: 1,
|
| 1465 |
+
};
|
| 1466 |
+
}
|
| 1467 |
+
|
| 1468 |
+
const transducer =
|
| 1469 |
+
initSherpaOnnxOfflineTransducerModelConfig(config.transducer, Module);
|
| 1470 |
+
|
| 1471 |
+
const paraformer =
|
| 1472 |
+
initSherpaOnnxOfflineParaformerModelConfig(config.paraformer, Module);
|
| 1473 |
+
|
| 1474 |
+
const nemoCtc =
|
| 1475 |
+
initSherpaOnnxOfflineNemoEncDecCtcModelConfig(config.nemoCtc, Module);
|
| 1476 |
+
|
| 1477 |
+
const whisper =
|
| 1478 |
+
initSherpaOnnxOfflineWhisperModelConfig(config.whisper, Module);
|
| 1479 |
+
|
| 1480 |
+
const tdnn = initSherpaOnnxOfflineTdnnModelConfig(config.tdnn, Module);
|
| 1481 |
+
|
| 1482 |
+
const senseVoice =
|
| 1483 |
+
initSherpaOnnxOfflineSenseVoiceModelConfig(config.senseVoice, Module);
|
| 1484 |
+
|
| 1485 |
+
const moonshine =
|
| 1486 |
+
initSherpaOnnxOfflineMoonshineModelConfig(config.moonshine, Module);
|
| 1487 |
+
|
| 1488 |
+
const fireRedAsr =
|
| 1489 |
+
initSherpaOnnxOfflineFireRedAsrModelConfig(config.fireRedAsr, Module);
|
| 1490 |
+
|
| 1491 |
+
const dolphin =
|
| 1492 |
+
initSherpaOnnxOfflineDolphinModelConfig(config.dolphin, Module);
|
| 1493 |
+
|
| 1494 |
+
const zipformerCtc =
|
| 1495 |
+
initSherpaOnnxOfflineZipformerCtcModelConfig(config.zipformerCtc, Module);
|
| 1496 |
+
|
| 1497 |
+
const canary = initSherpaOnnxOfflineCanaryModelConfig(config.canary, Module);
|
| 1498 |
+
|
| 1499 |
+
const wenetCtc =
|
| 1500 |
+
initSherpaOnnxOfflineWenetCtcModelConfig(config.wenetCtc, Module);
|
| 1501 |
+
|
| 1502 |
+
const omnilingual = initSherpaOnnxOfflineOmnilingualAsrCtcModelConfig(
|
| 1503 |
+
config.omnilingual, Module);
|
| 1504 |
+
|
| 1505 |
+
const medasr =
|
| 1506 |
+
initSherpaOnnxOfflineMedAsrCtcModelConfig(config.medasr, Module);
|
| 1507 |
+
|
| 1508 |
+
const funasrNano =
|
| 1509 |
+
initSherpaOnnxOfflineFunAsrNanoModelConfig(config.funasrNano, Module);
|
| 1510 |
+
|
| 1511 |
+
const fireRedAsrCtc = initSherpaOnnxOfflineFireRedAsrCtcModelConfig(
|
| 1512 |
+
config.fireRedAsrCtc, Module);
|
| 1513 |
+
|
| 1514 |
+
const qwen3Asr =
|
| 1515 |
+
initSherpaOnnxOfflineQwen3AsrModelConfig(config.qwen3Asr, Module);
|
| 1516 |
+
|
| 1517 |
+
const cohereTranscribe = initSherpaOnnxOfflineCohereTranscribeModelConfig(
|
| 1518 |
+
config.cohereTranscribe, Module);
|
| 1519 |
+
|
| 1520 |
+
const len = transducer.len + paraformer.len + nemoCtc.len + whisper.len +
|
| 1521 |
+
tdnn.len + 8 * 4 + senseVoice.len + moonshine.len + fireRedAsr.len +
|
| 1522 |
+
dolphin.len + zipformerCtc.len + canary.len + wenetCtc.len +
|
| 1523 |
+
omnilingual.len + medasr.len + funasrNano.len + fireRedAsrCtc.len +
|
| 1524 |
+
qwen3Asr.len + cohereTranscribe.len;
|
| 1525 |
+
|
| 1526 |
+
const ptr = Module._malloc(len);
|
| 1527 |
+
|
| 1528 |
+
let offset = 0;
|
| 1529 |
+
Module._CopyHeap(transducer.ptr, transducer.len, ptr + offset);
|
| 1530 |
+
offset += transducer.len;
|
| 1531 |
+
|
| 1532 |
+
Module._CopyHeap(paraformer.ptr, paraformer.len, ptr + offset);
|
| 1533 |
+
offset += paraformer.len;
|
| 1534 |
+
|
| 1535 |
+
Module._CopyHeap(nemoCtc.ptr, nemoCtc.len, ptr + offset);
|
| 1536 |
+
offset += nemoCtc.len;
|
| 1537 |
+
|
| 1538 |
+
Module._CopyHeap(whisper.ptr, whisper.len, ptr + offset);
|
| 1539 |
+
offset += whisper.len;
|
| 1540 |
+
|
| 1541 |
+
Module._CopyHeap(tdnn.ptr, tdnn.len, ptr + offset);
|
| 1542 |
+
offset += tdnn.len;
|
| 1543 |
+
|
| 1544 |
+
const tokensLen = Module.lengthBytesUTF8(config.tokens || '') + 1;
|
| 1545 |
+
const providerLen = Module.lengthBytesUTF8(config.provider || 'cpu') + 1;
|
| 1546 |
+
const modelTypeLen = Module.lengthBytesUTF8(config.modelType || '') + 1;
|
| 1547 |
+
const modelingUnitLen = Module.lengthBytesUTF8(config.modelingUnit || '') + 1;
|
| 1548 |
+
const bpeVocabLen = Module.lengthBytesUTF8(config.bpeVocab || '') + 1;
|
| 1549 |
+
const teleSpeechCtcLen =
|
| 1550 |
+
Module.lengthBytesUTF8(config.teleSpeechCtc || '') + 1;
|
| 1551 |
+
|
| 1552 |
+
const bufferLen = tokensLen + providerLen + modelTypeLen + modelingUnitLen +
|
| 1553 |
+
bpeVocabLen + teleSpeechCtcLen;
|
| 1554 |
+
|
| 1555 |
+
const buffer = Module._malloc(bufferLen);
|
| 1556 |
+
|
| 1557 |
+
offset = 0;
|
| 1558 |
+
Module.stringToUTF8(config.tokens, buffer, tokensLen);
|
| 1559 |
+
offset += tokensLen;
|
| 1560 |
+
|
| 1561 |
+
Module.stringToUTF8(config.provider || 'cpu', buffer + offset, providerLen);
|
| 1562 |
+
offset += providerLen;
|
| 1563 |
+
|
| 1564 |
+
Module.stringToUTF8(config.modelType || '', buffer + offset, modelTypeLen);
|
| 1565 |
+
offset += modelTypeLen;
|
| 1566 |
+
|
| 1567 |
+
Module.stringToUTF8(
|
| 1568 |
+
config.modelingUnit || '', buffer + offset, modelingUnitLen);
|
| 1569 |
+
offset += modelingUnitLen;
|
| 1570 |
+
|
| 1571 |
+
Module.stringToUTF8(config.bpeVocab || '', buffer + offset, bpeVocabLen);
|
| 1572 |
+
offset += bpeVocabLen;
|
| 1573 |
+
|
| 1574 |
+
Module.stringToUTF8(
|
| 1575 |
+
config.teleSpeechCtc || '', buffer + offset, teleSpeechCtcLen);
|
| 1576 |
+
offset += teleSpeechCtcLen;
|
| 1577 |
+
|
| 1578 |
+
offset =
|
| 1579 |
+
transducer.len + paraformer.len + nemoCtc.len + whisper.len + tdnn.len;
|
| 1580 |
+
Module.setValue(ptr + offset, buffer, 'i8*'); // tokens
|
| 1581 |
+
offset += 4;
|
| 1582 |
+
|
| 1583 |
+
Module.setValue(ptr + offset, config.numThreads || 1, 'i32');
|
| 1584 |
+
offset += 4;
|
| 1585 |
+
|
| 1586 |
+
Module.setValue(ptr + offset, config.debug ?? 1, 'i32');
|
| 1587 |
+
offset += 4;
|
| 1588 |
+
|
| 1589 |
+
Module.setValue(ptr + offset, buffer + tokensLen, 'i8*'); // provider
|
| 1590 |
+
offset += 4;
|
| 1591 |
+
|
| 1592 |
+
Module.setValue(
|
| 1593 |
+
ptr + offset, buffer + tokensLen + providerLen, 'i8*'); // modelType
|
| 1594 |
+
offset += 4;
|
| 1595 |
+
|
| 1596 |
+
Module.setValue(
|
| 1597 |
+
ptr + offset, buffer + tokensLen + providerLen + modelTypeLen,
|
| 1598 |
+
'i8*'); // modelingUnit
|
| 1599 |
+
offset += 4;
|
| 1600 |
+
|
| 1601 |
+
Module.setValue(
|
| 1602 |
+
ptr + offset,
|
| 1603 |
+
buffer + tokensLen + providerLen + modelTypeLen + modelingUnitLen,
|
| 1604 |
+
'i8*'); // bpeVocab
|
| 1605 |
+
offset += 4;
|
| 1606 |
+
|
| 1607 |
+
Module.setValue(
|
| 1608 |
+
ptr + offset,
|
| 1609 |
+
buffer + tokensLen + providerLen + modelTypeLen + modelingUnitLen +
|
| 1610 |
+
bpeVocabLen,
|
| 1611 |
+
'i8*'); // teleSpeechCtc
|
| 1612 |
+
offset += 4;
|
| 1613 |
+
|
| 1614 |
+
Module._CopyHeap(senseVoice.ptr, senseVoice.len, ptr + offset);
|
| 1615 |
+
offset += senseVoice.len;
|
| 1616 |
+
|
| 1617 |
+
Module._CopyHeap(moonshine.ptr, moonshine.len, ptr + offset);
|
| 1618 |
+
offset += moonshine.len;
|
| 1619 |
+
|
| 1620 |
+
Module._CopyHeap(fireRedAsr.ptr, fireRedAsr.len, ptr + offset);
|
| 1621 |
+
offset += fireRedAsr.len;
|
| 1622 |
+
|
| 1623 |
+
Module._CopyHeap(dolphin.ptr, dolphin.len, ptr + offset);
|
| 1624 |
+
offset += dolphin.len;
|
| 1625 |
+
|
| 1626 |
+
Module._CopyHeap(zipformerCtc.ptr, zipformerCtc.len, ptr + offset);
|
| 1627 |
+
offset += zipformerCtc.len;
|
| 1628 |
+
|
| 1629 |
+
Module._CopyHeap(canary.ptr, canary.len, ptr + offset);
|
| 1630 |
+
offset += canary.len;
|
| 1631 |
+
|
| 1632 |
+
Module._CopyHeap(wenetCtc.ptr, wenetCtc.len, ptr + offset);
|
| 1633 |
+
offset += wenetCtc.len;
|
| 1634 |
+
|
| 1635 |
+
Module._CopyHeap(omnilingual.ptr, omnilingual.len, ptr + offset);
|
| 1636 |
+
offset += omnilingual.len;
|
| 1637 |
+
|
| 1638 |
+
Module._CopyHeap(medasr.ptr, medasr.len, ptr + offset);
|
| 1639 |
+
offset += medasr.len;
|
| 1640 |
+
|
| 1641 |
+
Module._CopyHeap(funasrNano.ptr, funasrNano.len, ptr + offset);
|
| 1642 |
+
offset += funasrNano.len;
|
| 1643 |
+
|
| 1644 |
+
Module._CopyHeap(fireRedAsrCtc.ptr, fireRedAsrCtc.len, ptr + offset);
|
| 1645 |
+
offset += fireRedAsrCtc.len;
|
| 1646 |
+
|
| 1647 |
+
Module._CopyHeap(qwen3Asr.ptr, qwen3Asr.len, ptr + offset);
|
| 1648 |
+
offset += qwen3Asr.len;
|
| 1649 |
+
|
| 1650 |
+
Module._CopyHeap(cohereTranscribe.ptr, cohereTranscribe.len, ptr + offset);
|
| 1651 |
+
offset += cohereTranscribe.len;
|
| 1652 |
+
|
| 1653 |
+
return {
|
| 1654 |
+
buffer: buffer,
|
| 1655 |
+
ptr: ptr,
|
| 1656 |
+
len: len,
|
| 1657 |
+
transducer: transducer,
|
| 1658 |
+
paraformer: paraformer,
|
| 1659 |
+
nemoCtc: nemoCtc,
|
| 1660 |
+
whisper: whisper,
|
| 1661 |
+
tdnn: tdnn,
|
| 1662 |
+
senseVoice: senseVoice,
|
| 1663 |
+
moonshine: moonshine,
|
| 1664 |
+
fireRedAsr: fireRedAsr,
|
| 1665 |
+
dolphin: dolphin,
|
| 1666 |
+
zipformerCtc: zipformerCtc,
|
| 1667 |
+
canary: canary,
|
| 1668 |
+
wenetCtc: wenetCtc,
|
| 1669 |
+
omnilingual: omnilingual,
|
| 1670 |
+
medasr: medasr,
|
| 1671 |
+
funasrNano: funasrNano,
|
| 1672 |
+
fireRedAsrCtc: fireRedAsrCtc,
|
| 1673 |
+
qwen3Asr: qwen3Asr,
|
| 1674 |
+
cohereTranscribe: cohereTranscribe
|
| 1675 |
+
};
|
| 1676 |
+
}
|
| 1677 |
+
|
| 1678 |
+
function initSherpaOnnxOfflineRecognizerConfig(config, Module) {
|
| 1679 |
+
if (!('featConfig' in config)) {
|
| 1680 |
+
config.featConfig = {
|
| 1681 |
+
sampleRate: 16000,
|
| 1682 |
+
featureDim: 80,
|
| 1683 |
+
};
|
| 1684 |
+
}
|
| 1685 |
+
|
| 1686 |
+
if (!('lmConfig' in config)) {
|
| 1687 |
+
config.lmConfig = {
|
| 1688 |
+
model: '',
|
| 1689 |
+
scale: 1.0,
|
| 1690 |
+
};
|
| 1691 |
+
}
|
| 1692 |
+
|
| 1693 |
+
if (!('hr' in config)) {
|
| 1694 |
+
config.hr = {
|
| 1695 |
+
lexicon: '',
|
| 1696 |
+
ruleFsts: '',
|
| 1697 |
+
};
|
| 1698 |
+
}
|
| 1699 |
+
|
| 1700 |
+
const feat = initSherpaOnnxFeatureConfig(config.featConfig, Module);
|
| 1701 |
+
const model = initSherpaOnnxOfflineModelConfig(config.modelConfig, Module);
|
| 1702 |
+
const lm = initSherpaOnnxOfflineLMConfig(config.lmConfig, Module);
|
| 1703 |
+
const hr = initSherpaOnnxHomophoneReplacerConfig(config.hr, Module);
|
| 1704 |
+
|
| 1705 |
+
const len = feat.len + model.len + lm.len + 7 * 4 + hr.len;
|
| 1706 |
+
const ptr = Module._malloc(len);
|
| 1707 |
+
|
| 1708 |
+
let offset = 0;
|
| 1709 |
+
Module._CopyHeap(feat.ptr, feat.len, ptr + offset);
|
| 1710 |
+
offset += feat.len;
|
| 1711 |
+
|
| 1712 |
+
Module._CopyHeap(model.ptr, model.len, ptr + offset);
|
| 1713 |
+
offset += model.len;
|
| 1714 |
+
|
| 1715 |
+
Module._CopyHeap(lm.ptr, lm.len, ptr + offset);
|
| 1716 |
+
offset += lm.len;
|
| 1717 |
+
|
| 1718 |
+
const decodingMethodLen =
|
| 1719 |
+
Module.lengthBytesUTF8(config.decodingMethod || 'greedy_search') + 1;
|
| 1720 |
+
const hotwordsFileLen = Module.lengthBytesUTF8(config.hotwordsFile || '') + 1;
|
| 1721 |
+
const ruleFstsLen = Module.lengthBytesUTF8(config.ruleFsts || '') + 1;
|
| 1722 |
+
const ruleFarsLen = Module.lengthBytesUTF8(config.ruleFars || '') + 1;
|
| 1723 |
+
const bufferLen =
|
| 1724 |
+
decodingMethodLen + hotwordsFileLen + ruleFstsLen + ruleFarsLen;
|
| 1725 |
+
const buffer = Module._malloc(bufferLen);
|
| 1726 |
+
|
| 1727 |
+
offset = 0;
|
| 1728 |
+
Module.stringToUTF8(
|
| 1729 |
+
config.decodingMethod || 'greedy_search', buffer, decodingMethodLen);
|
| 1730 |
+
offset += decodingMethodLen;
|
| 1731 |
+
|
| 1732 |
+
Module.stringToUTF8(
|
| 1733 |
+
config.hotwordsFile || '', buffer + offset, hotwordsFileLen);
|
| 1734 |
+
offset += hotwordsFileLen;
|
| 1735 |
+
|
| 1736 |
+
Module.stringToUTF8(config.ruleFsts || '', buffer + offset, ruleFstsLen);
|
| 1737 |
+
offset += ruleFstsLen;
|
| 1738 |
+
|
| 1739 |
+
Module.stringToUTF8(config.ruleFars || '', buffer + offset, ruleFarsLen);
|
| 1740 |
+
offset += ruleFarsLen;
|
| 1741 |
+
|
| 1742 |
+
offset = feat.len + model.len + lm.len;
|
| 1743 |
+
|
| 1744 |
+
Module.setValue(ptr + offset, buffer, 'i8*'); // decoding method
|
| 1745 |
+
offset += 4;
|
| 1746 |
+
|
| 1747 |
+
Module.setValue(ptr + offset, config.maxActivePaths || 4, 'i32');
|
| 1748 |
+
offset += 4;
|
| 1749 |
+
|
| 1750 |
+
Module.setValue(ptr + offset, buffer + decodingMethodLen, 'i8*');
|
| 1751 |
+
offset += 4;
|
| 1752 |
+
|
| 1753 |
+
Module.setValue(ptr + offset, config.hotwordsScore || 1.5, 'float');
|
| 1754 |
+
offset += 4;
|
| 1755 |
+
|
| 1756 |
+
Module.setValue(
|
| 1757 |
+
ptr + offset, buffer + decodingMethodLen + hotwordsFileLen, 'i8*');
|
| 1758 |
+
offset += 4;
|
| 1759 |
+
|
| 1760 |
+
Module.setValue(
|
| 1761 |
+
ptr + offset, buffer + decodingMethodLen + hotwordsFileLen + ruleFstsLen,
|
| 1762 |
+
'i8*');
|
| 1763 |
+
offset += 4;
|
| 1764 |
+
|
| 1765 |
+
Module.setValue(ptr + offset, config.blankPenalty || 0, 'float');
|
| 1766 |
+
offset += 4;
|
| 1767 |
+
|
| 1768 |
+
Module._CopyHeap(hr.ptr, hr.len, ptr + offset);
|
| 1769 |
+
offset += hr.len;
|
| 1770 |
+
|
| 1771 |
+
return {
|
| 1772 |
+
buffer: buffer,
|
| 1773 |
+
ptr: ptr,
|
| 1774 |
+
len: len,
|
| 1775 |
+
feat: feat,
|
| 1776 |
+
model: model,
|
| 1777 |
+
lm: lm,
|
| 1778 |
+
hr: hr,
|
| 1779 |
+
};
|
| 1780 |
+
}
|
| 1781 |
+
|
| 1782 |
+
class OfflineStream {
|
| 1783 |
+
constructor(handle, Module) {
|
| 1784 |
+
this.handle = handle;
|
| 1785 |
+
this.Module = Module;
|
| 1786 |
+
}
|
| 1787 |
+
|
| 1788 |
+
free() {
|
| 1789 |
+
if (this.handle) {
|
| 1790 |
+
this.Module._SherpaOnnxDestroyOfflineStream(this.handle);
|
| 1791 |
+
this.handle = null;
|
| 1792 |
+
}
|
| 1793 |
+
}
|
| 1794 |
+
|
| 1795 |
+
/**
|
| 1796 |
+
* @param sampleRate {Number}
|
| 1797 |
+
* @param samples {Float32Array} Containing samples in the range [-1, 1]
|
| 1798 |
+
*/
|
| 1799 |
+
acceptWaveform(sampleRate, samples) {
|
| 1800 |
+
const pointer =
|
| 1801 |
+
this.Module._malloc(samples.length * samples.BYTES_PER_ELEMENT);
|
| 1802 |
+
this.Module.HEAPF32.set(samples, pointer / samples.BYTES_PER_ELEMENT);
|
| 1803 |
+
this.Module._SherpaOnnxAcceptWaveformOffline(
|
| 1804 |
+
this.handle, sampleRate, pointer, samples.length);
|
| 1805 |
+
this.Module._free(pointer);
|
| 1806 |
+
}
|
| 1807 |
+
|
| 1808 |
+
/**
|
| 1809 |
+
* @param key {String} The option name
|
| 1810 |
+
* @param value {String} The option value
|
| 1811 |
+
*/
|
| 1812 |
+
setOption(key, value) {
|
| 1813 |
+
const keyLen = this.Module.lengthBytesUTF8(key) + 1;
|
| 1814 |
+
const valueLen = this.Module.lengthBytesUTF8(value) + 1;
|
| 1815 |
+
const pKey = this.Module._malloc(keyLen);
|
| 1816 |
+
const pValue = this.Module._malloc(valueLen);
|
| 1817 |
+
this.Module.stringToUTF8(key, pKey, keyLen);
|
| 1818 |
+
this.Module.stringToUTF8(value, pValue, valueLen);
|
| 1819 |
+
this.Module._SherpaOnnxOfflineStreamSetOption(this.handle, pKey, pValue);
|
| 1820 |
+
this.Module._free(pKey);
|
| 1821 |
+
this.Module._free(pValue);
|
| 1822 |
+
}
|
| 1823 |
+
|
| 1824 |
+
/**
|
| 1825 |
+
* @param key {String} The option name
|
| 1826 |
+
* @returns {String} The option value, or empty string if not set
|
| 1827 |
+
*/
|
| 1828 |
+
getOption(key) {
|
| 1829 |
+
const keyLen = this.Module.lengthBytesUTF8(key) + 1;
|
| 1830 |
+
const pKey = this.Module._malloc(keyLen);
|
| 1831 |
+
this.Module.stringToUTF8(key, pKey, keyLen);
|
| 1832 |
+
const pValue =
|
| 1833 |
+
this.Module._SherpaOnnxOfflineStreamGetOption(this.handle, pKey);
|
| 1834 |
+
const value = this.Module.UTF8ToString(pValue);
|
| 1835 |
+
this.Module._free(pKey);
|
| 1836 |
+
return value;
|
| 1837 |
+
}
|
| 1838 |
+
};
|
| 1839 |
+
|
| 1840 |
+
class OfflineRecognizer {
|
| 1841 |
+
constructor(configObj, Module) {
|
| 1842 |
+
this.config = configObj;
|
| 1843 |
+
const config = initSherpaOnnxOfflineRecognizerConfig(configObj, Module);
|
| 1844 |
+
const handle = Module._SherpaOnnxCreateOfflineRecognizer(config.ptr);
|
| 1845 |
+
freeConfig(config, Module);
|
| 1846 |
+
|
| 1847 |
+
this.handle = handle;
|
| 1848 |
+
this.Module = Module;
|
| 1849 |
+
}
|
| 1850 |
+
|
| 1851 |
+
setConfig(configObj) {
|
| 1852 |
+
const config =
|
| 1853 |
+
initSherpaOnnxOfflineRecognizerConfig(configObj, this.Module);
|
| 1854 |
+
this.Module._SherpaOnnxOfflineRecognizerSetConfig(this.handle, config.ptr);
|
| 1855 |
+
freeConfig(config, this.Module);
|
| 1856 |
+
}
|
| 1857 |
+
|
| 1858 |
+
free() {
|
| 1859 |
+
this.Module._SherpaOnnxDestroyOfflineRecognizer(this.handle);
|
| 1860 |
+
this.handle = 0
|
| 1861 |
+
}
|
| 1862 |
+
|
| 1863 |
+
createStream() {
|
| 1864 |
+
const handle = this.Module._SherpaOnnxCreateOfflineStream(this.handle);
|
| 1865 |
+
return new OfflineStream(handle, this.Module);
|
| 1866 |
+
}
|
| 1867 |
+
|
| 1868 |
+
decode(stream) {
|
| 1869 |
+
this.Module._SherpaOnnxDecodeOfflineStream(this.handle, stream.handle);
|
| 1870 |
+
}
|
| 1871 |
+
|
| 1872 |
+
getResult(stream) {
|
| 1873 |
+
const r =
|
| 1874 |
+
this.Module._SherpaOnnxGetOfflineStreamResultAsJson(stream.handle);
|
| 1875 |
+
const jsonStr = this.Module.UTF8ToString(r);
|
| 1876 |
+
const ans = JSON.parse(jsonStr);
|
| 1877 |
+
this.Module._SherpaOnnxDestroyOfflineStreamResultJson(r);
|
| 1878 |
+
|
| 1879 |
+
return ans;
|
| 1880 |
+
}
|
| 1881 |
+
};
|
| 1882 |
+
|
| 1883 |
+
class OnlineStream {
|
| 1884 |
+
constructor(handle, Module) {
|
| 1885 |
+
this.handle = handle;
|
| 1886 |
+
this.pointer = null; // buffer
|
| 1887 |
+
this.n = 0; // buffer size
|
| 1888 |
+
this.Module = Module;
|
| 1889 |
+
}
|
| 1890 |
+
|
| 1891 |
+
free() {
|
| 1892 |
+
if (this.handle) {
|
| 1893 |
+
this.Module._SherpaOnnxDestroyOnlineStream(this.handle);
|
| 1894 |
+
this.handle = null;
|
| 1895 |
+
this.Module._free(this.pointer);
|
| 1896 |
+
this.pointer = null;
|
| 1897 |
+
this.n = 0;
|
| 1898 |
+
}
|
| 1899 |
+
}
|
| 1900 |
+
|
| 1901 |
+
/**
|
| 1902 |
+
* @param sampleRate {Number}
|
| 1903 |
+
* @param samples {Float32Array} Containing samples in the range [-1, 1]
|
| 1904 |
+
*/
|
| 1905 |
+
acceptWaveform(sampleRate, samples) {
|
| 1906 |
+
if (this.n < samples.length) {
|
| 1907 |
+
this.Module._free(this.pointer);
|
| 1908 |
+
this.pointer =
|
| 1909 |
+
this.Module._malloc(samples.length * samples.BYTES_PER_ELEMENT);
|
| 1910 |
+
this.n = samples.length
|
| 1911 |
+
}
|
| 1912 |
+
|
| 1913 |
+
this.Module.HEAPF32.set(samples, this.pointer / samples.BYTES_PER_ELEMENT);
|
| 1914 |
+
this.Module._SherpaOnnxOnlineStreamAcceptWaveform(
|
| 1915 |
+
this.handle, sampleRate, this.pointer, samples.length);
|
| 1916 |
+
}
|
| 1917 |
+
|
| 1918 |
+
inputFinished() {
|
| 1919 |
+
this.Module._SherpaOnnxOnlineStreamInputFinished(this.handle);
|
| 1920 |
+
}
|
| 1921 |
+
|
| 1922 |
+
/**
|
| 1923 |
+
* @param key {String} The option name
|
| 1924 |
+
* @param value {String} The option value
|
| 1925 |
+
*/
|
| 1926 |
+
setOption(key, value) {
|
| 1927 |
+
const keyLen = this.Module.lengthBytesUTF8(key) + 1;
|
| 1928 |
+
const valueLen = this.Module.lengthBytesUTF8(value) + 1;
|
| 1929 |
+
const pKey = this.Module._malloc(keyLen);
|
| 1930 |
+
const pValue = this.Module._malloc(valueLen);
|
| 1931 |
+
this.Module.stringToUTF8(key, pKey, keyLen);
|
| 1932 |
+
this.Module.stringToUTF8(value, pValue, valueLen);
|
| 1933 |
+
this.Module._SherpaOnnxOnlineStreamSetOption(this.handle, pKey, pValue);
|
| 1934 |
+
this.Module._free(pKey);
|
| 1935 |
+
this.Module._free(pValue);
|
| 1936 |
+
}
|
| 1937 |
+
|
| 1938 |
+
/**
|
| 1939 |
+
* @param key {String} The option name
|
| 1940 |
+
* @returns {String} The option value, or empty string if not set
|
| 1941 |
+
*/
|
| 1942 |
+
getOption(key) {
|
| 1943 |
+
const keyLen = this.Module.lengthBytesUTF8(key) + 1;
|
| 1944 |
+
const pKey = this.Module._malloc(keyLen);
|
| 1945 |
+
this.Module.stringToUTF8(key, pKey, keyLen);
|
| 1946 |
+
const pValue =
|
| 1947 |
+
this.Module._SherpaOnnxOnlineStreamGetOption(this.handle, pKey);
|
| 1948 |
+
const value = this.Module.UTF8ToString(pValue);
|
| 1949 |
+
this.Module._free(pKey);
|
| 1950 |
+
return value;
|
| 1951 |
+
}
|
| 1952 |
+
};
|
| 1953 |
+
|
| 1954 |
+
class OnlineRecognizer {
|
| 1955 |
+
constructor(configObj, Module) {
|
| 1956 |
+
this.config = configObj;
|
| 1957 |
+
const config = initSherpaOnnxOnlineRecognizerConfig(configObj, Module)
|
| 1958 |
+
const handle = Module._SherpaOnnxCreateOnlineRecognizer(config.ptr);
|
| 1959 |
+
|
| 1960 |
+
freeConfig(config, Module);
|
| 1961 |
+
|
| 1962 |
+
this.handle = handle;
|
| 1963 |
+
this.Module = Module;
|
| 1964 |
+
}
|
| 1965 |
+
|
| 1966 |
+
free() {
|
| 1967 |
+
this.Module._SherpaOnnxDestroyOnlineRecognizer(this.handle);
|
| 1968 |
+
this.handle = 0
|
| 1969 |
+
}
|
| 1970 |
+
|
| 1971 |
+
createStream() {
|
| 1972 |
+
const handle = this.Module._SherpaOnnxCreateOnlineStream(this.handle);
|
| 1973 |
+
return new OnlineStream(handle, this.Module);
|
| 1974 |
+
}
|
| 1975 |
+
|
| 1976 |
+
isReady(stream) {
|
| 1977 |
+
return this.Module._SherpaOnnxIsOnlineStreamReady(
|
| 1978 |
+
this.handle, stream.handle) == 1;
|
| 1979 |
+
}
|
| 1980 |
+
|
| 1981 |
+
decode(stream) {
|
| 1982 |
+
this.Module._SherpaOnnxDecodeOnlineStream(this.handle, stream.handle);
|
| 1983 |
+
}
|
| 1984 |
+
|
| 1985 |
+
isEndpoint(stream) {
|
| 1986 |
+
return this.Module._SherpaOnnxOnlineStreamIsEndpoint(
|
| 1987 |
+
this.handle, stream.handle) == 1;
|
| 1988 |
+
}
|
| 1989 |
+
|
| 1990 |
+
reset(stream) {
|
| 1991 |
+
this.Module._SherpaOnnxOnlineStreamReset(this.handle, stream.handle);
|
| 1992 |
+
}
|
| 1993 |
+
|
| 1994 |
+
getResult(stream) {
|
| 1995 |
+
const r = this.Module._SherpaOnnxGetOnlineStreamResultAsJson(
|
| 1996 |
+
this.handle, stream.handle);
|
| 1997 |
+
const jsonStr = this.Module.UTF8ToString(r);
|
| 1998 |
+
const ans = JSON.parse(jsonStr);
|
| 1999 |
+
this.Module._SherpaOnnxDestroyOnlineStreamResultJson(r);
|
| 2000 |
+
|
| 2001 |
+
return ans;
|
| 2002 |
+
}
|
| 2003 |
+
}
|
| 2004 |
+
|
| 2005 |
+
if (typeof process == 'object' && typeof process.versions == 'object' &&
|
| 2006 |
+
typeof process.versions.node == 'string') {
|
| 2007 |
+
module.exports = {
|
| 2008 |
+
createOnlineRecognizer,
|
| 2009 |
+
OfflineRecognizer,
|
| 2010 |
+
};
|
| 2011 |
+
}
|
sherpa-onnx-vad.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
function freeConfig(config, Module) {
|
| 2 |
+
if ('buffer' in config) {
|
| 3 |
+
Module._free(config.buffer);
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
if ('sileroVad' in config) {
|
| 7 |
+
freeConfig(config.sileroVad, Module)
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
if ('tenVad' in config) {
|
| 11 |
+
freeConfig(config.tenVad, Module)
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
Module._free(config.ptr);
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
// The user should free the returned pointers
|
| 19 |
+
function initSherpaOnnxSileroVadModelConfig(config, Module) {
|
| 20 |
+
const modelLen = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 21 |
+
|
| 22 |
+
const n = modelLen;
|
| 23 |
+
|
| 24 |
+
const buffer = Module._malloc(n);
|
| 25 |
+
|
| 26 |
+
const len = 6 * 4;
|
| 27 |
+
const ptr = Module._malloc(len);
|
| 28 |
+
|
| 29 |
+
Module.stringToUTF8(config.model || '', buffer, modelLen);
|
| 30 |
+
|
| 31 |
+
let offset = 0;
|
| 32 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 33 |
+
offset += 4;
|
| 34 |
+
|
| 35 |
+
Module.setValue(ptr + offset, config.threshold || 0.5, 'float');
|
| 36 |
+
offset += 4;
|
| 37 |
+
|
| 38 |
+
Module.setValue(ptr + offset, config.minSilenceDuration || 0.5, 'float');
|
| 39 |
+
offset += 4;
|
| 40 |
+
|
| 41 |
+
Module.setValue(ptr + offset, config.minSpeechDuration || 0.25, 'float');
|
| 42 |
+
offset += 4;
|
| 43 |
+
|
| 44 |
+
Module.setValue(ptr + offset, config.windowSize || 512, 'i32');
|
| 45 |
+
offset += 4;
|
| 46 |
+
|
| 47 |
+
Module.setValue(ptr + offset, config.maxSpeechDuration || 20, 'float');
|
| 48 |
+
offset += 4;
|
| 49 |
+
|
| 50 |
+
return {
|
| 51 |
+
buffer: buffer,
|
| 52 |
+
ptr: ptr,
|
| 53 |
+
len: len,
|
| 54 |
+
};
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
function initSherpaOnnxTenVadModelConfig(config, Module) {
|
| 58 |
+
const modelLen = Module.lengthBytesUTF8(config.model || '') + 1;
|
| 59 |
+
|
| 60 |
+
const n = modelLen;
|
| 61 |
+
|
| 62 |
+
const buffer = Module._malloc(n);
|
| 63 |
+
|
| 64 |
+
const len = 6 * 4;
|
| 65 |
+
const ptr = Module._malloc(len);
|
| 66 |
+
|
| 67 |
+
Module.stringToUTF8(config.model || '', buffer, modelLen);
|
| 68 |
+
|
| 69 |
+
let offset = 0;
|
| 70 |
+
Module.setValue(ptr, buffer, 'i8*');
|
| 71 |
+
offset += 4;
|
| 72 |
+
|
| 73 |
+
Module.setValue(ptr + offset, config.threshold || 0.5, 'float');
|
| 74 |
+
offset += 4;
|
| 75 |
+
|
| 76 |
+
Module.setValue(ptr + offset, config.minSilenceDuration || 0.5, 'float');
|
| 77 |
+
offset += 4;
|
| 78 |
+
|
| 79 |
+
Module.setValue(ptr + offset, config.minSpeechDuration || 0.25, 'float');
|
| 80 |
+
offset += 4;
|
| 81 |
+
|
| 82 |
+
Module.setValue(ptr + offset, config.windowSize || 256, 'i32');
|
| 83 |
+
offset += 4;
|
| 84 |
+
|
| 85 |
+
Module.setValue(ptr + offset, config.maxSpeechDuration || 20, 'float');
|
| 86 |
+
offset += 4;
|
| 87 |
+
|
| 88 |
+
return {
|
| 89 |
+
buffer: buffer,
|
| 90 |
+
ptr: ptr,
|
| 91 |
+
len: len,
|
| 92 |
+
};
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
function initSherpaOnnxVadModelConfig(config, Module) {
|
| 96 |
+
if (!('sileroVad' in config)) {
|
| 97 |
+
config.sileroVad = {
|
| 98 |
+
model: '',
|
| 99 |
+
threshold: 0.50,
|
| 100 |
+
minSilenceDuration: 0.50,
|
| 101 |
+
minSpeechDuration: 0.25,
|
| 102 |
+
windowSize: 512,
|
| 103 |
+
maxSpeechDuration: 20,
|
| 104 |
+
};
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
if (!('tenVad' in config)) {
|
| 108 |
+
config.tenVad = {
|
| 109 |
+
model: '',
|
| 110 |
+
threshold: 0.50,
|
| 111 |
+
minSilenceDuration: 0.50,
|
| 112 |
+
minSpeechDuration: 0.25,
|
| 113 |
+
windowSize: 256,
|
| 114 |
+
maxSpeechDuration: 20,
|
| 115 |
+
};
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
const sileroVad =
|
| 119 |
+
initSherpaOnnxSileroVadModelConfig(config.sileroVad, Module);
|
| 120 |
+
|
| 121 |
+
const tenVad = initSherpaOnnxTenVadModelConfig(config.tenVad, Module);
|
| 122 |
+
|
| 123 |
+
const len = sileroVad.len + 4 * 4 + tenVad.len;
|
| 124 |
+
const ptr = Module._malloc(len);
|
| 125 |
+
|
| 126 |
+
const providerLen = Module.lengthBytesUTF8(config.provider || 'cpu') + 1;
|
| 127 |
+
const buffer = Module._malloc(providerLen);
|
| 128 |
+
Module.stringToUTF8(config.provider || 'cpu', buffer, providerLen);
|
| 129 |
+
|
| 130 |
+
let offset = 0;
|
| 131 |
+
Module._CopyHeap(sileroVad.ptr, sileroVad.len, ptr + offset);
|
| 132 |
+
offset += sileroVad.len;
|
| 133 |
+
|
| 134 |
+
Module.setValue(ptr + offset, config.sampleRate || 16000, 'i32');
|
| 135 |
+
offset += 4;
|
| 136 |
+
|
| 137 |
+
Module.setValue(ptr + offset, config.numThreads || 1, 'i32');
|
| 138 |
+
offset += 4;
|
| 139 |
+
|
| 140 |
+
Module.setValue(ptr + offset, buffer, 'i8*'); // provider
|
| 141 |
+
offset += 4;
|
| 142 |
+
|
| 143 |
+
Module.setValue(ptr + offset, config.debug || 0, 'i32');
|
| 144 |
+
offset += 4;
|
| 145 |
+
|
| 146 |
+
Module._CopyHeap(tenVad.ptr, tenVad.len, ptr + offset);
|
| 147 |
+
offset += tenVad.len;
|
| 148 |
+
|
| 149 |
+
return {
|
| 150 |
+
buffer: buffer,
|
| 151 |
+
ptr: ptr,
|
| 152 |
+
len: len,
|
| 153 |
+
sileroVad: sileroVad,
|
| 154 |
+
tenVad: tenVad
|
| 155 |
+
};
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
function createVad(Module, myConfig) {
|
| 159 |
+
const sileroVad = {
|
| 160 |
+
model: './silero_vad.onnx',
|
| 161 |
+
threshold: 0.50,
|
| 162 |
+
minSilenceDuration: 0.50,
|
| 163 |
+
minSpeechDuration: 0.25,
|
| 164 |
+
maxSpeechDuration: 20,
|
| 165 |
+
windowSize: 512,
|
| 166 |
+
};
|
| 167 |
+
|
| 168 |
+
const tenVad = {
|
| 169 |
+
model: '',
|
| 170 |
+
threshold: 0.50,
|
| 171 |
+
minSilenceDuration: 0.50,
|
| 172 |
+
minSpeechDuration: 0.25,
|
| 173 |
+
maxSpeechDuration: 20,
|
| 174 |
+
windowSize: 256,
|
| 175 |
+
};
|
| 176 |
+
|
| 177 |
+
let config = {
|
| 178 |
+
sileroVad: sileroVad,
|
| 179 |
+
tenVad: tenVad,
|
| 180 |
+
sampleRate: 16000,
|
| 181 |
+
numThreads: 1,
|
| 182 |
+
provider: 'cpu',
|
| 183 |
+
debug: 1,
|
| 184 |
+
bufferSizeInSeconds: 30,
|
| 185 |
+
};
|
| 186 |
+
|
| 187 |
+
if (myConfig) {
|
| 188 |
+
config = myConfig;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
return new Vad(config, Module);
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
class CircularBuffer {
|
| 196 |
+
constructor(capacity, Module) {
|
| 197 |
+
this.handle = Module._SherpaOnnxCreateCircularBuffer(capacity);
|
| 198 |
+
this.Module = Module;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
free() {
|
| 202 |
+
this.Module._SherpaOnnxDestroyCircularBuffer(this.handle);
|
| 203 |
+
this.handle = 0
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
/**
|
| 207 |
+
* @param samples {Float32Array}
|
| 208 |
+
*/
|
| 209 |
+
push(samples) {
|
| 210 |
+
const pointer =
|
| 211 |
+
this.Module._malloc(samples.length * samples.BYTES_PER_ELEMENT);
|
| 212 |
+
this.Module.HEAPF32.set(samples, pointer / samples.BYTES_PER_ELEMENT);
|
| 213 |
+
this.Module._SherpaOnnxCircularBufferPush(
|
| 214 |
+
this.handle, pointer, samples.length);
|
| 215 |
+
this.Module._free(pointer);
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
get(startIndex, n) {
|
| 219 |
+
const p =
|
| 220 |
+
this.Module._SherpaOnnxCircularBufferGet(this.handle, startIndex, n);
|
| 221 |
+
|
| 222 |
+
const samplesPtr = p / 4;
|
| 223 |
+
const samples = new Float32Array(n);
|
| 224 |
+
for (let i = 0; i < n; i++) {
|
| 225 |
+
samples[i] = this.Module.HEAPF32[samplesPtr + i];
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
this.Module._SherpaOnnxCircularBufferFree(p);
|
| 229 |
+
|
| 230 |
+
return samples;
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
pop(n) {
|
| 234 |
+
this.Module._SherpaOnnxCircularBufferPop(this.handle, n);
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
size() {
|
| 238 |
+
return this.Module._SherpaOnnxCircularBufferSize(this.handle);
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
head() {
|
| 242 |
+
return this.Module._SherpaOnnxCircularBufferHead(this.handle);
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
reset() {
|
| 246 |
+
this.Module._SherpaOnnxCircularBufferReset(this.handle);
|
| 247 |
+
}
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
class Vad {
|
| 251 |
+
constructor(configObj, Module) {
|
| 252 |
+
this.config = configObj;
|
| 253 |
+
const config = initSherpaOnnxVadModelConfig(configObj, Module);
|
| 254 |
+
const handle = Module._SherpaOnnxCreateVoiceActivityDetector(
|
| 255 |
+
config.ptr, configObj.bufferSizeInSeconds || 30);
|
| 256 |
+
freeConfig(config, Module);
|
| 257 |
+
|
| 258 |
+
this.handle = handle;
|
| 259 |
+
this.Module = Module;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
free() {
|
| 263 |
+
this.Module._SherpaOnnxDestroyVoiceActivityDetector(this.handle);
|
| 264 |
+
this.handle = 0
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
// samples is a float32 array
|
| 268 |
+
acceptWaveform(samples) {
|
| 269 |
+
const pointer =
|
| 270 |
+
this.Module._malloc(samples.length * samples.BYTES_PER_ELEMENT);
|
| 271 |
+
this.Module.HEAPF32.set(samples, pointer / samples.BYTES_PER_ELEMENT);
|
| 272 |
+
this.Module._SherpaOnnxVoiceActivityDetectorAcceptWaveform(
|
| 273 |
+
this.handle, pointer, samples.length);
|
| 274 |
+
this.Module._free(pointer);
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
isEmpty() {
|
| 278 |
+
return this.Module._SherpaOnnxVoiceActivityDetectorEmpty(this.handle) == 1;
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
+
isDetected() {
|
| 282 |
+
return this.Module._SherpaOnnxVoiceActivityDetectorDetected(this.handle) ==
|
| 283 |
+
1;
|
| 284 |
+
}
|
| 285 |
+
|
| 286 |
+
pop() {
|
| 287 |
+
this.Module._SherpaOnnxVoiceActivityDetectorPop(this.handle);
|
| 288 |
+
}
|
| 289 |
+
|
| 290 |
+
clear() {
|
| 291 |
+
this.Module._SherpaOnnxVoiceActivityDetectorClear(this.handle);
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
/*
|
| 295 |
+
{
|
| 296 |
+
samples: a 1-d float32 array,
|
| 297 |
+
start: an int32
|
| 298 |
+
}
|
| 299 |
+
*/
|
| 300 |
+
front() {
|
| 301 |
+
const h = this.Module._SherpaOnnxVoiceActivityDetectorFront(this.handle);
|
| 302 |
+
|
| 303 |
+
const start = this.Module.HEAP32[h / 4];
|
| 304 |
+
const samplesPtr = this.Module.HEAP32[h / 4 + 1] / 4;
|
| 305 |
+
const numSamples = this.Module.HEAP32[h / 4 + 2];
|
| 306 |
+
|
| 307 |
+
const samples = new Float32Array(numSamples);
|
| 308 |
+
for (let i = 0; i < numSamples; i++) {
|
| 309 |
+
samples[i] = this.Module.HEAPF32[samplesPtr + i];
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
this.Module._SherpaOnnxDestroySpeechSegment(h);
|
| 313 |
+
return {samples: samples, start: start};
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
reset() {
|
| 317 |
+
this.Module._SherpaOnnxVoiceActivityDetectorReset(this.handle);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
flush() {
|
| 321 |
+
this.Module._SherpaOnnxVoiceActivityDetectorFlush(this.handle);
|
| 322 |
+
}
|
| 323 |
+
};
|
| 324 |
+
|
| 325 |
+
if (typeof process == 'object' && typeof process.versions == 'object' &&
|
| 326 |
+
typeof process.versions.node == 'string') {
|
| 327 |
+
module.exports = {
|
| 328 |
+
createVad,
|
| 329 |
+
CircularBuffer,
|
| 330 |
+
};
|
| 331 |
+
}
|
sherpa-onnx-wasm-main-vad-asr.data
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
loaded dynamically by Ekko
|
| 2 |
+
loaded dynamically by Ekko
|
| 3 |
+
loaded dynamically by Ekko
|
| 4 |
+
loaded dynamically by Ekko
|
| 5 |
+
loaded dynamically by Ekko
|
sherpa-onnx-wasm-main-vad-asr.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
var Module=typeof Module!="undefined"?Module:{};var ENVIRONMENT_IS_WEB=!!globalThis.window;var ENVIRONMENT_IS_WORKER=!!globalThis.WorkerGlobalScope;var ENVIRONMENT_IS_NODE=globalThis.process?.versions?.node&&globalThis.process?.type!="renderer";if(!Module["expectedDataFileDownloads"])Module["expectedDataFileDownloads"]=0;Module["expectedDataFileDownloads"]++;(()=>{var isPthread=typeof ENVIRONMENT_IS_PTHREAD!="undefined"&&ENVIRONMENT_IS_PTHREAD;var isWasmWorker=typeof ENVIRONMENT_IS_WASM_WORKER!="undefined"&&ENVIRONMENT_IS_WASM_WORKER;if(isPthread||isWasmWorker)return;var isNode=globalThis.process&&globalThis.process.versions&&globalThis.process.versions.node&&globalThis.process.type!="renderer";async function loadPackage(metadata){var PACKAGE_PATH="";if(typeof window==="object"){PACKAGE_PATH=window["encodeURIComponent"](window.location.pathname.substring(0,window.location.pathname.lastIndexOf("/"))+"/")}else if(typeof process==="undefined"&&typeof location!=="undefined"){PACKAGE_PATH=encodeURIComponent(location.pathname.substring(0,location.pathname.lastIndexOf("/"))+"/")}var PACKAGE_NAME="../../bin/sherpa-onnx-wasm-main-vad-asr.data";var REMOTE_PACKAGE_BASE="sherpa-onnx-wasm-main-vad-asr.data";var REMOTE_PACKAGE_NAME=Module["locateFile"]?Module["locateFile"](REMOTE_PACKAGE_BASE,""):REMOTE_PACKAGE_BASE;var REMOTE_PACKAGE_SIZE=metadata["remote_package_size"];async function fetchRemotePackage(packageName,packageSize){if(isNode){var contents=require("fs").readFileSync(packageName);return new Uint8Array(contents).buffer}if(!Module["dataFileDownloads"])Module["dataFileDownloads"]={};try{var response=await fetch(packageName)}catch(e){throw new Error(`Network Error: ${packageName}`,{e})}if(!response.ok){throw new Error(`${response.status}: ${response.url}`)}const chunks=[];const headers=response.headers;const total=Number(headers.get("Content-Length")||packageSize);let loaded=0;Module["setStatus"]&&Module["setStatus"]("Downloading data...");const reader=response.body.getReader();while(1){var{done,value}=await reader.read();if(done)break;chunks.push(value);loaded+=value.length;Module["dataFileDownloads"][packageName]={loaded,total};let totalLoaded=0;let totalSize=0;for(const download of Object.values(Module["dataFileDownloads"])){totalLoaded+=download.loaded;totalSize+=download.total}Module["setStatus"]&&Module["setStatus"](`Downloading data... (${totalLoaded}/${totalSize})`)}const packageData=new Uint8Array(chunks.map(c=>c.length).reduce((a,b)=>a+b,0));let offset=0;for(const chunk of chunks){packageData.set(chunk,offset);offset+=chunk.length}return packageData.buffer}var fetchPromise;var fetched=Module["getPreloadedPackage"]&&Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE);if(!fetched){fetchPromise=fetchRemotePackage(REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE)}async function runWithFS(Module){function assert(check,msg){if(!check)throw new Error(msg)}for(var file of metadata["files"]){var name=file["filename"];Module["addRunDependency"](`fp ${name}`)}async function processPackageData(arrayBuffer){assert(arrayBuffer,"Loading data file failed.");assert(arrayBuffer.constructor.name===ArrayBuffer.name,"bad input to processPackageData "+arrayBuffer.constructor.name);var byteArray=new Uint8Array(arrayBuffer);for(var file of metadata["files"]){var name=file["filename"];var data=byteArray.subarray(file["start"],file["end"]);Module["FS_createDataFile"](name,null,data,true,true,true);Module["removeRunDependency"](`fp ${name}`)}Module["removeRunDependency"]("datafile_../../bin/sherpa-onnx-wasm-main-vad-asr.data")}Module["addRunDependency"]("datafile_../../bin/sherpa-onnx-wasm-main-vad-asr.data");if(!Module["preloadResults"])Module["preloadResults"]={};Module["preloadResults"][PACKAGE_NAME]={fromCache:false};if(!fetched){fetched=await fetchPromise}processPackageData(fetched)}if(Module["calledRun"]){runWithFS(Module)}else{if(!Module["preRun"])Module["preRun"]=[];Module["preRun"].push(runWithFS)}}loadPackage({files:[{filename:"/nemo-transducer-decoder.onnx",start:0,end:27},{filename:"/nemo-transducer-encoder.onnx",start:27,end:54},{filename:"/nemo-transducer-joiner.onnx",start:54,end:81},{filename:"/silero_vad.onnx",start:81,end:108},{filename:"/tokens.txt",start:108,end:135}],remote_package_size:135})})();var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var _scriptName=globalThis.document?.currentScript?.src;if(typeof __filename!="undefined"){_scriptName=__filename}else if(ENVIRONMENT_IS_WORKER){_scriptName=self.location.href}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename);return ret};readAsync=async(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):filename;var ret=fs.readFileSync(filename,binary?undefined:"utf8");return ret};if(process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){try{scriptDirectory=new URL(".",_scriptName).href}catch{}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=async url=>{if(isFileURI(url)){return new Promise((resolve,reject)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response);return}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}var response=await fetch(url,{credentials:"same-origin"});if(response.ok){return response.arrayBuffer()}throw new Error(response.status+" : "+response.url)}}}else{}var out=console.log.bind(console);var err=console.error.bind(console);var wasmBinary;var ABORT=false;var EXITSTATUS;var isFileURI=filename=>filename.startsWith("file://");var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;var HEAP64,HEAPU64;var runtimeInitialized=false;function updateMemoryViews(){var b=wasmMemory.buffer;HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b);HEAP64=new BigInt64Array(b);HEAPU64=new BigUint64Array(b)}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(onPreRuns)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.initialized)FS.init();TTY.init();wasmExports["P"]();FS.ignorePermissions=false}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(onPostRuns)}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var wasmBinaryFile;function findWasmBinary(){return locateFile("sherpa-onnx-wasm-main-vad-asr.wasm")}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}async function getWasmBinary(binaryFile){if(!wasmBinary){try{var response=await readAsync(binaryFile);return new Uint8Array(response)}catch{}}return getBinarySync(binaryFile)}async function instantiateArrayBuffer(binaryFile,imports){try{var binary=await getWasmBinary(binaryFile);var instance=await WebAssembly.instantiate(binary,imports);return instance}catch(reason){err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)}}async function instantiateAsync(binary,binaryFile,imports){if(!binary&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE){try{var response=fetch(binaryFile,{credentials:"same-origin"});var instantiationResult=await WebAssembly.instantiateStreaming(response,imports);return instantiationResult}catch(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation")}}return instantiateArrayBuffer(binaryFile,imports)}function getWasmImports(){var imports={a:wasmImports};return imports}async function createWasm(){function receiveInstance(instance,module){wasmExports=instance.exports;assignWasmExports(wasmExports);updateMemoryViews();removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){return receiveInstance(result["instance"])}var info=getWasmImports();if(Module["instantiateWasm"]){return new Promise((resolve,reject)=>{Module["instantiateWasm"](info,(inst,mod)=>{resolve(receiveInstance(inst,mod))})})}wasmBinaryFile??=findWasmBinary();var result=await instantiateAsync(wasmBinary,wasmBinaryFile,info);var exports=receiveInstantiationResult(result);return exports}class ExitStatus{name="ExitStatus";constructor(status){this.message=`Program terminated with exit(${status})`;this.status=status}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var onPostRuns=[];var addOnPostRun=cb=>onPostRuns.push(cb);var onPreRuns=[];var addOnPreRun=cb=>onPreRuns.push(cb);var runDependencies=0;var dependenciesFulfilled=null;var removeRunDependency=id=>{runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}};var addRunDependency=id=>{runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)};function getValue(ptr,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":return HEAP8[ptr];case"i8":return HEAP8[ptr];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":return HEAP64[ptr>>3];case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];case"*":return HEAPU32[ptr>>2];default:abort(`invalid type for getValue: ${type}`)}}var noExitRuntime=true;function setValue(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":HEAP8[ptr]=value;break;case"i8":HEAP8[ptr]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":HEAP64[ptr>>3]=BigInt(value);break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;case"*":HEAPU32[ptr>>2]=value;break;default:abort(`invalid type for setValue: ${type}`)}}var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}}var exceptionLast=0;var uncaughtExceptionCount=0;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var syscallGetVarargI=()=>{var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret};var syscallGetVarargP=syscallGetVarargI;var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.slice(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.slice(0,-1)}return root+dir},basename:path=>path&&path.match(/([^\/]+|\/)\/*$/)[1],join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(ENVIRONMENT_IS_NODE){var nodeCrypto=require("crypto");return view=>nodeCrypto.randomFillSync(view)}return view=>crypto.getRandomValues(view)};var randomFill=view=>{(randomFill=initRandomFill())(view)};var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).slice(1);to=PATH_FS.resolve(to).slice(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")}};var UTF8Decoder=globalThis.TextDecoder&&new TextDecoder;var findStringEnd=(heapOrArray,idx,maxBytesToRead,ignoreNul)=>{var maxIdx=idx+maxBytesToRead;if(ignoreNul)return maxIdx;while(heapOrArray[idx]&&!(idx>=maxIdx))++idx;return idx};var UTF8ArrayToString=(heapOrArray,idx=0,maxBytesToRead,ignoreNul)=>{var endPtr=findStringEnd(heapOrArray,idx,maxBytesToRead,ignoreNul);if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.codePointAt(i);if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;i++}}heap[outIdx]=0;return outIdx-startIdx};var intArrayFromString=(stringy,dontAddNull,length)=>{var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array};var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;var fd=process.stdin.fd;try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE)}catch(e){if(e.toString().includes("EOF"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}}else if(globalThis.window?.prompt){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.atime=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(60)}try{for(var i=0;i<length;i++){stream.tty.ops.put_char(stream.tty,buffer[offset+i])}}catch(e){throw new FS.ErrnoError(29)}if(length){stream.node.mtime=stream.node.ctime=Date.now()}return i}},default_tty_ops:{get_char(tty){return FS_stdin_getChar()},put_char(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output?.length>0){out(UTF8ArrayToString(tty.output));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output?.length>0){err(UTF8ArrayToString(tty.output));tty.output=[]}}}};var zeroMemory=(ptr,size)=>HEAPU8.fill(0,ptr,ptr+size);var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(ptr)zeroMemory(ptr,size);return ptr};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16895,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.atime=node.mtime=node.ctime=Date.now();if(parent){parent.contents[name]=node;parent.atime=parent.mtime=parent.ctime=node.atime}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)>>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.atime);attr.mtime=new Date(node.mtime);attr.ctime=new Date(node.ctime);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){for(const key of["mode","atime","mtime","ctime"]){if(attr[key]!=null){node[key]=attr[key]}}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){if(!MEMFS.doesNotExistError){MEMFS.doesNotExistError=new FS.ErrnoError(44);MEMFS.doesNotExistError.stack="<generic error, no stack>"}throw MEMFS.doesNotExistError},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){if(FS.isDir(old_node.mode)){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}FS.hashRemoveNode(new_node)}delete old_node.parent.contents[old_node.name];new_dir.contents[new_name]=old_node;old_node.name=new_name;new_dir.ctime=new_dir.mtime=old_node.parent.ctime=old_node.parent.mtime=Date.now()},unlink(parent,name){delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.ctime=parent.mtime=Date.now()},readdir(node){return[".","..",...Object.keys(node.contents)]},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size},write(stream,buffer,offset,length,position,canOwn){if(buffer.buffer===HEAP8.buffer){canOwn=false}if(!length)return 0;var node=stream.node;node.mtime=node.ctime=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray){node.contents.set(buffer.subarray(offset,offset+length),position)}else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length},llseek(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},mmap(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents&&contents.buffer===HEAP8.buffer){allocated=false;ptr=contents.byteOffset}else{allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}if(contents){if(position>0||position+length<contents.length){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}HEAP8.set(contents,ptr)}}return{ptr,allocated}},msync(stream,buffer,offset,length,mmapFlags){MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var asyncLoad=async url=>{var arrayBuffer=await readAsync(url);return new Uint8Array(arrayBuffer)};var FS_createDataFile=(...args)=>FS.createDataFile(...args);var getUniqueRunDependency=id=>id;var preloadPlugins=[];var FS_handledByPreloadPlugin=async(byteArray,fullname)=>{if(typeof Browser!="undefined")Browser.init();for(var plugin of preloadPlugins){if(plugin["canHandle"](fullname)){return plugin["handle"](byteArray,fullname)}}return byteArray};var FS_preloadFile=async(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);addRunDependency(dep);try{var byteArray=url;if(typeof url=="string"){byteArray=await asyncLoad(url)}byteArray=await FS_handledByPreloadPlugin(byteArray,fullname);preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}}finally{removeRunDependency(dep)}};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{FS_preloadFile(parent,name,url,canRead,canWrite,dontCreateFile,canOwn,preFinish).then(onload).catch(onerror)};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,filesystems:null,syncFSRequests:0,readFiles:{},ErrnoError:class{name="ErrnoError";constructor(errno){this.errno=errno}},FSStream:class{shared={};get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{node_ops={};stream_ops={};readMode=292|73;writeMode=146;mounted=null;constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.rdev=rdev;this.atime=this.mtime=this.ctime=Date.now()}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){if(!path){throw new FS.ErrnoError(44)}opts.follow_mount??=true;if(!PATH.isAbs(path)){path=FS.cwd()+"/"+path}linkloop:for(var nlinks=0;nlinks<40;nlinks++){var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}if(parts[i]==="."){continue}if(parts[i]===".."){current_path=PATH.dirname(current_path);if(FS.isRoot(current)){path=current_path+"/"+parts.slice(i+1).join("/");nlinks--;continue linkloop}else{current=current.parent}continue}current_path=PATH.join2(current_path,parts[i]);try{current=FS.lookupNode(current,parts[i])}catch(e){if(e?.errno===44&&islast&&opts.noent_okay){return{path:current_path}}throw e}if(FS.isMountpoint(current)&&(!islast||opts.follow_mount)){current=current.mounted.root}if(FS.isLink(current.mode)&&(!islast||opts.follow)){if(!current.node_ops.readlink){throw new FS.ErrnoError(52)}var link=current.node_ops.readlink(current);if(!PATH.isAbs(link)){link=PATH.dirname(current_path)+"/"+link}path=link+"/"+parts.slice(i+1).join("/");continue linkloop}}return{path:current_path,node:current}}throw new FS.ErrnoError(32)},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){if(!FS.isDir(dir.mode)){return 54}try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&(512|64)){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},checkOpExists(op,err){if(!op){throw new FS.ErrnoError(err)}return op},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},doSetAttr(stream,node,attr){var setattr=stream?.stream_ops.setattr;var arg=setattr?stream:node;setattr??=node.node_ops.setattr;FS.checkOpExists(setattr,63);setattr(arg,attr)},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}for(var mount of mounts){if(mount.type.syncfs){mount.type.syncfs(mount,populate,done)}else{done(null)}}},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);for(var[hash,current]of Object.entries(FS.nameTable)){while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}}node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name){throw new FS.ErrnoError(28)}if(name==="."||name===".."){throw new FS.ErrnoError(20)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},statfs(path){return FS.statfsNode(FS.lookupPath(path,{follow:true}).node)},statfsStream(stream){return FS.statfsNode(stream.node)},statfsNode(node){var rtn={bsize:4096,frsize:4096,blocks:1e6,bfree:5e5,bavail:5e5,files:FS.nextInode,ffree:FS.nextInode-1,fsid:42,flags:2,namelen:255};if(node.node_ops.statfs){Object.assign(rtn,node.node_ops.statfs(node.mount.opts.root))}return rtn},create(path,mode=438){mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode=511){mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var dir of dirs){if(!dir)continue;if(d||PATH.isAbs(path))d+="/";d+=dir;try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name);old_node.parent=new_dir}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var readdir=FS.checkOpExists(node.node_ops.readdir,54);return readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return link.node_ops.readlink(link)},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;var getattr=FS.checkOpExists(node.node_ops.getattr,63);return getattr(node)},fstat(fd){var stream=FS.getStreamChecked(fd);var node=stream.node;var getattr=stream.stream_ops.getattr;var arg=getattr?stream:node;getattr??=node.node_ops.getattr;FS.checkOpExists(getattr,63);return getattr(arg)},lstat(path){return FS.stat(path,true)},doChmod(stream,node,mode,dontFollow){FS.doSetAttr(stream,node,{mode:mode&4095|node.mode&~4095,ctime:Date.now(),dontFollow})},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChmod(null,node,mode,dontFollow)},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.doChmod(stream,stream.node,mode,false)},doChown(stream,node,dontFollow){FS.doSetAttr(stream,node,{timestamp:Date.now(),dontFollow})},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}FS.doChown(null,node,dontFollow)},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.doChown(stream,stream.node,false)},doTruncate(stream,node,len){if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}FS.doSetAttr(stream,node,{size:len,timestamp:Date.now()})},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}FS.doTruncate(null,node,len)},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if(len<0||(stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.doTruncate(stream,stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;var setattr=FS.checkOpExists(node.node_ops.setattr,63);setattr(node,{atime,mtime})},open(path,flags,mode=438){if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;var isDirPath;if(typeof path=="object"){node=path}else{isDirPath=path.endsWith("/");var lookup=FS.lookupPath(path,{follow:!(flags&131072),noent_okay:true});node=lookup.node;path=lookup.path}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else if(isDirPath){throw new FS.ErrnoError(31)}else{node=FS.mknod(path,mode|511,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node,path:FS.getPath(node),flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(created){FS.chmod(node,mode&511)}if(Module["logReadFiles"]&&!(flags&1)){if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}if(!length){throw new FS.ErrnoError(28)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){abort(`Invalid encoding type "${opts.encoding}"`)}var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){buf=UTF8ArrayToString(buf)}FS.close(stream);return buf},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){data=new Uint8Array(intArrayFromString(data,true))}if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{abort("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length,llseek:()=>0});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomFill(randomBuffer);randomLeft=randomBuffer.byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16895,73);node.stream_ops={llseek:MEMFS.stream_ops.llseek};node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path},id:fd+1};ret.parent=ret;return ret},readdir(){return Array.from(FS.streams.entries()).filter(([k,v])=>v).map(([k,v])=>k.toString())}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;for(var stream of FS.streams){if(stream){FS.close(stream)}}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){if(e.errno!=20)throw e}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}},createDevice(parent,name,input,output){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);FS.createDevice.major??=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open(stream){stream.seekable=false},close(stream){if(output?.buffer?.length){output(10)}},read(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.atime=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(29)}}if(length){stream.node.mtime=stream.node.ctime=Date.now()}return i}});return FS.mkdev(path,mode,dev)},forceLoadFile(obj){if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(globalThis.XMLHttpRequest){abort("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else{try{obj.contents=readBinary(obj.url)}catch(e){throw new FS.ErrnoError(29)}}},createLazyFile(parent,name,url,canRead,canWrite){class LazyUint8Array{lengthKnown=false;chunks=[];get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)abort("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)abort("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))abort("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")abort("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(globalThis.XMLHttpRequest){if(!ENVIRONMENT_IS_WORKER)abort("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};for(const[key,fn]of Object.entries(node.stream_ops)){stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}}function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size}stream_ops.read=(stream,buffer,offset,length,position)=>{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var UTF8ToString=(ptr,maxBytesToRead,ignoreNul)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead,ignoreNul):"";var SYSCALLS={calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return dir+"/"+path},writeStat(buf,stat){HEAPU32[buf>>2]=stat.dev;HEAPU32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAPU32[buf+12>>2]=stat.uid;HEAPU32[buf+16>>2]=stat.gid;HEAPU32[buf+20>>2]=stat.rdev;HEAP64[buf+24>>3]=BigInt(stat.size);HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();HEAP64[buf+40>>3]=BigInt(Math.floor(atime/1e3));HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;HEAP64[buf+56>>3]=BigInt(Math.floor(mtime/1e3));HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;HEAP64[buf+72>>3]=BigInt(Math.floor(ctime/1e3));HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;HEAP64[buf+88>>3]=BigInt(stat.ino);return 0},writeStatFs(buf,stats){HEAPU32[buf+4>>2]=stats.bsize;HEAPU32[buf+60>>2]=stats.bsize;HEAP64[buf+8>>3]=BigInt(stats.blocks);HEAP64[buf+16>>3]=BigInt(stats.bfree);HEAP64[buf+24>>3]=BigInt(stats.bavail);HEAP64[buf+32>>3]=BigInt(stats.files);HEAP64[buf+40>>3]=BigInt(stats.ffree);HEAPU32[buf+48>>2]=stats.fsid;HEAPU32[buf+64>>2]=stats.flags;HEAPU32[buf+56>>2]=stats.namelen},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{return SYSCALLS.writeStat(buf,FS.fstat(fd))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(size<cwdLengthInBytes)return-68;stringToUTF8(cwd,buf,size);return cwdLengthInBytes}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_getdents64(fd,dirp,count){try{var stream=SYSCALLS.getStreamFromFD(fd);stream.getdents||=FS.readdir(stream.path);var struct_size=280;var pos=0;var off=FS.llseek(stream,0,1);var startIdx=Math.floor(off/struct_size);var endIdx=Math.min(stream.getdents.length,startIdx+Math.floor(count/struct_size));for(var idx=startIdx;idx<endIdx;idx++){var id;var type;var name=stream.getdents[idx];if(name==="."){id=stream.node.id;type=4}else if(name===".."){var lookup=FS.lookupPath(stream.path,{parent:true});id=lookup.node.id;type=4}else{var child;try{child=FS.lookupNode(stream.node,name)}catch(e){if(e?.errno===28){continue}throw e}id=child.id;type=FS.isChrdev(child.mode)?2:FS.isDir(child.mode)?4:FS.isLink(child.mode)?10:8}HEAP64[dirp+pos>>3]=BigInt(id);HEAP64[dirp+pos+8>>3]=BigInt((idx+1)*struct_size);HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=syscallGetVarargP();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=syscallGetVarargP();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag,c_oflag,c_cflag,c_lflag,c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=syscallGetVarargP();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21537:case 21531:{var argp=syscallGetVarargP();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=syscallGetVarargP();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.lstat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.writeStat(buf,nofollow?FS.lstat(path):FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?syscallGetVarargI():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.writeStat(buf,FS.stat(path))}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_unlinkat(dirfd,path,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(!flags){FS.unlink(path)}else if(flags===512){FS.rmdir(path)}else{return-28}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>abort("");var INT53_MAX=9007199254740992;var INT53_MIN=-9007199254740992;var bigintToI53Checked=num=>num<INT53_MIN||num>INT53_MAX?NaN:Number(num);function __gmtime_js(time,tmPtr){time=bigintToI53Checked(time);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};function __localtime_js(time,tmPtr){time=bigintToI53Checked(time);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}var __mktime_js=function(tmPtr){var ret=(()=>{var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();var timeMs=date.getTime();if(isNaN(timeMs)){return-1}return timeMs/1e3})();return BigInt(ret)};function __mmap_js(len,prot,flags,fd,offset,allocated,addr){offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){offset=bigintToI53Checked(offset);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffset<winterOffset){stringToUTF8(winterName,std_name,17);stringToUTF8(summerName,dst_name,17)}else{stringToUTF8(winterName,dst_name,17);stringToUTF8(summerName,std_name,17)}};var _emscripten_get_now=()=>performance.now();var _emscripten_date_now=()=>Date.now();var nowIsMonotonic=1;var checkWasiClock=clock_id=>clock_id>=0&&clock_id<=3;function _clock_time_get(clk_id,ignored_precision,ptime){ignored_precision=bigintToI53Checked(ignored_precision);if(!checkWasiClock(clk_id)){return 28}var now;if(clk_id===0){now=_emscripten_date_now()}else if(nowIsMonotonic){now=_emscripten_get_now()}else{return 52}var nsec=Math.round(now*1e3*1e3);HEAP64[ptime>>3]=BigInt(nsec);return 0}var readEmAsmArgsArray=[];var readEmAsmArgs=(sigPtr,buf)=>{readEmAsmArgsArray.length=0;var ch;while(ch=HEAPU8[sigPtr++]){var wide=ch!=105;wide&=ch!=112;buf+=wide&&buf%8?4:0;readEmAsmArgsArray.push(ch==112?HEAPU32[buf>>2]:ch==106?HEAP64[buf>>3]:ch==105?HEAP32[buf>>2]:HEAPF64[buf>>3]);buf+=wide?8:4}return readEmAsmArgsArray};var runEmAsmFunction=(code,sigPtr,argbuf)=>{var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code](...args)};var _emscripten_asm_const_int=(code,sigPtr,argbuf)=>runEmAsmFunction(code,sigPtr,argbuf);var _emscripten_errn=(str,len)=>err(UTF8ToString(str,len));var getHeapMax=()=>2147483648;var _emscripten_get_heap_max=()=>getHeapMax();var UNWIND_CACHE={};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var convertFrameToPC=frame=>{var match;if(match=/\bwasm-function\[\d+\]:(0x[0-9a-f]+)/.exec(frame)){return+match[1]}else if(match=/:(\d+):\d+(?:\)|$)/.exec(frame)){return 2147483648|+match[1]}return 0};var saveInUnwindCache=callstack=>{for(var line of callstack){var pc=convertFrameToPC(line);if(pc){UNWIND_CACHE[pc]=line}}};var jsStackTrace=()=>(new Error).stack.toString();var _emscripten_stack_snapshot=()=>{var callstack=jsStackTrace().split("\n");if(callstack[0]=="Error"){callstack.shift()}saveInUnwindCache(callstack);UNWIND_CACHE.last_addr=convertFrameToPC(callstack[3]);UNWIND_CACHE.last_stack=callstack;return UNWIND_CACHE.last_addr};var _emscripten_pc_get_function=pc=>{var frame=UNWIND_CACHE[pc];if(!frame)return 0;var name;var match;if(match=/^\s+at .*\.wasm\.(.*) \(.*\)$/.exec(frame)){name=match[1]}else if(match=/^\s+at (.*) \(.*\)$/.exec(frame)){name=match[1]}else if(match=/^(.+?)@/.exec(frame)){name=match[1]}else{return 0}_free(_emscripten_pc_get_function.ret??0);_emscripten_pc_get_function.ret=stringToNewUTF8(name);return _emscripten_pc_get_function.ret};var growMemory=size=>{var oldHeapSize=wasmMemory.buffer.byteLength;var pages=(size-oldHeapSize+65535)/65536|0;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var _emscripten_stack_unwind_buffer=(addr,buffer,count)=>{var stack;if(UNWIND_CACHE.last_addr==addr){stack=UNWIND_CACHE.last_stack}else{stack=jsStackTrace().split("\n");if(stack[0]=="Error"){stack.shift()}saveInUnwindCache(stack)}var offset=3;while(stack[offset]&&convertFrameToPC(stack[offset])!=addr){++offset}for(var i=0;i<count&&stack[i+offset];++i){HEAP32[buffer+i*4>>2]=convertFrameToPC(stack[i+offset])}return i};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(globalThis.navigator?.language??"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;var envp=0;for(var string of getEnvStrings()){var ptr=environ_buf+bufSize;HEAPU32[__environ+envp>>2]=ptr;bufSize+=stringToUTF8(string,ptr,Infinity)+1;envp+=4}return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;for(var string of strings){bufSize+=lengthBytesUTF8(string)+1}HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break;if(typeof offset!="undefined"){offset+=curr}}return ret};function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset,whence,newOffset){offset=bigintToI53Checked(offset);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);HEAP64[newOffset>>3]=BigInt(stream.position);if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len){break}if(typeof offset!="undefined"){offset+=curr}}return ret};function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func(...cArgs);function onDone(ret){if(stack!==0)stackRestore(stack);return convertReturnValue(ret)}ret=onDone(ret);return ret};var FS_createPath=(...args)=>FS.createPath(...args);var FS_unlink=(...args)=>FS.unlink(...args);var FS_createLazyFile=(...args)=>FS.createLazyFile(...args);var FS_createDevice=(...args)=>FS.createDevice(...args);FS.createPreloadedFile=FS_createPreloadedFile;FS.preloadFile=FS_preloadFile;FS.staticInit();{if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(Module["preloadPlugins"])preloadPlugins=Module["preloadPlugins"];if(Module["print"])out=Module["print"];if(Module["printErr"])err=Module["printErr"];if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].shift()()}}}Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["ccall"]=ccall;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;Module["FS_preloadFile"]=FS_preloadFile;Module["FS_unlink"]=FS_unlink;Module["FS_createPath"]=FS_createPath;Module["FS_createDevice"]=FS_createDevice;Module["FS"]=FS;Module["FS_createDataFile"]=FS_createDataFile;Module["FS_createLazyFile"]=FS_createLazyFile;var ASM_CONSTS={1198924:()=>typeof wasmOffsetConverter!=="undefined",1198981:($0,$1,$2,$3,$4)=>{if(typeof Module=="undefined"||!Module.MountedFiles){return 1}let fileName=UTF8ToString(Number($0>>>0));if(fileName.startsWith("./")){fileName=fileName.substring(2)}const fileData=Module.MountedFiles.get(fileName);if(!fileData){return 2}const offset=Number($1>>>0);const length=Number($2>>>0);const dataIdOrBuffer=Number($3>>>0);const loadType=$4;if(offset+length>fileData.byteLength){return 3}try{const data=fileData.subarray(offset,offset+length);switch(loadType){case 0:HEAPU8.set(data,dataIdOrBuffer);break;case 1:if(Module.webgpuUploadExternalBuffer){Module.webgpuUploadExternalBuffer(dataIdOrBuffer,data)}else{Module.jsepUploadExternalBuffer(dataIdOrBuffer,data)}break;default:return 4}return 0}catch{return 4}}};function HaveOffsetConverter(){return typeof wasmOffsetConverter!=="undefined"}var _CopyHeap,_SherpaOnnxCreateOfflineRecognizer,_SherpaOnnxDestroyOfflineRecognizer,_SherpaOnnxCreateOfflineStream,_SherpaOnnxDestroyOfflineStream,_SherpaOnnxAcceptWaveformOffline,_SherpaOnnxDecodeOfflineStream,_SherpaOnnxDecodeMultipleOfflineStreams,_SherpaOnnxGetOfflineStreamResult,_SherpaOnnxDestroyOfflineRecognizerResult,_SherpaOnnxGetOfflineStreamResultAsJson,_SherpaOnnxDestroyOfflineStreamResultJson,_SherpaOnnxCreateCircularBuffer,_SherpaOnnxDestroyCircularBuffer,_SherpaOnnxCircularBufferPush,_SherpaOnnxCircularBufferGet,_SherpaOnnxCircularBufferFree,_SherpaOnnxCircularBufferPop,_SherpaOnnxCircularBufferSize,_SherpaOnnxCircularBufferHead,_SherpaOnnxCircularBufferReset,_SherpaOnnxCreateVoiceActivityDetector,_SherpaOnnxDestroyVoiceActivityDetector,_SherpaOnnxVoiceActivityDetectorAcceptWaveform,_SherpaOnnxVoiceActivityDetectorEmpty,_SherpaOnnxVoiceActivityDetectorDetected,_SherpaOnnxVoiceActivityDetectorPop,_SherpaOnnxVoiceActivityDetectorClear,_SherpaOnnxVoiceActivityDetectorFront,_SherpaOnnxDestroySpeechSegment,_SherpaOnnxVoiceActivityDetectorReset,_SherpaOnnxVoiceActivityDetectorFlush,_SherpaOnnxFileExists,_emscripten_builtin_memalign,_malloc,_free,__emscripten_stack_restore,__emscripten_stack_alloc,_emscripten_stack_get_current,memory,__indirect_function_table,wasmMemory;function assignWasmExports(wasmExports){_CopyHeap=Module["_CopyHeap"]=wasmExports["Q"];_SherpaOnnxCreateOfflineRecognizer=Module["_SherpaOnnxCreateOfflineRecognizer"]=wasmExports["R"];_SherpaOnnxDestroyOfflineRecognizer=Module["_SherpaOnnxDestroyOfflineRecognizer"]=wasmExports["S"];_SherpaOnnxCreateOfflineStream=Module["_SherpaOnnxCreateOfflineStream"]=wasmExports["T"];_SherpaOnnxDestroyOfflineStream=Module["_SherpaOnnxDestroyOfflineStream"]=wasmExports["U"];_SherpaOnnxAcceptWaveformOffline=Module["_SherpaOnnxAcceptWaveformOffline"]=wasmExports["V"];_SherpaOnnxDecodeOfflineStream=Module["_SherpaOnnxDecodeOfflineStream"]=wasmExports["W"];_SherpaOnnxDecodeMultipleOfflineStreams=Module["_SherpaOnnxDecodeMultipleOfflineStreams"]=wasmExports["X"];_SherpaOnnxGetOfflineStreamResult=Module["_SherpaOnnxGetOfflineStreamResult"]=wasmExports["Y"];_SherpaOnnxDestroyOfflineRecognizerResult=Module["_SherpaOnnxDestroyOfflineRecognizerResult"]=wasmExports["Z"];_SherpaOnnxGetOfflineStreamResultAsJson=Module["_SherpaOnnxGetOfflineStreamResultAsJson"]=wasmExports["_"];_SherpaOnnxDestroyOfflineStreamResultJson=Module["_SherpaOnnxDestroyOfflineStreamResultJson"]=wasmExports["$"];_SherpaOnnxCreateCircularBuffer=Module["_SherpaOnnxCreateCircularBuffer"]=wasmExports["aa"];_SherpaOnnxDestroyCircularBuffer=Module["_SherpaOnnxDestroyCircularBuffer"]=wasmExports["ba"];_SherpaOnnxCircularBufferPush=Module["_SherpaOnnxCircularBufferPush"]=wasmExports["ca"];_SherpaOnnxCircularBufferGet=Module["_SherpaOnnxCircularBufferGet"]=wasmExports["da"];_SherpaOnnxCircularBufferFree=Module["_SherpaOnnxCircularBufferFree"]=wasmExports["ea"];_SherpaOnnxCircularBufferPop=Module["_SherpaOnnxCircularBufferPop"]=wasmExports["fa"];_SherpaOnnxCircularBufferSize=Module["_SherpaOnnxCircularBufferSize"]=wasmExports["ga"];_SherpaOnnxCircularBufferHead=Module["_SherpaOnnxCircularBufferHead"]=wasmExports["ha"];_SherpaOnnxCircularBufferReset=Module["_SherpaOnnxCircularBufferReset"]=wasmExports["ia"];_SherpaOnnxCreateVoiceActivityDetector=Module["_SherpaOnnxCreateVoiceActivityDetector"]=wasmExports["ja"];_SherpaOnnxDestroyVoiceActivityDetector=Module["_SherpaOnnxDestroyVoiceActivityDetector"]=wasmExports["ka"];_SherpaOnnxVoiceActivityDetectorAcceptWaveform=Module["_SherpaOnnxVoiceActivityDetectorAcceptWaveform"]=wasmExports["la"];_SherpaOnnxVoiceActivityDetectorEmpty=Module["_SherpaOnnxVoiceActivityDetectorEmpty"]=wasmExports["ma"];_SherpaOnnxVoiceActivityDetectorDetected=Module["_SherpaOnnxVoiceActivityDetectorDetected"]=wasmExports["na"];_SherpaOnnxVoiceActivityDetectorPop=Module["_SherpaOnnxVoiceActivityDetectorPop"]=wasmExports["oa"];_SherpaOnnxVoiceActivityDetectorClear=Module["_SherpaOnnxVoiceActivityDetectorClear"]=wasmExports["pa"];_SherpaOnnxVoiceActivityDetectorFront=Module["_SherpaOnnxVoiceActivityDetectorFront"]=wasmExports["qa"];_SherpaOnnxDestroySpeechSegment=Module["_SherpaOnnxDestroySpeechSegment"]=wasmExports["ra"];_SherpaOnnxVoiceActivityDetectorReset=Module["_SherpaOnnxVoiceActivityDetectorReset"]=wasmExports["sa"];_SherpaOnnxVoiceActivityDetectorFlush=Module["_SherpaOnnxVoiceActivityDetectorFlush"]=wasmExports["ta"];_SherpaOnnxFileExists=Module["_SherpaOnnxFileExists"]=wasmExports["ua"];_emscripten_builtin_memalign=wasmExports["va"];_malloc=Module["_malloc"]=wasmExports["wa"];_free=Module["_free"]=wasmExports["xa"];__emscripten_stack_restore=wasmExports["ya"];__emscripten_stack_alloc=wasmExports["za"];_emscripten_stack_get_current=wasmExports["Aa"];memory=wasmMemory=wasmExports["O"];__indirect_function_table=wasmExports["__indirect_function_table"]}var wasmImports={q:HaveOffsetConverter,a:___cxa_throw,c:___syscall_fcntl64,J:___syscall_fstat64,A:___syscall_getcwd,B:___syscall_getdents64,k:___syscall_ioctl,F:___syscall_lstat64,C:___syscall_mkdirat,G:___syscall_newfstatat,g:___syscall_openat,z:___syscall_readlinkat,x:___syscall_rmdir,I:___syscall_stat64,y:___syscall_unlinkat,w:__abort_js,t:__gmtime_js,u:__localtime_js,v:__mktime_js,D:__mmap_js,E:__munmap_js,l:__tzset_js,M:_clock_time_get,h:_emscripten_asm_const_int,L:_emscripten_date_now,i:_emscripten_errn,K:_emscripten_get_heap_max,d:_emscripten_get_now,p:_emscripten_pc_get_function,H:_emscripten_resize_heap,s:_emscripten_stack_snapshot,r:_emscripten_stack_unwind_buffer,m:_environ_get,n:_environ_sizes_get,b:_exit,e:_fd_close,j:_fd_read,N:_fd_seek,f:_fd_write,o:_proc_exit};function run(){if(runDependencies>0){dependenciesFulfilled=run;return}preRun();if(runDependencies>0){dependenciesFulfilled=run;return}function doRun(){Module["calledRun"]=true;if(ABORT)return;initRuntime();Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}var wasmExports;createWasm();run();
|
sherpa-onnx-wasm-main-vad-asr.wasm
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:75b82aca6140d2876c7913fd818bfe0356727bc557efc5e4b550247ca19e0d5a
|
| 3 |
+
size 13457647
|
style.css
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
body {
|
| 2 |
+
padding: 2rem;
|
| 3 |
+
font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
h1 {
|
| 7 |
+
font-size: 16px;
|
| 8 |
+
margin-top: 0;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
p {
|
| 12 |
+
color: rgb(107, 114, 128);
|
| 13 |
+
font-size: 15px;
|
| 14 |
+
margin-bottom: 10px;
|
| 15 |
+
margin-top: 5px;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
.card {
|
| 19 |
+
max-width: 620px;
|
| 20 |
+
margin: 0 auto;
|
| 21 |
+
padding: 16px;
|
| 22 |
+
border: 1px solid lightgray;
|
| 23 |
+
border-radius: 16px;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
.card p:last-child {
|
| 27 |
+
margin-bottom: 0;
|
| 28 |
+
}
|
styles.css
ADDED
|
@@ -0,0 +1,1365 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:root {
|
| 2 |
+
color-scheme: light;
|
| 3 |
+
font-family: "Manrope", "Avenir Next", sans-serif;
|
| 4 |
+
color: #151517;
|
| 5 |
+
background: #f3f4f0;
|
| 6 |
+
font-synthesis: none;
|
| 7 |
+
--ink: #151517;
|
| 8 |
+
--ink-rgb: 21, 21, 23;
|
| 9 |
+
--white-rgb: 255, 255, 255;
|
| 10 |
+
--surface-rgb: 250, 250, 247;
|
| 11 |
+
--toolbar-rgb: 248, 249, 246;
|
| 12 |
+
--gradient-end-rgb: 232, 234, 228;
|
| 13 |
+
--muted: rgba(var(--ink-rgb), 0.5);
|
| 14 |
+
--line: rgba(var(--ink-rgb), 0.1);
|
| 15 |
+
--paper: #f3f4f0;
|
| 16 |
+
--surface: #fafbf8;
|
| 17 |
+
--primary-hover: #353538;
|
| 18 |
+
--red: #c60c2e;
|
| 19 |
+
--green: #18ad74;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
:root[data-theme="dark"] {
|
| 23 |
+
color-scheme: dark;
|
| 24 |
+
color: #f1f4f7;
|
| 25 |
+
background: #10151c;
|
| 26 |
+
--ink: #f1f4f7;
|
| 27 |
+
--ink-rgb: 241, 244, 247;
|
| 28 |
+
--white-rgb: 31, 39, 49;
|
| 29 |
+
--surface-rgb: 27, 35, 45;
|
| 30 |
+
--toolbar-rgb: 27, 35, 45;
|
| 31 |
+
--gradient-end-rgb: 13, 20, 29;
|
| 32 |
+
--muted: rgba(var(--ink-rgb), 0.58);
|
| 33 |
+
--line: rgba(var(--ink-rgb), 0.13);
|
| 34 |
+
--paper: #10151c;
|
| 35 |
+
--surface: #1b232d;
|
| 36 |
+
--primary-hover: #d4dde5;
|
| 37 |
+
--red: #fb5476;
|
| 38 |
+
--green: #5bdba7;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
* {
|
| 42 |
+
box-sizing: border-box;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
[hidden] {
|
| 46 |
+
display: none !important;
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
html {
|
| 50 |
+
min-width: 320px;
|
| 51 |
+
min-height: 100%;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
body {
|
| 55 |
+
min-height: 100vh;
|
| 56 |
+
margin: 0;
|
| 57 |
+
overflow-x: hidden;
|
| 58 |
+
background-color: var(--paper);
|
| 59 |
+
background-image:
|
| 60 |
+
linear-gradient(rgba(var(--ink-rgb), 0.035) 1px, transparent 1px),
|
| 61 |
+
linear-gradient(90deg, rgba(var(--ink-rgb), 0.035) 1px, transparent 1px);
|
| 62 |
+
background-size: 64px 64px;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
button,
|
| 66 |
+
input {
|
| 67 |
+
font: inherit;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
button,
|
| 71 |
+
label {
|
| 72 |
+
-webkit-tap-highlight-color: transparent;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
button:focus-visible,
|
| 76 |
+
label:has(input:focus-visible),
|
| 77 |
+
a:focus-visible {
|
| 78 |
+
outline: 2px solid var(--red);
|
| 79 |
+
outline-offset: 4px;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
a {
|
| 83 |
+
color: inherit;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
#ambient {
|
| 87 |
+
position: fixed;
|
| 88 |
+
inset: 0;
|
| 89 |
+
width: 100%;
|
| 90 |
+
height: 100%;
|
| 91 |
+
pointer-events: none;
|
| 92 |
+
opacity: 0.24;
|
| 93 |
+
z-index: -1;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
.topbar {
|
| 97 |
+
height: 88px;
|
| 98 |
+
display: flex;
|
| 99 |
+
align-items: center;
|
| 100 |
+
justify-content: space-between;
|
| 101 |
+
padding: 0 42px;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
.brand {
|
| 105 |
+
display: flex;
|
| 106 |
+
align-items: baseline;
|
| 107 |
+
gap: 9px;
|
| 108 |
+
text-decoration: none;
|
| 109 |
+
font-size: 14px;
|
| 110 |
+
font-weight: 700;
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
.brand-mark {
|
| 114 |
+
text-transform: uppercase;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.brand-divider,
|
| 118 |
+
.product-name {
|
| 119 |
+
color: var(--muted);
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.topbar-actions,
|
| 123 |
+
.transcript-actions {
|
| 124 |
+
display: flex;
|
| 125 |
+
align-items: center;
|
| 126 |
+
gap: 10px;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
.circle-button {
|
| 130 |
+
width: 48px;
|
| 131 |
+
height: 48px;
|
| 132 |
+
border: 1px solid rgba(var(--ink-rgb), 0.08);
|
| 133 |
+
border-radius: 50%;
|
| 134 |
+
background: rgba(var(--white-rgb), 0.68);
|
| 135 |
+
color: rgba(var(--ink-rgb), 0.5);
|
| 136 |
+
box-shadow: 0 5px 20px rgba(var(--ink-rgb), 0.05);
|
| 137 |
+
cursor: pointer;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
.circle-button > span:not(:empty) {
|
| 141 |
+
display: grid;
|
| 142 |
+
place-items: center;
|
| 143 |
+
width: 22px;
|
| 144 |
+
height: 22px;
|
| 145 |
+
margin: auto;
|
| 146 |
+
border: 2px solid currentColor;
|
| 147 |
+
border-radius: 50%;
|
| 148 |
+
font-size: 13px;
|
| 149 |
+
font-weight: 700;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
.theme-button svg {
|
| 153 |
+
width: 20px;
|
| 154 |
+
height: 20px;
|
| 155 |
+
vertical-align: middle;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
.circle-button.sliders span,
|
| 159 |
+
.circle-button.sliders span::before,
|
| 160 |
+
.circle-button.sliders span::after {
|
| 161 |
+
display: block;
|
| 162 |
+
width: 22px;
|
| 163 |
+
height: 2px;
|
| 164 |
+
background: currentColor;
|
| 165 |
+
content: "";
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
.circle-button.sliders span {
|
| 169 |
+
position: relative;
|
| 170 |
+
margin: auto;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
.circle-button.sliders span::before {
|
| 174 |
+
position: absolute;
|
| 175 |
+
top: -7px;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
.circle-button.sliders span::after {
|
| 179 |
+
position: absolute;
|
| 180 |
+
top: 7px;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
.circle-button:disabled {
|
| 184 |
+
cursor: default;
|
| 185 |
+
opacity: 0.38;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
main {
|
| 189 |
+
width: min(920px, calc(100% - 44px));
|
| 190 |
+
margin: 30px auto 0;
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
.intro {
|
| 194 |
+
text-align: center;
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
.section-label {
|
| 198 |
+
margin: 0 0 14px;
|
| 199 |
+
color: rgba(var(--ink-rgb), 0.46);
|
| 200 |
+
font-size: 12px;
|
| 201 |
+
font-weight: 700;
|
| 202 |
+
text-transform: uppercase;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
h1,
|
| 206 |
+
h2,
|
| 207 |
+
p {
|
| 208 |
+
letter-spacing: 0;
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
h1 {
|
| 212 |
+
margin: 0;
|
| 213 |
+
font-size: clamp(34px, 5vw, 58px);
|
| 214 |
+
line-height: 1.08;
|
| 215 |
+
font-weight: 500;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
.intro-copy {
|
| 219 |
+
max-width: 640px;
|
| 220 |
+
margin: 22px auto 0;
|
| 221 |
+
color: var(--muted);
|
| 222 |
+
font-size: 16px;
|
| 223 |
+
line-height: 1.65;
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
.workspace {
|
| 227 |
+
min-height: 500px;
|
| 228 |
+
display: flex;
|
| 229 |
+
flex-direction: column;
|
| 230 |
+
align-items: center;
|
| 231 |
+
padding: 46px 0 74px;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
.model-status {
|
| 235 |
+
width: min(620px, 100%);
|
| 236 |
+
min-height: 24px;
|
| 237 |
+
display: flex;
|
| 238 |
+
align-items: center;
|
| 239 |
+
justify-content: center;
|
| 240 |
+
flex-wrap: wrap;
|
| 241 |
+
gap: 8px;
|
| 242 |
+
margin-top: 24px;
|
| 243 |
+
color: var(--muted);
|
| 244 |
+
font-size: 12px;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
#statusText {
|
| 248 |
+
white-space: nowrap;
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
#statusDetail {
|
| 252 |
+
max-width: 100%;
|
| 253 |
+
min-width: 0;
|
| 254 |
+
overflow: hidden;
|
| 255 |
+
color: rgba(var(--ink-rgb), 0.34);
|
| 256 |
+
text-overflow: ellipsis;
|
| 257 |
+
white-space: nowrap;
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
.status-dot {
|
| 261 |
+
width: 7px;
|
| 262 |
+
height: 7px;
|
| 263 |
+
border-radius: 50%;
|
| 264 |
+
background: #c7a73f;
|
| 265 |
+
box-shadow: 0 0 0 5px rgba(199, 167, 63, 0.1);
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
.status-dot.ready {
|
| 269 |
+
background: var(--green);
|
| 270 |
+
box-shadow: 0 0 0 5px rgba(24, 173, 116, 0.1);
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
.status-dot.error {
|
| 274 |
+
background: var(--red);
|
| 275 |
+
box-shadow: 0 0 0 5px rgba(198, 12, 46, 0.1);
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
.progress-track {
|
| 279 |
+
width: min(360px, 80vw);
|
| 280 |
+
height: 2px;
|
| 281 |
+
margin-top: 10px;
|
| 282 |
+
overflow: hidden;
|
| 283 |
+
background: rgba(var(--ink-rgb), 0.08);
|
| 284 |
+
}
|
| 285 |
+
|
| 286 |
+
.progress-track span {
|
| 287 |
+
display: block;
|
| 288 |
+
width: 0;
|
| 289 |
+
height: 100%;
|
| 290 |
+
background: var(--red);
|
| 291 |
+
transition: width 180ms ease;
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
.progress-track.complete {
|
| 295 |
+
opacity: 0;
|
| 296 |
+
transition: opacity 400ms ease;
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
.mode-panel {
|
| 300 |
+
width: 100%;
|
| 301 |
+
display: flex;
|
| 302 |
+
flex-direction: column;
|
| 303 |
+
align-items: center;
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
.mode-panel[hidden] {
|
| 307 |
+
display: none;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
.live-caption {
|
| 311 |
+
width: min(720px, 100%);
|
| 312 |
+
margin: 30px 0 0;
|
| 313 |
+
color: var(--ink);
|
| 314 |
+
font-size: clamp(21px, 3vw, 30px);
|
| 315 |
+
line-height: 1.4;
|
| 316 |
+
text-align: center;
|
| 317 |
+
text-wrap: balance;
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
.stage {
|
| 321 |
+
--stage-size: clamp(220px, 31vw, 310px);
|
| 322 |
+
position: relative;
|
| 323 |
+
width: var(--stage-size);
|
| 324 |
+
height: var(--stage-size);
|
| 325 |
+
margin-top: 30px;
|
| 326 |
+
padding: 0;
|
| 327 |
+
border: 0;
|
| 328 |
+
border-radius: 50%;
|
| 329 |
+
background: transparent;
|
| 330 |
+
cursor: pointer;
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
.stage:disabled {
|
| 334 |
+
cursor: wait;
|
| 335 |
+
filter: grayscale(0.3);
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
.ring {
|
| 339 |
+
position: absolute;
|
| 340 |
+
width: 100%;
|
| 341 |
+
height: 100%;
|
| 342 |
+
border: 1px solid rgba(140, 191, 255, 0.22);
|
| 343 |
+
border-radius: 50%;
|
| 344 |
+
pointer-events: none;
|
| 345 |
+
will-change: transform;
|
| 346 |
+
animation: ring-breathe 7s ease-in-out infinite;
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
.orb {
|
| 350 |
+
position: relative;
|
| 351 |
+
z-index: 2;
|
| 352 |
+
overflow: hidden;
|
| 353 |
+
border-radius: 50%;
|
| 354 |
+
box-shadow: 0 0 16px rgba(71, 85, 105, 0.14);
|
| 355 |
+
will-change: transform, box-shadow;
|
| 356 |
+
animation: idle-pulse 8s ease-in-out infinite;
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
.orb canvas {
|
| 360 |
+
position: absolute;
|
| 361 |
+
inset: 0;
|
| 362 |
+
width: 100%;
|
| 363 |
+
height: 100%;
|
| 364 |
+
border-radius: 50%;
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
@keyframes idle-pulse {
|
| 368 |
+
0%, 100% { transform: scale(1); box-shadow: 0 0 30px rgba(140, 191, 255, 0.18), 0 0 62px rgba(255, 170, 173, 0.08); }
|
| 369 |
+
50% { transform: scale(1.008); box-shadow: 0 0 35px rgba(140, 191, 255, 0.22), 0 0 68px rgba(255, 170, 173, 0.1); }
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
@keyframes ring-breathe {
|
| 373 |
+
0%, 100% { transform: scale(1); opacity: 0.72; }
|
| 374 |
+
50% { transform: scale(1.018); opacity: 0.42; }
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
.stage-label {
|
| 378 |
+
margin: 24px 0 0;
|
| 379 |
+
color: rgba(var(--ink-rgb), 0.6);
|
| 380 |
+
font-size: 15px;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
.stage-note {
|
| 384 |
+
margin: 7px 0 0;
|
| 385 |
+
color: rgba(var(--ink-rgb), 0.36);
|
| 386 |
+
font-size: 12px;
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
.icon-button {
|
| 390 |
+
border: 0;
|
| 391 |
+
cursor: pointer;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
.transcript {
|
| 395 |
+
padding: 38px 0 64px;
|
| 396 |
+
border-top: 1px solid var(--line);
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
+
.transcript-heading {
|
| 400 |
+
display: flex;
|
| 401 |
+
align-items: flex-start;
|
| 402 |
+
justify-content: space-between;
|
| 403 |
+
gap: 20px;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
.transcript h2,
|
| 407 |
+
dialog h2 {
|
| 408 |
+
margin: 0;
|
| 409 |
+
font-size: 22px;
|
| 410 |
+
font-weight: 600;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
.section-label {
|
| 414 |
+
margin-bottom: 8px;
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
.icon-button {
|
| 418 |
+
min-width: 34px;
|
| 419 |
+
height: 34px;
|
| 420 |
+
padding: 0 8px;
|
| 421 |
+
background: transparent;
|
| 422 |
+
color: rgba(var(--ink-rgb), 0.48);
|
| 423 |
+
font-size: 15px;
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
.icon-button[aria-pressed="true"] {
|
| 427 |
+
color: var(--red);
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
.icon-button:disabled {
|
| 431 |
+
cursor: default;
|
| 432 |
+
opacity: 0.25;
|
| 433 |
+
}
|
| 434 |
+
|
| 435 |
+
.empty-transcript {
|
| 436 |
+
min-height: 170px;
|
| 437 |
+
display: grid;
|
| 438 |
+
place-items: center;
|
| 439 |
+
color: rgba(var(--ink-rgb), 0.32);
|
| 440 |
+
font-size: 14px;
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
.segments {
|
| 444 |
+
margin: 30px 0 0;
|
| 445 |
+
padding: 0;
|
| 446 |
+
list-style: none;
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
.segment {
|
| 450 |
+
display: grid;
|
| 451 |
+
grid-template-columns: 74px minmax(0, 1fr);
|
| 452 |
+
gap: 22px;
|
| 453 |
+
padding: 18px 0;
|
| 454 |
+
border-bottom: 1px solid var(--line);
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
.segment-text {
|
| 458 |
+
margin: 0;
|
| 459 |
+
font-size: 18px;
|
| 460 |
+
line-height: 1.65;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
.segment.preview .segment-text {
|
| 464 |
+
opacity: 0.65;
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
.word {
|
| 468 |
+
border-radius: 2px;
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
footer {
|
| 472 |
+
width: min(920px, calc(100% - 44px));
|
| 473 |
+
display: flex;
|
| 474 |
+
justify-content: space-between;
|
| 475 |
+
gap: 18px;
|
| 476 |
+
margin: 0 auto;
|
| 477 |
+
padding: 22px 0 34px;
|
| 478 |
+
border-top: 1px solid var(--line);
|
| 479 |
+
color: rgba(var(--ink-rgb), 0.42);
|
| 480 |
+
font-size: 11px;
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
.footer-links {
|
| 484 |
+
display: flex;
|
| 485 |
+
align-items: center;
|
| 486 |
+
justify-content: flex-end;
|
| 487 |
+
flex-wrap: wrap;
|
| 488 |
+
gap: 8px;
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
.footer-chip {
|
| 492 |
+
display: inline-flex;
|
| 493 |
+
align-items: center;
|
| 494 |
+
gap: 7px;
|
| 495 |
+
min-height: 32px;
|
| 496 |
+
padding: 7px 11px;
|
| 497 |
+
border: 1px solid rgba(var(--ink-rgb), 0.12);
|
| 498 |
+
border-radius: 999px;
|
| 499 |
+
background: rgba(var(--surface-rgb), 0.82);
|
| 500 |
+
color: rgba(var(--ink-rgb), 0.72);
|
| 501 |
+
font-size: 11px;
|
| 502 |
+
font-weight: 600;
|
| 503 |
+
line-height: 1;
|
| 504 |
+
text-decoration: none;
|
| 505 |
+
transition: background 160ms ease, border-color 160ms ease, color 160ms ease, transform 160ms ease;
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
.footer-chip:hover {
|
| 509 |
+
border-color: rgba(198, 12, 46, 0.28);
|
| 510 |
+
background: var(--surface);
|
| 511 |
+
color: var(--ink);
|
| 512 |
+
transform: translateY(-1px);
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
.footer-chip svg,
|
| 516 |
+
.footer-chip img {
|
| 517 |
+
width: 15px;
|
| 518 |
+
height: 15px;
|
| 519 |
+
flex: 0 0 auto;
|
| 520 |
+
}
|
| 521 |
+
|
| 522 |
+
.footer-chip--github svg {
|
| 523 |
+
color: var(--ink);
|
| 524 |
+
}
|
| 525 |
+
|
| 526 |
+
.footer-chip--linkedin svg {
|
| 527 |
+
color: #0a66c2;
|
| 528 |
+
}
|
| 529 |
+
|
| 530 |
+
dialog {
|
| 531 |
+
width: min(440px, calc(100% - 36px));
|
| 532 |
+
padding: 28px;
|
| 533 |
+
border: 1px solid rgba(var(--ink-rgb), 0.08);
|
| 534 |
+
border-radius: 7px;
|
| 535 |
+
color: var(--ink);
|
| 536 |
+
background: rgba(var(--surface-rgb), 0.98);
|
| 537 |
+
box-shadow: 0 24px 80px rgba(var(--ink-rgb), 0.16);
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
dialog::backdrop {
|
| 541 |
+
background: rgba(var(--ink-rgb), 0.14);
|
| 542 |
+
backdrop-filter: blur(7px);
|
| 543 |
+
}
|
| 544 |
+
|
| 545 |
+
dialog form {
|
| 546 |
+
position: relative;
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
dialog p:not(.section-label) {
|
| 550 |
+
color: var(--muted);
|
| 551 |
+
font-size: 14px;
|
| 552 |
+
line-height: 1.6;
|
| 553 |
+
}
|
| 554 |
+
|
| 555 |
+
.dialog-close {
|
| 556 |
+
position: absolute;
|
| 557 |
+
top: -12px;
|
| 558 |
+
right: -8px;
|
| 559 |
+
width: 32px;
|
| 560 |
+
height: 32px;
|
| 561 |
+
border: 0;
|
| 562 |
+
background: transparent;
|
| 563 |
+
color: var(--muted);
|
| 564 |
+
cursor: pointer;
|
| 565 |
+
font-size: 22px;
|
| 566 |
+
}
|
| 567 |
+
|
| 568 |
+
#microphoneDialog {
|
| 569 |
+
width: min(470px, calc(100% - 32px));
|
| 570 |
+
padding: 0;
|
| 571 |
+
overflow: hidden;
|
| 572 |
+
border-radius: 20px;
|
| 573 |
+
background: var(--surface);
|
| 574 |
+
box-shadow: 0 30px 90px rgba(var(--ink-rgb), 0.22);
|
| 575 |
+
}
|
| 576 |
+
|
| 577 |
+
#microphoneDialog::backdrop {
|
| 578 |
+
background: rgba(var(--ink-rgb), 0.36);
|
| 579 |
+
backdrop-filter: blur(10px);
|
| 580 |
+
}
|
| 581 |
+
|
| 582 |
+
.microphone-dialog-content {
|
| 583 |
+
position: relative;
|
| 584 |
+
padding: 34px;
|
| 585 |
+
}
|
| 586 |
+
|
| 587 |
+
.microphone-dialog-content .dialog-close {
|
| 588 |
+
top: 16px;
|
| 589 |
+
right: 18px;
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
.microphone-icon {
|
| 593 |
+
width: 68px;
|
| 594 |
+
height: 68px;
|
| 595 |
+
display: grid;
|
| 596 |
+
place-items: center;
|
| 597 |
+
margin-bottom: 27px;
|
| 598 |
+
border: 1px solid rgba(24, 173, 116, 0.17);
|
| 599 |
+
border-radius: 20px;
|
| 600 |
+
background: linear-gradient(145deg, #e8f7ed, #d6f0e4);
|
| 601 |
+
color: #16875d;
|
| 602 |
+
box-shadow: 0 10px 28px rgba(24, 173, 116, 0.12);
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
.microphone-icon svg {
|
| 606 |
+
width: 30px;
|
| 607 |
+
height: 30px;
|
| 608 |
+
}
|
| 609 |
+
|
| 610 |
+
#microphoneDialog h2 {
|
| 611 |
+
max-width: 350px;
|
| 612 |
+
margin-bottom: 13px;
|
| 613 |
+
font-size: 26px;
|
| 614 |
+
line-height: 1.25;
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
#microphoneDialog #microphoneDescription {
|
| 618 |
+
margin: 0;
|
| 619 |
+
color: rgba(var(--ink-rgb), 0.66);
|
| 620 |
+
font-size: 14px;
|
| 621 |
+
line-height: 1.7;
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
#microphoneDialog .microphone-browser-note {
|
| 625 |
+
margin: 23px 0 0;
|
| 626 |
+
padding: 12px 15px;
|
| 627 |
+
border-left: 2px solid var(--green);
|
| 628 |
+
border-radius: 0 9px 9px 0;
|
| 629 |
+
background: rgba(24, 173, 116, 0.07);
|
| 630 |
+
color: rgba(var(--ink-rgb), 0.69);
|
| 631 |
+
font-size: 12px;
|
| 632 |
+
line-height: 1.55;
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
+
.microphone-actions {
|
| 636 |
+
display: flex;
|
| 637 |
+
justify-content: flex-end;
|
| 638 |
+
gap: 10px;
|
| 639 |
+
margin-top: 29px;
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
.microphone-actions button {
|
| 643 |
+
min-height: 44px;
|
| 644 |
+
padding: 0 18px;
|
| 645 |
+
border-radius: 10px;
|
| 646 |
+
cursor: pointer;
|
| 647 |
+
font-size: 13px;
|
| 648 |
+
font-weight: 700;
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
+
.microphone-secondary {
|
| 652 |
+
border: 1px solid var(--line);
|
| 653 |
+
background: transparent;
|
| 654 |
+
color: var(--ink);
|
| 655 |
+
}
|
| 656 |
+
|
| 657 |
+
.microphone-primary {
|
| 658 |
+
border: 1px solid var(--ink);
|
| 659 |
+
background: var(--ink);
|
| 660 |
+
color: var(--paper);
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
.microphone-primary:hover {
|
| 664 |
+
background: var(--primary-hover);
|
| 665 |
+
}
|
| 666 |
+
|
| 667 |
+
@media (max-width: 420px) {
|
| 668 |
+
.microphone-dialog-content { padding: 28px 24px; }
|
| 669 |
+
.microphone-actions { flex-direction: column-reverse; }
|
| 670 |
+
.microphone-actions button { width: 100%; }
|
| 671 |
+
}
|
| 672 |
+
|
| 673 |
+
#settingsDialog {
|
| 674 |
+
width: min(560px, calc(100% - 36px));
|
| 675 |
+
}
|
| 676 |
+
|
| 677 |
+
#settingsDialog form {
|
| 678 |
+
max-height: min(70vh, 560px);
|
| 679 |
+
display: flex;
|
| 680 |
+
flex-direction: column;
|
| 681 |
+
}
|
| 682 |
+
|
| 683 |
+
.history-section {
|
| 684 |
+
min-height: 0;
|
| 685 |
+
margin-top: 24px;
|
| 686 |
+
padding-top: 22px;
|
| 687 |
+
border-top: 1px solid var(--line);
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
.history-section .section-label {
|
| 691 |
+
margin-bottom: 7px;
|
| 692 |
+
}
|
| 693 |
+
|
| 694 |
+
.history-title-row {
|
| 695 |
+
display: flex;
|
| 696 |
+
align-items: baseline;
|
| 697 |
+
justify-content: space-between;
|
| 698 |
+
gap: 20px;
|
| 699 |
+
}
|
| 700 |
+
|
| 701 |
+
.history-clear,
|
| 702 |
+
.history-open,
|
| 703 |
+
.history-delete {
|
| 704 |
+
border: 0;
|
| 705 |
+
background: transparent;
|
| 706 |
+
color: inherit;
|
| 707 |
+
cursor: pointer;
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
.history-clear {
|
| 711 |
+
padding: 4px 0;
|
| 712 |
+
color: var(--red);
|
| 713 |
+
font-size: 12px;
|
| 714 |
+
}
|
| 715 |
+
|
| 716 |
+
.history-clear:disabled {
|
| 717 |
+
cursor: default;
|
| 718 |
+
opacity: 0.35;
|
| 719 |
+
}
|
| 720 |
+
|
| 721 |
+
.history-open:disabled,
|
| 722 |
+
.history-delete:disabled {
|
| 723 |
+
cursor: default;
|
| 724 |
+
opacity: 0.4;
|
| 725 |
+
}
|
| 726 |
+
|
| 727 |
+
.history-empty {
|
| 728 |
+
margin: 22px 0 4px;
|
| 729 |
+
padding: 24px 0;
|
| 730 |
+
border-top: 1px solid var(--line);
|
| 731 |
+
text-align: center;
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
.history-list {
|
| 735 |
+
min-height: 0;
|
| 736 |
+
margin: 16px 0 0;
|
| 737 |
+
padding: 0;
|
| 738 |
+
overflow-y: auto;
|
| 739 |
+
list-style: none;
|
| 740 |
+
border-bottom: 1px solid var(--line);
|
| 741 |
+
}
|
| 742 |
+
|
| 743 |
+
.history-item {
|
| 744 |
+
display: grid;
|
| 745 |
+
grid-template-columns: minmax(0, 1fr) 36px;
|
| 746 |
+
align-items: center;
|
| 747 |
+
border-top: 1px solid var(--line);
|
| 748 |
+
}
|
| 749 |
+
|
| 750 |
+
.history-open {
|
| 751 |
+
min-width: 0;
|
| 752 |
+
display: flex;
|
| 753 |
+
flex-direction: column;
|
| 754 |
+
gap: 4px;
|
| 755 |
+
padding: 14px 12px 14px 0;
|
| 756 |
+
text-align: left;
|
| 757 |
+
}
|
| 758 |
+
|
| 759 |
+
.history-date,
|
| 760 |
+
.history-meta {
|
| 761 |
+
color: var(--muted);
|
| 762 |
+
font-size: 11px;
|
| 763 |
+
}
|
| 764 |
+
|
| 765 |
+
.history-preview {
|
| 766 |
+
display: -webkit-box;
|
| 767 |
+
overflow: hidden;
|
| 768 |
+
font-size: 14px;
|
| 769 |
+
line-height: 1.45;
|
| 770 |
+
-webkit-box-orient: vertical;
|
| 771 |
+
-webkit-line-clamp: 2;
|
| 772 |
+
}
|
| 773 |
+
|
| 774 |
+
.history-delete {
|
| 775 |
+
width: 36px;
|
| 776 |
+
height: 36px;
|
| 777 |
+
color: var(--muted);
|
| 778 |
+
font-size: 20px;
|
| 779 |
+
}
|
| 780 |
+
|
| 781 |
+
dl {
|
| 782 |
+
margin: 22px 0 0;
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
dl div,
|
| 786 |
+
.setting-row {
|
| 787 |
+
display: flex;
|
| 788 |
+
align-items: center;
|
| 789 |
+
justify-content: space-between;
|
| 790 |
+
gap: 20px;
|
| 791 |
+
padding: 13px 0;
|
| 792 |
+
border-top: 1px solid var(--line);
|
| 793 |
+
}
|
| 794 |
+
|
| 795 |
+
dt,
|
| 796 |
+
.setting-row strong {
|
| 797 |
+
font-size: 13px;
|
| 798 |
+
font-weight: 600;
|
| 799 |
+
}
|
| 800 |
+
|
| 801 |
+
dd {
|
| 802 |
+
margin: 0;
|
| 803 |
+
color: var(--muted);
|
| 804 |
+
font-size: 13px;
|
| 805 |
+
}
|
| 806 |
+
|
| 807 |
+
.model-link {
|
| 808 |
+
display: inline-flex;
|
| 809 |
+
align-items: center;
|
| 810 |
+
gap: 3px;
|
| 811 |
+
text-decoration: none;
|
| 812 |
+
transition: color 160ms ease;
|
| 813 |
+
}
|
| 814 |
+
|
| 815 |
+
.model-link:hover {
|
| 816 |
+
color: var(--red);
|
| 817 |
+
}
|
| 818 |
+
|
| 819 |
+
.model-link svg {
|
| 820 |
+
width: 15px;
|
| 821 |
+
height: 15px;
|
| 822 |
+
flex: 0 0 auto;
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
.setting-row span {
|
| 826 |
+
display: flex;
|
| 827 |
+
flex-direction: column;
|
| 828 |
+
gap: 3px;
|
| 829 |
+
}
|
| 830 |
+
|
| 831 |
+
.setting-row small {
|
| 832 |
+
color: var(--muted);
|
| 833 |
+
font-size: 11px;
|
| 834 |
+
}
|
| 835 |
+
|
| 836 |
+
.setting-row input {
|
| 837 |
+
width: 38px;
|
| 838 |
+
height: 20px;
|
| 839 |
+
accent-color: var(--red);
|
| 840 |
+
}
|
| 841 |
+
|
| 842 |
+
@media (max-width: 620px) {
|
| 843 |
+
body {
|
| 844 |
+
background-size: 48px 48px;
|
| 845 |
+
}
|
| 846 |
+
|
| 847 |
+
.topbar {
|
| 848 |
+
height: 72px;
|
| 849 |
+
padding: 0 18px;
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
.circle-button {
|
| 853 |
+
width: 42px;
|
| 854 |
+
height: 42px;
|
| 855 |
+
}
|
| 856 |
+
|
| 857 |
+
main,
|
| 858 |
+
footer {
|
| 859 |
+
width: min(100% - 32px, 920px);
|
| 860 |
+
}
|
| 861 |
+
|
| 862 |
+
main {
|
| 863 |
+
margin-top: 28px;
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
h1 {
|
| 867 |
+
font-size: 35px;
|
| 868 |
+
}
|
| 869 |
+
|
| 870 |
+
.intro-copy {
|
| 871 |
+
font-size: 14px;
|
| 872 |
+
}
|
| 873 |
+
|
| 874 |
+
.workspace {
|
| 875 |
+
min-height: 450px;
|
| 876 |
+
padding-top: 36px;
|
| 877 |
+
}
|
| 878 |
+
|
| 879 |
+
.stage {
|
| 880 |
+
--stage-size: min(68vw, 260px);
|
| 881 |
+
}
|
| 882 |
+
|
| 883 |
+
.transcript-heading {
|
| 884 |
+
align-items: center;
|
| 885 |
+
}
|
| 886 |
+
|
| 887 |
+
.segment {
|
| 888 |
+
grid-template-columns: 58px minmax(0, 1fr);
|
| 889 |
+
gap: 12px;
|
| 890 |
+
}
|
| 891 |
+
|
| 892 |
+
.segment-text {
|
| 893 |
+
font-size: 16px;
|
| 894 |
+
}
|
| 895 |
+
|
| 896 |
+
footer {
|
| 897 |
+
flex-direction: column;
|
| 898 |
+
}
|
| 899 |
+
}
|
| 900 |
+
|
| 901 |
+
@media (prefers-reduced-motion: reduce) {
|
| 902 |
+
*,
|
| 903 |
+
*::before,
|
| 904 |
+
*::after {
|
| 905 |
+
scroll-behavior: auto !important;
|
| 906 |
+
transition-duration: 0.01ms !important;
|
| 907 |
+
animation-duration: 0.01ms !important;
|
| 908 |
+
}
|
| 909 |
+
}
|
| 910 |
+
|
| 911 |
+
/* Rye voice interaction scene */
|
| 912 |
+
body {
|
| 913 |
+
min-height: 100dvh;
|
| 914 |
+
overflow: hidden;
|
| 915 |
+
background-image:
|
| 916 |
+
linear-gradient(rgba(var(--ink-rgb), 0.025) 1px, transparent 1px),
|
| 917 |
+
linear-gradient(90deg, rgba(var(--ink-rgb), 0.025) 1px, transparent 1px),
|
| 918 |
+
linear-gradient(145deg, rgba(var(--white-rgb), 0.72), rgba(var(--gradient-end-rgb), 0.42));
|
| 919 |
+
background-size: 32px 32px, 32px 32px, 100% 100%;
|
| 920 |
+
}
|
| 921 |
+
|
| 922 |
+
.topbar {
|
| 923 |
+
position: fixed;
|
| 924 |
+
inset: 0 0 auto;
|
| 925 |
+
z-index: 30;
|
| 926 |
+
height: 84px;
|
| 927 |
+
padding: 0 28px;
|
| 928 |
+
}
|
| 929 |
+
|
| 930 |
+
.circle-button {
|
| 931 |
+
width: 40px;
|
| 932 |
+
height: 40px;
|
| 933 |
+
}
|
| 934 |
+
|
| 935 |
+
main.scene {
|
| 936 |
+
--orb-y: 50%;
|
| 937 |
+
--scene-stage-size: 300px;
|
| 938 |
+
--scene-orb-size: 270px;
|
| 939 |
+
width: min(100%, 720px);
|
| 940 |
+
height: 100dvh;
|
| 941 |
+
min-height: 620px;
|
| 942 |
+
margin: 0 auto;
|
| 943 |
+
position: relative;
|
| 944 |
+
}
|
| 945 |
+
|
| 946 |
+
.scene .intro {
|
| 947 |
+
position: absolute;
|
| 948 |
+
left: 50%;
|
| 949 |
+
bottom: calc(50% + 182px);
|
| 950 |
+
width: min(100% - 48px, 540px);
|
| 951 |
+
transform: translateX(-50%);
|
| 952 |
+
opacity: 1;
|
| 953 |
+
visibility: visible;
|
| 954 |
+
transition:
|
| 955 |
+
opacity 350ms ease,
|
| 956 |
+
visibility 350ms ease,
|
| 957 |
+
transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
|
| 958 |
+
}
|
| 959 |
+
|
| 960 |
+
.scene.session-active .intro {
|
| 961 |
+
opacity: 0;
|
| 962 |
+
visibility: hidden;
|
| 963 |
+
transform: translate(-50%, -16px);
|
| 964 |
+
pointer-events: none;
|
| 965 |
+
}
|
| 966 |
+
|
| 967 |
+
.scene h1 {
|
| 968 |
+
font-size: 36px;
|
| 969 |
+
line-height: 1.12;
|
| 970 |
+
}
|
| 971 |
+
|
| 972 |
+
.scene .intro-copy {
|
| 973 |
+
max-width: 460px;
|
| 974 |
+
margin-top: 10px;
|
| 975 |
+
font-size: 13px;
|
| 976 |
+
line-height: 1.55;
|
| 977 |
+
}
|
| 978 |
+
|
| 979 |
+
.scene .workspace {
|
| 980 |
+
min-height: 0;
|
| 981 |
+
padding: 0;
|
| 982 |
+
}
|
| 983 |
+
|
| 984 |
+
.scene.conversation-visible {
|
| 985 |
+
--orb-y: 30%;
|
| 986 |
+
}
|
| 987 |
+
|
| 988 |
+
.scene .model-status {
|
| 989 |
+
position: absolute;
|
| 990 |
+
z-index: 8;
|
| 991 |
+
top: 88px;
|
| 992 |
+
left: 50%;
|
| 993 |
+
width: calc(100% - 48px);
|
| 994 |
+
flex-wrap: nowrap;
|
| 995 |
+
margin: 0;
|
| 996 |
+
transform: translateX(-50%);
|
| 997 |
+
transition: opacity 250ms ease;
|
| 998 |
+
}
|
| 999 |
+
|
| 1000 |
+
.scene.session-active .model-status {
|
| 1001 |
+
opacity: 0;
|
| 1002 |
+
pointer-events: none;
|
| 1003 |
+
}
|
| 1004 |
+
|
| 1005 |
+
.scene .progress-track {
|
| 1006 |
+
position: absolute;
|
| 1007 |
+
z-index: 8;
|
| 1008 |
+
top: 122px;
|
| 1009 |
+
left: 50%;
|
| 1010 |
+
margin: 0;
|
| 1011 |
+
transform: translateX(-50%);
|
| 1012 |
+
}
|
| 1013 |
+
|
| 1014 |
+
.scene .mode-panel {
|
| 1015 |
+
display: contents;
|
| 1016 |
+
}
|
| 1017 |
+
|
| 1018 |
+
.scene .stage {
|
| 1019 |
+
position: absolute;
|
| 1020 |
+
z-index: 5;
|
| 1021 |
+
top: var(--orb-y);
|
| 1022 |
+
left: 50%;
|
| 1023 |
+
width: var(--scene-stage-size);
|
| 1024 |
+
height: var(--scene-stage-size);
|
| 1025 |
+
display: flex;
|
| 1026 |
+
align-items: center;
|
| 1027 |
+
justify-content: center;
|
| 1028 |
+
margin: 0;
|
| 1029 |
+
transform: translate(-50%, -50%);
|
| 1030 |
+
transition: top 550ms cubic-bezier(0.32, 0.72, 0, 1);
|
| 1031 |
+
}
|
| 1032 |
+
|
| 1033 |
+
.scene .stage::after {
|
| 1034 |
+
position: absolute;
|
| 1035 |
+
inset: -8px;
|
| 1036 |
+
border: 1px solid rgba(var(--ink-rgb), 0.08);
|
| 1037 |
+
border-radius: 50%;
|
| 1038 |
+
content: "";
|
| 1039 |
+
pointer-events: none;
|
| 1040 |
+
transition: transform 250ms ease, opacity 250ms ease;
|
| 1041 |
+
}
|
| 1042 |
+
|
| 1043 |
+
.scene .stage:not(:disabled):hover::after {
|
| 1044 |
+
transform: scale(1.025);
|
| 1045 |
+
}
|
| 1046 |
+
|
| 1047 |
+
.scene .stage:not(:disabled) .orb {
|
| 1048 |
+
transition: transform 250ms ease, box-shadow 250ms ease;
|
| 1049 |
+
}
|
| 1050 |
+
|
| 1051 |
+
.scene .stage:not(:disabled):hover .orb {
|
| 1052 |
+
transform: scale(1.035);
|
| 1053 |
+
}
|
| 1054 |
+
|
| 1055 |
+
.scene .stage:not(:disabled):active .orb {
|
| 1056 |
+
transform: scale(0.97);
|
| 1057 |
+
}
|
| 1058 |
+
|
| 1059 |
+
.scene .stage:focus-visible .orb {
|
| 1060 |
+
outline: 3px solid rgba(82, 39, 255, 0.28);
|
| 1061 |
+
outline-offset: 7px;
|
| 1062 |
+
}
|
| 1063 |
+
|
| 1064 |
+
.scene .stage:disabled {
|
| 1065 |
+
opacity: 1;
|
| 1066 |
+
filter: none;
|
| 1067 |
+
}
|
| 1068 |
+
|
| 1069 |
+
.scene #orb {
|
| 1070 |
+
position: relative;
|
| 1071 |
+
inset: auto;
|
| 1072 |
+
width: var(--scene-orb-size);
|
| 1073 |
+
height: var(--scene-orb-size);
|
| 1074 |
+
background: #8cbfff;
|
| 1075 |
+
filter: none;
|
| 1076 |
+
box-shadow: 0 18px 55px rgba(44, 25, 92, 0.18);
|
| 1077 |
+
}
|
| 1078 |
+
|
| 1079 |
+
.scene .stage-copy {
|
| 1080 |
+
position: absolute;
|
| 1081 |
+
z-index: 6;
|
| 1082 |
+
top: calc(var(--orb-y) + var(--scene-orb-size) / 2 + 42px);
|
| 1083 |
+
left: 50%;
|
| 1084 |
+
width: min(100% - 40px, 420px);
|
| 1085 |
+
transform: translateX(-50%);
|
| 1086 |
+
text-align: center;
|
| 1087 |
+
transition: top 550ms cubic-bezier(0.32, 0.72, 0, 1);
|
| 1088 |
+
}
|
| 1089 |
+
|
| 1090 |
+
.scene .stage-label {
|
| 1091 |
+
margin: 0;
|
| 1092 |
+
font-size: 13px;
|
| 1093 |
+
}
|
| 1094 |
+
|
| 1095 |
+
.scene .stage-note {
|
| 1096 |
+
margin-top: 6px;
|
| 1097 |
+
font-size: 11px;
|
| 1098 |
+
}
|
| 1099 |
+
|
| 1100 |
+
.scene .transcript {
|
| 1101 |
+
position: absolute;
|
| 1102 |
+
z-index: 2;
|
| 1103 |
+
top: calc(var(--orb-y) + var(--scene-orb-size) / 2 + 90px);
|
| 1104 |
+
bottom: 72px;
|
| 1105 |
+
left: 50%;
|
| 1106 |
+
width: min(560px, calc(100vw - 32px));
|
| 1107 |
+
padding: 0 24px 8px;
|
| 1108 |
+
overflow-y: auto;
|
| 1109 |
+
scrollbar-width: none;
|
| 1110 |
+
border: 0;
|
| 1111 |
+
background: transparent;
|
| 1112 |
+
opacity: 0;
|
| 1113 |
+
visibility: hidden;
|
| 1114 |
+
transform: translate(-50%, 18px);
|
| 1115 |
+
transition:
|
| 1116 |
+
top 550ms cubic-bezier(0.32, 0.72, 0, 1),
|
| 1117 |
+
opacity 300ms ease,
|
| 1118 |
+
visibility 300ms ease,
|
| 1119 |
+
transform 420ms cubic-bezier(0.32, 0.72, 0, 1);
|
| 1120 |
+
-webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 28px, #000 100%);
|
| 1121 |
+
mask-image: linear-gradient(to bottom, transparent 0, #000 28px, #000 100%);
|
| 1122 |
+
}
|
| 1123 |
+
|
| 1124 |
+
.scene .transcript::-webkit-scrollbar {
|
| 1125 |
+
display: none;
|
| 1126 |
+
}
|
| 1127 |
+
|
| 1128 |
+
.scene .transcript.open {
|
| 1129 |
+
opacity: 1;
|
| 1130 |
+
visibility: visible;
|
| 1131 |
+
transform: translate(-50%, 0);
|
| 1132 |
+
}
|
| 1133 |
+
|
| 1134 |
+
.scene .transcript-heading {
|
| 1135 |
+
position: absolute;
|
| 1136 |
+
z-index: 18;
|
| 1137 |
+
bottom: 18px;
|
| 1138 |
+
left: 50%;
|
| 1139 |
+
width: auto;
|
| 1140 |
+
opacity: 0;
|
| 1141 |
+
visibility: hidden;
|
| 1142 |
+
transform: translate(-50%, 10px);
|
| 1143 |
+
transition: opacity 250ms ease, visibility 250ms ease, transform 350ms cubic-bezier(0.32, 0.72, 0, 1);
|
| 1144 |
+
}
|
| 1145 |
+
|
| 1146 |
+
.scene.conversation-visible .transcript-heading {
|
| 1147 |
+
opacity: 1;
|
| 1148 |
+
visibility: visible;
|
| 1149 |
+
transform: translate(-50%, 0);
|
| 1150 |
+
}
|
| 1151 |
+
|
| 1152 |
+
.scene .empty-transcript {
|
| 1153 |
+
display: none;
|
| 1154 |
+
}
|
| 1155 |
+
|
| 1156 |
+
.scene .transcript-actions {
|
| 1157 |
+
gap: 5px;
|
| 1158 |
+
padding: 4px 8px;
|
| 1159 |
+
border: 1px solid var(--line);
|
| 1160 |
+
border-radius: 8px;
|
| 1161 |
+
background: rgba(var(--toolbar-rgb), 0.86);
|
| 1162 |
+
box-shadow: 0 8px 24px rgba(var(--ink-rgb), 0.07);
|
| 1163 |
+
backdrop-filter: blur(16px);
|
| 1164 |
+
-webkit-backdrop-filter: blur(16px);
|
| 1165 |
+
}
|
| 1166 |
+
|
| 1167 |
+
.scene .segments {
|
| 1168 |
+
min-height: 100%;
|
| 1169 |
+
display: flex;
|
| 1170 |
+
flex-direction: column;
|
| 1171 |
+
justify-content: flex-end;
|
| 1172 |
+
gap: 18px;
|
| 1173 |
+
margin: 0;
|
| 1174 |
+
padding: 22px 0 16px;
|
| 1175 |
+
}
|
| 1176 |
+
|
| 1177 |
+
.scene .segment {
|
| 1178 |
+
width: fit-content;
|
| 1179 |
+
max-width: 78%;
|
| 1180 |
+
display: flex;
|
| 1181 |
+
flex-direction: column;
|
| 1182 |
+
align-items: flex-end;
|
| 1183 |
+
align-self: flex-end;
|
| 1184 |
+
gap: 3px;
|
| 1185 |
+
padding: 0;
|
| 1186 |
+
border: 0;
|
| 1187 |
+
color: rgba(27, 67, 77, 0.9);
|
| 1188 |
+
text-align: right;
|
| 1189 |
+
animation: message-in 220ms ease-out both;
|
| 1190 |
+
}
|
| 1191 |
+
|
| 1192 |
+
.scene .segment-text {
|
| 1193 |
+
margin: 0;
|
| 1194 |
+
font-size: 15px;
|
| 1195 |
+
line-height: 1.55;
|
| 1196 |
+
overflow-wrap: anywhere;
|
| 1197 |
+
}
|
| 1198 |
+
|
| 1199 |
+
.theme-button[aria-pressed="true"] {
|
| 1200 |
+
color: var(--ink);
|
| 1201 |
+
}
|
| 1202 |
+
|
| 1203 |
+
:root[data-theme="dark"] .scene .segment {
|
| 1204 |
+
color: #b8f2e2;
|
| 1205 |
+
}
|
| 1206 |
+
|
| 1207 |
+
:root[data-theme="dark"] .footer-chip--linkedin svg {
|
| 1208 |
+
color: #83bfff;
|
| 1209 |
+
}
|
| 1210 |
+
.reveal-word {
|
| 1211 |
+
display: inline-block;
|
| 1212 |
+
animation: reveal-word 420ms cubic-bezier(0.16, 0.7, 0.22, 1) both;
|
| 1213 |
+
}
|
| 1214 |
+
|
| 1215 |
+
@keyframes message-in {
|
| 1216 |
+
from { opacity: 0; transform: translateY(5px); }
|
| 1217 |
+
to { opacity: 1; transform: translateY(0); }
|
| 1218 |
+
}
|
| 1219 |
+
|
| 1220 |
+
@keyframes reveal-word {
|
| 1221 |
+
from { opacity: 0; filter: blur(1.5px); transform: translateY(2px); }
|
| 1222 |
+
to { opacity: 1; filter: blur(0); transform: translateY(0); }
|
| 1223 |
+
}
|
| 1224 |
+
|
| 1225 |
+
body.session-active footer {
|
| 1226 |
+
opacity: 0;
|
| 1227 |
+
visibility: hidden;
|
| 1228 |
+
transform: translateY(10px);
|
| 1229 |
+
pointer-events: none;
|
| 1230 |
+
}
|
| 1231 |
+
|
| 1232 |
+
footer {
|
| 1233 |
+
position: fixed;
|
| 1234 |
+
z-index: 12;
|
| 1235 |
+
right: 22px;
|
| 1236 |
+
bottom: 18px;
|
| 1237 |
+
left: 22px;
|
| 1238 |
+
width: auto;
|
| 1239 |
+
margin: 0;
|
| 1240 |
+
padding: 0;
|
| 1241 |
+
border: 0;
|
| 1242 |
+
transition: opacity 300ms ease, visibility 300ms ease, transform 400ms cubic-bezier(0.32, 0.72, 0, 1);
|
| 1243 |
+
}
|
| 1244 |
+
|
| 1245 |
+
@media (max-width: 620px) {
|
| 1246 |
+
.topbar {
|
| 1247 |
+
height: 68px;
|
| 1248 |
+
padding: 0 18px;
|
| 1249 |
+
}
|
| 1250 |
+
|
| 1251 |
+
.brand {
|
| 1252 |
+
font-size: 12px;
|
| 1253 |
+
}
|
| 1254 |
+
|
| 1255 |
+
main.scene {
|
| 1256 |
+
--scene-stage-size: 218px;
|
| 1257 |
+
--scene-orb-size: 192px;
|
| 1258 |
+
min-height: 560px;
|
| 1259 |
+
}
|
| 1260 |
+
|
| 1261 |
+
.scene.conversation-visible {
|
| 1262 |
+
--orb-y: 28%;
|
| 1263 |
+
}
|
| 1264 |
+
|
| 1265 |
+
.scene .intro {
|
| 1266 |
+
bottom: calc(50% + 132px);
|
| 1267 |
+
width: calc(100% - 36px);
|
| 1268 |
+
}
|
| 1269 |
+
|
| 1270 |
+
.scene h1 {
|
| 1271 |
+
font-size: 28px;
|
| 1272 |
+
}
|
| 1273 |
+
|
| 1274 |
+
.scene .intro-copy {
|
| 1275 |
+
max-width: 340px;
|
| 1276 |
+
font-size: 12px;
|
| 1277 |
+
}
|
| 1278 |
+
|
| 1279 |
+
.scene .model-status {
|
| 1280 |
+
top: 74px;
|
| 1281 |
+
}
|
| 1282 |
+
|
| 1283 |
+
.scene .progress-track {
|
| 1284 |
+
top: 106px;
|
| 1285 |
+
}
|
| 1286 |
+
|
| 1287 |
+
.scene .transcript {
|
| 1288 |
+
bottom: 68px;
|
| 1289 |
+
width: calc(100vw - 20px);
|
| 1290 |
+
padding: 0 12px 8px;
|
| 1291 |
+
}
|
| 1292 |
+
|
| 1293 |
+
.scene .segments {
|
| 1294 |
+
padding-top: 18px;
|
| 1295 |
+
}
|
| 1296 |
+
|
| 1297 |
+
.scene .segment {
|
| 1298 |
+
max-width: 84%;
|
| 1299 |
+
}
|
| 1300 |
+
|
| 1301 |
+
.scene .segment-text {
|
| 1302 |
+
font-size: 14px;
|
| 1303 |
+
}
|
| 1304 |
+
|
| 1305 |
+
footer {
|
| 1306 |
+
right: 18px;
|
| 1307 |
+
bottom: 14px;
|
| 1308 |
+
left: 18px;
|
| 1309 |
+
font-size: 9px;
|
| 1310 |
+
}
|
| 1311 |
+
|
| 1312 |
+
.footer-links {
|
| 1313 |
+
justify-content: flex-start;
|
| 1314 |
+
}
|
| 1315 |
+
}
|
| 1316 |
+
|
| 1317 |
+
@media (min-width: 621px) and (max-height: 800px) {
|
| 1318 |
+
.scene .model-status {
|
| 1319 |
+
top: 40px;
|
| 1320 |
+
}
|
| 1321 |
+
|
| 1322 |
+
.scene .progress-track {
|
| 1323 |
+
top: 70px;
|
| 1324 |
+
}
|
| 1325 |
+
}
|
| 1326 |
+
|
| 1327 |
+
@media (min-width: 621px) and (max-height: 700px) {
|
| 1328 |
+
main.scene {
|
| 1329 |
+
--scene-stage-size: 260px;
|
| 1330 |
+
--scene-orb-size: 235px;
|
| 1331 |
+
}
|
| 1332 |
+
|
| 1333 |
+
.scene .intro {
|
| 1334 |
+
bottom: calc(50% + 144px);
|
| 1335 |
+
}
|
| 1336 |
+
}
|
| 1337 |
+
|
| 1338 |
+
@media (max-width: 620px) and (max-height: 700px) {
|
| 1339 |
+
main.scene {
|
| 1340 |
+
--scene-stage-size: 174px;
|
| 1341 |
+
--scene-orb-size: 150px;
|
| 1342 |
+
}
|
| 1343 |
+
|
| 1344 |
+
main.scene:not(.conversation-visible) {
|
| 1345 |
+
--orb-y: 55%;
|
| 1346 |
+
}
|
| 1347 |
+
|
| 1348 |
+
.scene .intro {
|
| 1349 |
+
bottom: calc(45% + 105px);
|
| 1350 |
+
}
|
| 1351 |
+
}
|
| 1352 |
+
|
| 1353 |
+
@media (max-width: 375px) {
|
| 1354 |
+
.footer-links {
|
| 1355 |
+
gap: 6px;
|
| 1356 |
+
}
|
| 1357 |
+
|
| 1358 |
+
.footer-chip--linkedin {
|
| 1359 |
+
padding-inline: 9px;
|
| 1360 |
+
}
|
| 1361 |
+
|
| 1362 |
+
.footer-chip--linkedin span {
|
| 1363 |
+
display: none;
|
| 1364 |
+
}
|
| 1365 |
+
}
|
validation.json
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema": "ekko-browser-validation-v1",
|
| 3 |
+
"date": "2026-09-21",
|
| 4 |
+
"status": "current-artifact-export-smoke-passed",
|
| 5 |
+
"platform": "macOS arm64",
|
| 6 |
+
"runtime": {
|
| 7 |
+
"sherpa_onnx": "1.13.6",
|
| 8 |
+
"onnxruntime_web": "1.29.0",
|
| 9 |
+
"sherpa_commit": "1cb484af5e69d3c7803c1eb0b3b5ab8041e0e911",
|
| 10 |
+
"emscripten": "4.0.23",
|
| 11 |
+
"wasm_sha256": "9b1d4b5ff9ff9f849fa725baa58e90a1c246cac7ff2f0303fa67aa3ad6ccd993",
|
| 12 |
+
"data_sha256": "f4452611fa61d1d51d6b764705812829c39088b1720c70ff01930b299d43796d",
|
| 13 |
+
"bundle_bytes_approximate": 13600000
|
| 14 |
+
},
|
| 15 |
+
"model": {
|
| 16 |
+
"revision": "d89411a3b893a1460ef0d46ef983b128028aa6b0",
|
| 17 |
+
"download_bytes": 135307048,
|
| 18 |
+
"local_verified_cache_server": true,
|
| 19 |
+
"reason": "The private v5 artifact revision loaded through the checksum-verified local cache server."
|
| 20 |
+
},
|
| 21 |
+
"current_artifact_smoke": {
|
| 22 |
+
"onnx_structure": "passed",
|
| 23 |
+
"onnxruntime_cpu_load": "passed",
|
| 24 |
+
"sherpa_onnx_decode": "passed",
|
| 25 |
+
"native_q5_load_and_decode": "passed",
|
| 26 |
+
"browser_wasm": "passed-local-private-preview",
|
| 27 |
+
"browser_model_download_mib": 129.7
|
| 28 |
+
},
|
| 29 |
+
"pnc_v1_browser_validation": {
|
| 30 |
+
"revision": "b1ff0133c7a2bf63ae6288640c267462229a719f",
|
| 31 |
+
"download_bytes": 24434481,
|
| 32 |
+
"loads_after_asr_ready": true,
|
| 33 |
+
"local_verified_cache_server": true
|
| 34 |
+
},
|
| 35 |
+
"pnc_v2_browser_validation": {
|
| 36 |
+
"revision": "2eed18a93ff921de00e4ec53046ae9b1f33de172",
|
| 37 |
+
"manifest_verified_against_box_1_release": true,
|
| 38 |
+
"browser_runtime_status": "local-wasm-smoke-passed",
|
| 39 |
+
"platform": "macOS in-app Chromium browser",
|
| 40 |
+
"checks": {
|
| 41 |
+
"onnxruntime_web_load": "passed",
|
| 42 |
+
"browser_python_parity_on_three_fixed_inputs": "passed",
|
| 43 |
+
"interior_sentence_stop_preserved": true,
|
| 44 |
+
"cross_segment_sentence_start_capitalized": true,
|
| 45 |
+
"word_timestamps_preserved": true,
|
| 46 |
+
"one_word_output": "Ja."
|
| 47 |
+
},
|
| 48 |
+
"remaining_checks": [
|
| 49 |
+
"Live microphone speech with v2 PnC on physical desktop and mobile devices",
|
| 50 |
+
"Compare false sentence stops on one-word and short speech against v1",
|
| 51 |
+
"Memory and latency on desktop and mobile browsers"
|
| 52 |
+
]
|
| 53 |
+
},
|
| 54 |
+
"live_chunking_20260925": {
|
| 55 |
+
"status": "local-wasm-smoke-passed",
|
| 56 |
+
"fixture": "CoRal-project__coral-v3_train_0000002.wav",
|
| 57 |
+
"method": "Injected three copies with one-second pauses into the actual browser ASR worker",
|
| 58 |
+
"provisional_results_before_stop": 3,
|
| 59 |
+
"final_vad_results_before_stop": 3,
|
| 60 |
+
"first_preview_after_audio_seconds": 3.3,
|
| 61 |
+
"final_word_timestamps_present": true,
|
| 62 |
+
"capture_drain_acknowledgement_unit_test": "passed",
|
| 63 |
+
"full_demo_ui_with_synthetic_microphone": {
|
| 64 |
+
"status": "passed",
|
| 65 |
+
"preview_visible_while_speech_detected": true,
|
| 66 |
+
"final_punctuated_transcript_visible_before_stop": true,
|
| 67 |
+
"stop_completes_with_transcript_retained": true
|
| 68 |
+
},
|
| 69 |
+
"limitations": [
|
| 70 |
+
"Browser speech used a synthetic MediaStream rather than a physical microphone",
|
| 71 |
+
"The VAD maximum speech duration is a soft limit, so uninterrupted speech is provisional until a pause or stop",
|
| 72 |
+
"Physical desktop and mobile microphone checks remain"
|
| 73 |
+
]
|
| 74 |
+
},
|
| 75 |
+
"long_form_replay_20260925": {
|
| 76 |
+
"status": "completed-with-remaining-recognition-gaps",
|
| 77 |
+
"method": "User-provided Danish telephone recording converted to 16 kHz mono and queued through the actual browser WASM VAD and ASR worker; final segments then processed by the browser PnC worker",
|
| 78 |
+
"audio_seconds": 774.27,
|
| 79 |
+
"browser_worker_processing_seconds": 228.1,
|
| 80 |
+
"final_segments": 113,
|
| 81 |
+
"provisional_updates": 175,
|
| 82 |
+
"worker_errors": 0,
|
| 83 |
+
"overlapping_final_segments": 0,
|
| 84 |
+
"raw_words": 1736,
|
| 85 |
+
"pnc_preserved_segment_timing_and_word_count": true,
|
| 86 |
+
"pnc_processing_seconds": 1.6,
|
| 87 |
+
"quality_reference": "ElevenLabs transcript in the supplied Markdown, treated as gold for this evaluation",
|
| 88 |
+
"reference_words": 2316,
|
| 89 |
+
"normalization": "Speaker labels and punctuation removed; Unicode word tokens lowercased",
|
| 90 |
+
"wer_before_gap_recovery": 0.3735,
|
| 91 |
+
"wer_after_gap_recovery": 0.3549,
|
| 92 |
+
"final_substitutions": 200,
|
| 93 |
+
"final_deletions": 601,
|
| 94 |
+
"final_insertions": 21,
|
| 95 |
+
"remaining_issue": "One 16-second interval remained undertranscribed; this replay does not prove complete speech capture or physical-microphone behavior."
|
| 96 |
+
},
|
| 97 |
+
"sparse_boundary_retry_20260925": {
|
| 98 |
+
"status": "local-wasm-replay-passed",
|
| 99 |
+
"method": "Retry browser ASR on VAD segments at least 5 seconds long with fewer than 2.5 words per second, shifting the raw-audio decode window by plus and minus 64 samples (4 ms); select a retry only when it yields at least 3 more words",
|
| 100 |
+
"audio_seconds": 774.27,
|
| 101 |
+
"browser_worker_processing_seconds": 280.4,
|
| 102 |
+
"baseline_processing_seconds": 228.1,
|
| 103 |
+
"final_segments": 113,
|
| 104 |
+
"provisional_updates": 175,
|
| 105 |
+
"worker_errors": 0,
|
| 106 |
+
"changed_segments": 8,
|
| 107 |
+
"raw_words": 1841,
|
| 108 |
+
"pnc_preserved_segment_timing_and_word_count": true,
|
| 109 |
+
"pnc_processing_seconds": 1.79,
|
| 110 |
+
"quality_reference": "ElevenLabs transcript in the supplied Markdown, treated as gold for this evaluation",
|
| 111 |
+
"wer_before_retry": 0.3549,
|
| 112 |
+
"wer_after_retry": 0.3174,
|
| 113 |
+
"final_substitutions": 212,
|
| 114 |
+
"final_deletions": 499,
|
| 115 |
+
"final_insertions": 24,
|
| 116 |
+
"cross_service_probe": {
|
| 117 |
+
"source": "transcription-api-service phase vote and comfort-noise findings",
|
| 118 |
+
"strict_majority_vote_method": "Offline vote over baseline and plus/minus 4 ms browser decodes for the 17 sparse segments",
|
| 119 |
+
"strict_majority_vote_wer": 0.3390,
|
| 120 |
+
"changed_segments_overlapping_digital_silence_runs": 0,
|
| 121 |
+
"digital_silence_definition": "Absolute amplitude at most 0.0001 for at least 0.2 seconds",
|
| 122 |
+
"adopted": false
|
| 123 |
+
},
|
| 124 |
+
"limitations": [
|
| 125 |
+
"A 16-second interval remains undertranscribed",
|
| 126 |
+
"One recording does not establish the retry rule's accuracy on other speakers or devices",
|
| 127 |
+
"Accelerated file replay does not measure live microphone latency or mobile behavior"
|
| 128 |
+
]
|
| 129 |
+
},
|
| 130 |
+
"checks": {
|
| 131 |
+
"wasm_initialization": "passed",
|
| 132 |
+
"model_sha256_verification": "passed",
|
| 133 |
+
"localhost_preview_server": "passed",
|
| 134 |
+
"microphone_live_speech": {
|
| 135 |
+
"status": "passed-with-real-speech-through-synthetic-media-stream",
|
| 136 |
+
"word_count": 12,
|
| 137 |
+
"vad_segment_emitted": true,
|
| 138 |
+
"pnc_output": "Ja, sådan er det jo kraftigt, og sådan et metal, ikke ansigt."
|
| 139 |
+
},
|
| 140 |
+
"microphone_multi_chunk_speech": {
|
| 141 |
+
"status": "passed-with-real-speech-through-synthetic-media-stream",
|
| 142 |
+
"audio_seconds": 20.53,
|
| 143 |
+
"segments_before_stop": 5,
|
| 144 |
+
"segments_after_stop": 5,
|
| 145 |
+
"explicit_inter_word_spacing": true,
|
| 146 |
+
"text_stays_below_orb_controls": true,
|
| 147 |
+
"toolbar_stays_below_transcript": true,
|
| 148 |
+
"stop_page_errors": 0
|
| 149 |
+
},
|
| 150 |
+
"microphone_onset_preroll": {
|
| 151 |
+
"status": "passed-with-real-speech-through-synthetic-media-stream",
|
| 152 |
+
"model_revision": "aff2c6e39817e66186a0aa0b3cc8d78fc1ea68ad",
|
| 153 |
+
"fixture": "CoRal-project__coral-v3_train_0000002.wav",
|
| 154 |
+
"runs": 2,
|
| 155 |
+
"opening_word": "nu",
|
| 156 |
+
"opening_word_preserved_runs": 2,
|
| 157 |
+
"first_word_start_seconds": 0.0,
|
| 158 |
+
"second_session_zero_based": true,
|
| 159 |
+
"page_errors": 0,
|
| 160 |
+
"pnc_enabled": false
|
| 161 |
+
},
|
| 162 |
+
"microphone_one_word": {
|
| 163 |
+
"status": "passed-with-real-speech-through-synthetic-media-stream",
|
| 164 |
+
"model_revision": "aff2c6e39817e66186a0aa0b3cc8d78fc1ea68ad",
|
| 165 |
+
"fixture_durations_seconds": [0.47, 0.62, 0.82],
|
| 166 |
+
"expected_word": "ja",
|
| 167 |
+
"recognized_before_stop": ["ja", "ja", "ja"],
|
| 168 |
+
"minimum_speech_seconds": 0.12
|
| 169 |
+
},
|
| 170 |
+
"pnc_export_regression": {
|
| 171 |
+
"status": "passed",
|
| 172 |
+
"source_words": 176,
|
| 173 |
+
"output_words": 176,
|
| 174 |
+
"lowercase_after_sentence_stop": false,
|
| 175 |
+
"malformed_mid_segment_stops_removed": true,
|
| 176 |
+
"cross_segment_sentence_starts_capitalized": true,
|
| 177 |
+
"word_timestamps_retained": true
|
| 178 |
+
},
|
| 179 |
+
"v5_browser_wasm_smoke": {
|
| 180 |
+
"status": "passed-local-private-preview",
|
| 181 |
+
"model_revision": "d89411a3b893a1460ef0d46ef983b128028aa6b0",
|
| 182 |
+
"int8_bundle_bytes": 135307058,
|
| 183 |
+
"current_matrix_mean_wer": 12.945774,
|
| 184 |
+
"one_word_fixture_seconds": 0.47,
|
| 185 |
+
"one_word_output": "ja",
|
| 186 |
+
"sentence_output": "nu tager du det her billede for det er lidt mærkeligt",
|
| 187 |
+
"native_timestamps_present": true,
|
| 188 |
+
"resource_errors": 0
|
| 189 |
+
},
|
| 190 |
+
"conversation_history": {
|
| 191 |
+
"status": "passed",
|
| 192 |
+
"storage": "localStorage",
|
| 193 |
+
"maximum_sessions": 20,
|
| 194 |
+
"persists_across_reload": true,
|
| 195 |
+
"reopens_saved_transcript": true,
|
| 196 |
+
"individual_delete": true,
|
| 197 |
+
"clear_all": true,
|
| 198 |
+
"stores_audio": false,
|
| 199 |
+
"mobile_dialog_fits_viewport": true
|
| 200 |
+
},
|
| 201 |
+
"pnc_browser_parity_probe": {
|
| 202 |
+
"status": "passed",
|
| 203 |
+
"input": "hej mit navn er emil hvordan går det",
|
| 204 |
+
"browser_and_python_output": "Hej, mit navn er Emil, hvordan går det?",
|
| 205 |
+
"word_count": 8,
|
| 206 |
+
"timestamps_preserved": true
|
| 207 |
+
},
|
| 208 |
+
"rye_voice_interaction": {
|
| 209 |
+
"orb_shader_parity": "passed",
|
| 210 |
+
"mobile_stage_css_pixels": 218,
|
| 211 |
+
"mobile_orb_css_pixels": 192,
|
| 212 |
+
"shader_colors": ["#27AE60", "#8CBFFF", "#FFAAAD"],
|
| 213 |
+
"mobile_orb_lift_pixels": 186,
|
| 214 |
+
"mobile_idle_label_gap_pixels": 42,
|
| 215 |
+
"animated_words": 12,
|
| 216 |
+
"mobile_orb_transcript_overlap": false,
|
| 217 |
+
"desktop_orb_transcript_overlap": false,
|
| 218 |
+
"desktop_transcript_toolbar_overlap": false
|
| 219 |
+
},
|
| 220 |
+
"warmed_decoder_performance_harness": {
|
| 221 |
+
"device": "Apple M1 Pro",
|
| 222 |
+
"browser": "Chromium 148 / Electron 42",
|
| 223 |
+
"initial_model_download_and_load_excluded": true,
|
| 224 |
+
"note": "Measured through the same offline decoder before file upload was removed from the public UI.",
|
| 225 |
+
"short_clip": {
|
| 226 |
+
"audio_seconds": 3.12,
|
| 227 |
+
"runs": 5,
|
| 228 |
+
"median_processing_seconds": 0.526,
|
| 229 |
+
"median_rtf": 0.16859,
|
| 230 |
+
"times_realtime": 5.93
|
| 231 |
+
},
|
| 232 |
+
"long_clip": {
|
| 233 |
+
"audio_seconds": 17.86,
|
| 234 |
+
"runs": 3,
|
| 235 |
+
"median_processing_seconds": 2.099,
|
| 236 |
+
"median_rtf": 0.11753,
|
| 237 |
+
"times_realtime": 8.51
|
| 238 |
+
}
|
| 239 |
+
},
|
| 240 |
+
"mobile_390x844_horizontal_overflow": false,
|
| 241 |
+
"desktop_1440x1000_horizontal_overflow": false,
|
| 242 |
+
"mobile_dialogs_fit_viewport": true,
|
| 243 |
+
"clean_reload_resource_errors": 0
|
| 244 |
+
},
|
| 245 |
+
"checks_model_revision": "7cb1747204bddd558ff449399689d5bb641fadd8",
|
| 246 |
+
"remaining_release_checks": [
|
| 247 |
+
"Load the current Tiny and PnC models directly from their public Hugging Face revisions without interception.",
|
| 248 |
+
"Run the complete current-model WER matrix through WebAssembly; local initialization cannot establish browser parity.",
|
| 249 |
+
"Run microphone speech on physical desktop and mobile devices.",
|
| 250 |
+
"Verify Safari, Chromium, and Firefox memory behavior.",
|
| 251 |
+
"Publish the static Space only after model terms and visibility are final."
|
| 252 |
+
]
|
| 253 |
+
}
|
worker.js
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* global OfflineRecognizer, createVad */
|
| 2 |
+
|
| 3 |
+
const SAMPLE_RATE = 16000;
|
| 4 |
+
const VAD_WINDOW = 512;
|
| 5 |
+
const SHORT_UTTERANCE_MIN_SECONDS = 0.12;
|
| 6 |
+
const LIVE_PRE_ROLL_SECONDS = 0.32;
|
| 7 |
+
const LIVE_PRE_ROLL_SAMPLES = Math.round(SAMPLE_RATE * LIVE_PRE_ROLL_SECONDS);
|
| 8 |
+
const LIVE_HISTORY_LIMIT = SAMPLE_RATE * 90;
|
| 9 |
+
const PREVIEW_MIN_SECONDS = 3;
|
| 10 |
+
const SPARSE_RETRY_MIN_SECONDS = 5;
|
| 11 |
+
const SPARSE_RETRY_WORDS_PER_SECOND = 2.5;
|
| 12 |
+
const SPARSE_RETRY_SHIFT_SAMPLES = 64;
|
| 13 |
+
const SPARSE_RETRY_MIN_EXTRA_WORDS = 3;
|
| 14 |
+
|
| 15 |
+
// A private Hugging Face static Space signs its iframe URL. Worker subrequests
|
| 16 |
+
// do not inherit that signature, so carry it to runtime scripts and model files.
|
| 17 |
+
function signedAsset(path) {
|
| 18 |
+
const base = new URL(self.location.href);
|
| 19 |
+
const url = new URL(path, base);
|
| 20 |
+
const signature = base.searchParams.get("__sign");
|
| 21 |
+
if (signature && url.origin === base.origin) url.searchParams.set("__sign", signature);
|
| 22 |
+
return url.href;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
let runtimeResolve;
|
| 26 |
+
const runtimeReady = new Promise((resolve) => {
|
| 27 |
+
runtimeResolve = resolve;
|
| 28 |
+
});
|
| 29 |
+
|
| 30 |
+
var Module = {
|
| 31 |
+
locateFile(path) {
|
| 32 |
+
return signedAsset(path);
|
| 33 |
+
},
|
| 34 |
+
setStatus(status) {
|
| 35 |
+
self.postMessage({type: "runtime-status", status});
|
| 36 |
+
},
|
| 37 |
+
onRuntimeInitialized() {
|
| 38 |
+
runtimeResolve();
|
| 39 |
+
},
|
| 40 |
+
print(text) {
|
| 41 |
+
self.postMessage({type: "runtime-log", message: String(text)});
|
| 42 |
+
},
|
| 43 |
+
printErr(text) {
|
| 44 |
+
self.postMessage({type: "runtime-log", message: String(text)});
|
| 45 |
+
},
|
| 46 |
+
};
|
| 47 |
+
self.Module = Module;
|
| 48 |
+
|
| 49 |
+
importScripts(signedAsset("sherpa-onnx-asr.js"), signedAsset("sherpa-onnx-vad.js"));
|
| 50 |
+
importScripts(signedAsset("sherpa-onnx-wasm-main-vad-asr.js"));
|
| 51 |
+
|
| 52 |
+
let recognizer = null;
|
| 53 |
+
let vad = null;
|
| 54 |
+
let initialization = null;
|
| 55 |
+
let liveCarry = new Float32Array(0);
|
| 56 |
+
let liveHistory = new Float32Array(0);
|
| 57 |
+
let liveHistoryStart = 0;
|
| 58 |
+
let liveSamplesAccepted = 0;
|
| 59 |
+
let previewStart = null;
|
| 60 |
+
let nextPreviewSample = 0;
|
| 61 |
+
let lastLiveResultEndSample = null;
|
| 62 |
+
|
| 63 |
+
function concatenate(left, right) {
|
| 64 |
+
const output = new Float32Array(left.length + right.length);
|
| 65 |
+
output.set(left);
|
| 66 |
+
output.set(right, left.length);
|
| 67 |
+
return output;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
function resetLiveAudio() {
|
| 71 |
+
liveCarry = new Float32Array(0);
|
| 72 |
+
liveHistory = new Float32Array(0);
|
| 73 |
+
liveHistoryStart = 0;
|
| 74 |
+
liveSamplesAccepted = 0;
|
| 75 |
+
previewStart = null;
|
| 76 |
+
nextPreviewSample = 0;
|
| 77 |
+
lastLiveResultEndSample = null;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
function clearLivePreview() {
|
| 81 |
+
if (previewStart === null) return;
|
| 82 |
+
previewStart = null;
|
| 83 |
+
nextPreviewSample = 0;
|
| 84 |
+
self.postMessage({type: "live-preview-clear"});
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
function appendLiveHistory(samples) {
|
| 88 |
+
liveHistory = concatenate(liveHistory, samples);
|
| 89 |
+
liveSamplesAccepted += samples.length;
|
| 90 |
+
if (liveHistory.length > LIVE_HISTORY_LIMIT) {
|
| 91 |
+
const discard = liveHistory.length - LIVE_HISTORY_LIMIT;
|
| 92 |
+
liveHistory = liveHistory.slice(discard);
|
| 93 |
+
liveHistoryStart += discard;
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
function addSegmentPreRoll(segment) {
|
| 98 |
+
const segmentStart = Number(segment.start);
|
| 99 |
+
const prefixStart = Math.max(liveHistoryStart, segmentStart - LIVE_PRE_ROLL_SAMPLES);
|
| 100 |
+
const prefixEnd = Math.min(segmentStart, liveHistoryStart + liveHistory.length);
|
| 101 |
+
if (prefixEnd <= prefixStart) {
|
| 102 |
+
return {samples: segment.samples, start: segmentStart};
|
| 103 |
+
}
|
| 104 |
+
const from = prefixStart - liveHistoryStart;
|
| 105 |
+
const to = prefixEnd - liveHistoryStart;
|
| 106 |
+
return {
|
| 107 |
+
samples: concatenate(liveHistory.slice(from, to), segment.samples),
|
| 108 |
+
start: prefixStart,
|
| 109 |
+
};
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
function retainRecentPreRoll() {
|
| 113 |
+
const keepFrom = Math.max(
|
| 114 |
+
liveHistoryStart,
|
| 115 |
+
(lastLiveResultEndSample ?? liveSamplesAccepted) - LIVE_PRE_ROLL_SAMPLES,
|
| 116 |
+
);
|
| 117 |
+
const discard = keepFrom - liveHistoryStart;
|
| 118 |
+
if (discard > 0) {
|
| 119 |
+
liveHistory = liveHistory.slice(discard);
|
| 120 |
+
liveHistoryStart = keepFrom;
|
| 121 |
+
}
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
function peakNormalize(samples) {
|
| 125 |
+
let peak = 0;
|
| 126 |
+
for (let index = 0; index < samples.length; index += 1) {
|
| 127 |
+
peak = Math.max(peak, Math.abs(samples[index]));
|
| 128 |
+
}
|
| 129 |
+
if (peak === 0 || peak === 0.95) {
|
| 130 |
+
return samples;
|
| 131 |
+
}
|
| 132 |
+
const scale = 0.95 / peak;
|
| 133 |
+
const normalized = new Float32Array(samples.length);
|
| 134 |
+
for (let index = 0; index < samples.length; index += 1) {
|
| 135 |
+
normalized[index] = samples[index] * scale;
|
| 136 |
+
}
|
| 137 |
+
return normalized;
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
async function sha256(bytes) {
|
| 141 |
+
const digest = await crypto.subtle.digest("SHA-256", bytes.buffer);
|
| 142 |
+
return Array.from(new Uint8Array(digest), (value) => value.toString(16).padStart(2, "0")).join("");
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
async function fetchVerified(file, completedBytes, totalBytes) {
|
| 146 |
+
const response = await fetch(signedAsset(file.url), {cache: "force-cache"});
|
| 147 |
+
if (!response.ok || !response.body) {
|
| 148 |
+
throw new Error(`Kunne ikke hente ${file.path} (${response.status})`);
|
| 149 |
+
}
|
| 150 |
+
const reader = response.body.getReader();
|
| 151 |
+
const chunks = [];
|
| 152 |
+
let loaded = 0;
|
| 153 |
+
while (true) {
|
| 154 |
+
const {done, value} = await reader.read();
|
| 155 |
+
if (done) break;
|
| 156 |
+
chunks.push(value);
|
| 157 |
+
loaded += value.byteLength;
|
| 158 |
+
self.postMessage({
|
| 159 |
+
type: "model-progress",
|
| 160 |
+
file: file.path,
|
| 161 |
+
loaded,
|
| 162 |
+
fileBytes: file.bytes,
|
| 163 |
+
overall: Math.min(1, (completedBytes + loaded) / totalBytes),
|
| 164 |
+
});
|
| 165 |
+
}
|
| 166 |
+
const bytes = new Uint8Array(loaded);
|
| 167 |
+
let offset = 0;
|
| 168 |
+
for (const chunk of chunks) {
|
| 169 |
+
bytes.set(chunk, offset);
|
| 170 |
+
offset += chunk.byteLength;
|
| 171 |
+
}
|
| 172 |
+
if (loaded !== file.bytes) {
|
| 173 |
+
throw new Error(`${file.path} har forkert størrelse (${loaded} bytes)`);
|
| 174 |
+
}
|
| 175 |
+
const digest = await sha256(bytes);
|
| 176 |
+
if (digest !== file.sha256) {
|
| 177 |
+
throw new Error(`${file.path} fejlede SHA-256-kontrol`);
|
| 178 |
+
}
|
| 179 |
+
return bytes;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
function createRecognizer(config) {
|
| 183 |
+
recognizer = new OfflineRecognizer(
|
| 184 |
+
{
|
| 185 |
+
featConfig: {
|
| 186 |
+
sampleRate: config.sampleRate,
|
| 187 |
+
featureDim: config.featureDim,
|
| 188 |
+
},
|
| 189 |
+
modelConfig: {
|
| 190 |
+
transducer: {
|
| 191 |
+
encoder: "./nemo-transducer-encoder.onnx",
|
| 192 |
+
decoder: "./nemo-transducer-decoder.onnx",
|
| 193 |
+
joiner: "./nemo-transducer-joiner.onnx",
|
| 194 |
+
},
|
| 195 |
+
tokens: "./tokens.txt",
|
| 196 |
+
modelType: config.modelType,
|
| 197 |
+
provider: "cpu",
|
| 198 |
+
numThreads: 1,
|
| 199 |
+
debug: 0,
|
| 200 |
+
},
|
| 201 |
+
decodingMethod: "greedy_search",
|
| 202 |
+
maxActivePaths: 4,
|
| 203 |
+
},
|
| 204 |
+
Module,
|
| 205 |
+
);
|
| 206 |
+
vad = createVad(Module, {
|
| 207 |
+
sileroVad: {
|
| 208 |
+
model: "./silero_vad.onnx",
|
| 209 |
+
threshold: 0.5,
|
| 210 |
+
minSilenceDuration: 0.5,
|
| 211 |
+
minSpeechDuration: SHORT_UTTERANCE_MIN_SECONDS,
|
| 212 |
+
maxSpeechDuration: 20,
|
| 213 |
+
windowSize: VAD_WINDOW,
|
| 214 |
+
},
|
| 215 |
+
sampleRate: SAMPLE_RATE,
|
| 216 |
+
numThreads: 1,
|
| 217 |
+
provider: "cpu",
|
| 218 |
+
debug: 0,
|
| 219 |
+
bufferSizeInSeconds: 90,
|
| 220 |
+
});
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
async function initialize(configUrl) {
|
| 224 |
+
if (recognizer) return;
|
| 225 |
+
await runtimeReady;
|
| 226 |
+
const response = await fetch(signedAsset(configUrl), {cache: "no-cache"});
|
| 227 |
+
if (!response.ok) throw new Error("Kunne ikke hente modelkonfigurationen");
|
| 228 |
+
const config = await response.json();
|
| 229 |
+
if (config.schema !== "ekko-browser-model-v1") {
|
| 230 |
+
throw new Error("Ukendt modelkonfiguration");
|
| 231 |
+
}
|
| 232 |
+
if (!Module.FS) throw new Error("WASM-filsystemet er ikke eksporteret");
|
| 233 |
+
|
| 234 |
+
const totalBytes = config.files.reduce((sum, file) => sum + file.bytes, 0);
|
| 235 |
+
let completedBytes = 0;
|
| 236 |
+
for (const file of config.files) {
|
| 237 |
+
const bytes = await fetchVerified(file, completedBytes, totalBytes);
|
| 238 |
+
Module.FS.writeFile(file.path, bytes);
|
| 239 |
+
completedBytes += bytes.byteLength;
|
| 240 |
+
}
|
| 241 |
+
createRecognizer(config);
|
| 242 |
+
self.postMessage({
|
| 243 |
+
type: "ready",
|
| 244 |
+
model: config.name,
|
| 245 |
+
runtime: config.runtime,
|
| 246 |
+
bytes: totalBytes,
|
| 247 |
+
});
|
| 248 |
+
}
|
| 249 |
+
|
| 250 |
+
function toWords(result, duration, timeOffset = 0) {
|
| 251 |
+
const tokens = Array.isArray(result.tokens) ? result.tokens : [];
|
| 252 |
+
const timestamps = Array.isArray(result.timestamps) ? result.timestamps : [];
|
| 253 |
+
const durations = Array.isArray(result.durations) ? result.durations : [];
|
| 254 |
+
if (tokens.length !== timestamps.length) return [];
|
| 255 |
+
const words = [];
|
| 256 |
+
let text = "";
|
| 257 |
+
let start = null;
|
| 258 |
+
let tokenIndices = [];
|
| 259 |
+
|
| 260 |
+
const finish = (endHint) => {
|
| 261 |
+
if (!text || start === null) return;
|
| 262 |
+
let end = endHint;
|
| 263 |
+
if (durations.length === tokens.length) {
|
| 264 |
+
for (const index of tokenIndices) {
|
| 265 |
+
end = Math.max(end, Number(timestamps[index]) + Number(durations[index]));
|
| 266 |
+
}
|
| 267 |
+
}
|
| 268 |
+
words.push({
|
| 269 |
+
text,
|
| 270 |
+
start: timeOffset + start,
|
| 271 |
+
end: timeOffset + Math.min(duration, Math.max(start, end)),
|
| 272 |
+
});
|
| 273 |
+
};
|
| 274 |
+
|
| 275 |
+
tokens.forEach((rawToken, index) => {
|
| 276 |
+
const token = String(rawToken);
|
| 277 |
+
const timestamp = Number(timestamps[index]);
|
| 278 |
+
if (token === " " || token.startsWith("▁")) {
|
| 279 |
+
finish(timestamp);
|
| 280 |
+
text = token.trim().replace(/^▁/, "");
|
| 281 |
+
start = timestamp;
|
| 282 |
+
tokenIndices = [index];
|
| 283 |
+
} else {
|
| 284 |
+
if (start === null) start = timestamp;
|
| 285 |
+
text += token;
|
| 286 |
+
tokenIndices.push(index);
|
| 287 |
+
}
|
| 288 |
+
});
|
| 289 |
+
if (text && start !== null) {
|
| 290 |
+
const fallback = timestamps.length ? Number(timestamps[timestamps.length - 1]) + 0.08 : start;
|
| 291 |
+
finish(fallback);
|
| 292 |
+
}
|
| 293 |
+
return words;
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
function decodeSamples(samples, source, timeOffset = 0) {
|
| 297 |
+
if (!recognizer) throw new Error("Modellen er ikke klar");
|
| 298 |
+
const normalized = peakNormalize(samples);
|
| 299 |
+
const duration = normalized.length / SAMPLE_RATE;
|
| 300 |
+
const stream = recognizer.createStream();
|
| 301 |
+
try {
|
| 302 |
+
stream.acceptWaveform(SAMPLE_RATE, normalized);
|
| 303 |
+
recognizer.decode(stream);
|
| 304 |
+
const result = recognizer.getResult(stream);
|
| 305 |
+
return {
|
| 306 |
+
source,
|
| 307 |
+
text: String(result.text || "").trim(),
|
| 308 |
+
start: timeOffset,
|
| 309 |
+
end: timeOffset + duration,
|
| 310 |
+
duration,
|
| 311 |
+
words: toWords(result, duration, timeOffset),
|
| 312 |
+
};
|
| 313 |
+
} finally {
|
| 314 |
+
stream.free();
|
| 315 |
+
}
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
function wordCount(text) {
|
| 319 |
+
const trimmed = text.trim();
|
| 320 |
+
return trimmed ? trimmed.split(/\s+/).length : 0;
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
function retrySparseSegment(buffered, result) {
|
| 324 |
+
const duration = buffered.samples.length / SAMPLE_RATE;
|
| 325 |
+
const originalCount = wordCount(result.text);
|
| 326 |
+
if (duration < SPARSE_RETRY_MIN_SECONDS ||
|
| 327 |
+
originalCount >= duration * SPARSE_RETRY_WORDS_PER_SECOND) return result;
|
| 328 |
+
|
| 329 |
+
let best = result;
|
| 330 |
+
let bestCount = originalCount;
|
| 331 |
+
for (const shift of [SPARSE_RETRY_SHIFT_SAMPLES, -SPARSE_RETRY_SHIFT_SAMPLES]) {
|
| 332 |
+
const start = buffered.start + shift;
|
| 333 |
+
const end = start + buffered.samples.length;
|
| 334 |
+
if (start < liveHistoryStart || end > liveHistoryStart + liveHistory.length) continue;
|
| 335 |
+
const samples = liveHistory.slice(start - liveHistoryStart, end - liveHistoryStart);
|
| 336 |
+
const candidate = decodeSamples(samples, "microphone", start / SAMPLE_RATE);
|
| 337 |
+
const count = wordCount(candidate.text);
|
| 338 |
+
if (count > bestCount) {
|
| 339 |
+
best = candidate;
|
| 340 |
+
bestCount = count;
|
| 341 |
+
}
|
| 342 |
+
}
|
| 343 |
+
if (bestCount < originalCount + SPARSE_RETRY_MIN_EXTRA_WORDS) return result;
|
| 344 |
+
|
| 345 |
+
// Keep the VAD span stable for gap recovery and downstream punctuation.
|
| 346 |
+
const correction = result.start - best.start;
|
| 347 |
+
return {
|
| 348 |
+
...best,
|
| 349 |
+
start: result.start,
|
| 350 |
+
end: result.end,
|
| 351 |
+
duration: result.duration,
|
| 352 |
+
words: best.words.map((word) => ({
|
| 353 |
+
...word,
|
| 354 |
+
start: word.start + correction,
|
| 355 |
+
end: word.end + correction,
|
| 356 |
+
})),
|
| 357 |
+
};
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
function recoverSpeechGap(nextStartSample) {
|
| 361 |
+
if (lastLiveResultEndSample === null) return;
|
| 362 |
+
const start = Math.max(lastLiveResultEndSample, liveHistoryStart);
|
| 363 |
+
const end = Math.min(nextStartSample, liveHistoryStart + liveHistory.length);
|
| 364 |
+
if (end - start < SAMPLE_RATE * 2) return;
|
| 365 |
+
const samples = liveHistory.slice(start - liveHistoryStart, end - liveHistoryStart);
|
| 366 |
+
let sumSquares = 0;
|
| 367 |
+
for (const value of samples) sumSquares += value * value;
|
| 368 |
+
if (Math.sqrt(sumSquares / samples.length) < 0.018) return;
|
| 369 |
+
const result = decodeSamples(samples, "microphone-gap", start / SAMPLE_RATE);
|
| 370 |
+
if (result.text.trim().split(/\s+/).length < 3) return;
|
| 371 |
+
self.postMessage({type: "live-result", result});
|
| 372 |
+
lastLiveResultEndSample = end;
|
| 373 |
+
retainRecentPreRoll();
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
function drainVad() {
|
| 377 |
+
while (!vad.isEmpty()) {
|
| 378 |
+
const segment = vad.front();
|
| 379 |
+
vad.pop();
|
| 380 |
+
const buffered = addSegmentPreRoll(segment);
|
| 381 |
+
const result = retrySparseSegment(
|
| 382 |
+
buffered,
|
| 383 |
+
decodeSamples(buffered.samples, "microphone", buffered.start / SAMPLE_RATE),
|
| 384 |
+
);
|
| 385 |
+
recoverSpeechGap(Math.round(result.start * SAMPLE_RATE));
|
| 386 |
+
clearLivePreview();
|
| 387 |
+
if (result.text) {
|
| 388 |
+
self.postMessage({type: "live-result", result});
|
| 389 |
+
lastLiveResultEndSample = Math.round(result.end * SAMPLE_RATE);
|
| 390 |
+
retainRecentPreRoll();
|
| 391 |
+
}
|
| 392 |
+
}
|
| 393 |
+
}
|
| 394 |
+
|
| 395 |
+
function maybePreviewSpeech() {
|
| 396 |
+
if (!vad.isDetected()) {
|
| 397 |
+
clearLivePreview();
|
| 398 |
+
return;
|
| 399 |
+
}
|
| 400 |
+
if (previewStart === null) {
|
| 401 |
+
previewStart = Math.max(liveHistoryStart, liveSamplesAccepted - SAMPLE_RATE / 2);
|
| 402 |
+
nextPreviewSample = previewStart + PREVIEW_MIN_SECONDS * SAMPLE_RATE;
|
| 403 |
+
}
|
| 404 |
+
if (liveSamplesAccepted < nextPreviewSample) return;
|
| 405 |
+
const start = Math.max(previewStart, liveHistoryStart);
|
| 406 |
+
const samples = liveHistory.slice(start - liveHistoryStart);
|
| 407 |
+
const result = decodeSamples(samples, "preview", start / SAMPLE_RATE);
|
| 408 |
+
if (result.text) self.postMessage({type: "live-preview", result});
|
| 409 |
+
const duration = samples.length / SAMPLE_RATE;
|
| 410 |
+
nextPreviewSample = liveSamplesAccepted + Math.max(PREVIEW_MIN_SECONDS, duration / 6) * SAMPLE_RATE;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
function acceptLiveChunk(samples) {
|
| 414 |
+
liveCarry = concatenate(liveCarry, samples);
|
| 415 |
+
while (liveCarry.length >= VAD_WINDOW) {
|
| 416 |
+
const frame = liveCarry.slice(0, VAD_WINDOW);
|
| 417 |
+
liveCarry = liveCarry.slice(VAD_WINDOW);
|
| 418 |
+
appendLiveHistory(frame);
|
| 419 |
+
vad.acceptWaveform(frame);
|
| 420 |
+
self.postMessage({type: "speech-state", detected: vad.isDetected()});
|
| 421 |
+
drainVad();
|
| 422 |
+
maybePreviewSpeech();
|
| 423 |
+
}
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
function stopLive() {
|
| 427 |
+
if (liveCarry.length) {
|
| 428 |
+
const padded = new Float32Array(VAD_WINDOW);
|
| 429 |
+
padded.set(liveCarry);
|
| 430 |
+
appendLiveHistory(padded);
|
| 431 |
+
vad.acceptWaveform(padded);
|
| 432 |
+
}
|
| 433 |
+
vad.flush();
|
| 434 |
+
drainVad();
|
| 435 |
+
recoverSpeechGap(liveSamplesAccepted);
|
| 436 |
+
clearLivePreview();
|
| 437 |
+
vad.reset();
|
| 438 |
+
resetLiveAudio();
|
| 439 |
+
self.postMessage({type: "live-stopped"});
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
self.onmessage = async (event) => {
|
| 443 |
+
const message = event.data || {};
|
| 444 |
+
try {
|
| 445 |
+
if (message.type === "init") {
|
| 446 |
+
initialization ||= initialize(message.configUrl || "model-config.json");
|
| 447 |
+
await initialization;
|
| 448 |
+
} else if (message.type === "live-start") {
|
| 449 |
+
await initialization;
|
| 450 |
+
vad.reset();
|
| 451 |
+
resetLiveAudio();
|
| 452 |
+
} else if (message.type === "live-chunk") {
|
| 453 |
+
await initialization;
|
| 454 |
+
acceptLiveChunk(new Float32Array(message.samples));
|
| 455 |
+
} else if (message.type === "live-stop") {
|
| 456 |
+
await initialization;
|
| 457 |
+
stopLive();
|
| 458 |
+
}
|
| 459 |
+
} catch (error) {
|
| 460 |
+
self.postMessage({
|
| 461 |
+
type: "error",
|
| 462 |
+
requestId: message.requestId,
|
| 463 |
+
message: error instanceof Error ? error.message : String(error),
|
| 464 |
+
});
|
| 465 |
+
}
|
| 466 |
+
};
|