Add findWord to model object, update docs and change test directory
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -5,3 +5,5 @@ libarchive
|
|||||||
clapack-wasm
|
clapack-wasm
|
||||||
openfst
|
openfst
|
||||||
emsdk
|
emsdk
|
||||||
|
index.html
|
||||||
|
test.js
|
||||||
47
API.md
47
API.md
@@ -1,5 +1,5 @@
|
|||||||
# API reference
|
# API reference
|
||||||
## JS' ```window``` object
|
## JS ```window``` object
|
||||||
| Function/Object | Description |
|
| Function/Object | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| ```Promise<Module> loadVosklet()``` | Load Vosklet module interface |
|
| ```Promise<Module> loadVosklet()``` | Load Vosklet module interface |
|
||||||
@@ -12,36 +12,41 @@
|
|||||||
## ```Module``` object
|
## ```Module``` object
|
||||||
| Function/Object | Description |
|
| Function/Object | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| ```Promise<Model> createModel(url: string, path: string, id: string)```<br><br>```Promise<SpkModel> createSpkModel(url: string, path: string, id: string)``` | Create a ```Model``` or ```SpkModel```, model files must be directly under the model root, and compressed model must be in .tgz format. If:<br>- **path** contains valid model files and **id** is the same, there will not be a fetch from **url**.<br>- **path** doesn't contain valid model files, or if it contains valid model files but **id** is different, there will be a fetch from **url**, and the model is stored with **id**. Models are thread-safe, reuse them as much as possible! |
|
| ```Promise<Model> createModel(url: string, path: string, id: string)```<br><br>```Promise<SpkModel> createSpkModel(url: string, path: string, id: string)``` | Create a ```Model``` or ```SpkModel```, model files must be directly under the model root, and compressed model must be in .tgz format. If:<br>- ```path``` contains valid model files and ```id``` is the same, there will not be a fetch from ```url```.<br>- ```path``` doesn't contain valid model files, or if it contains valid model files but ```id``` is different, there will be a fetch from ```url```, and the model is stored with ```id```. Models are thread-safe and reusable across recognizers.|
|
||||||
| ```Promise<Recognizer> createRecognizer(model: Model, sampleRate: float)```<br><br>```Promise<Recognizer> createRecognizerWithSpkModel(model: Model, spkModel: spkModel, sampleRate: float)```<br><br>```Promise<Recognizer> createRecognizerWithGrm(model: Model, grammar: string, sampleRate: float)``` | Create a ```Recognizer```, it will use **model**'s thread if it's the first user of **model**, else it will use a new thread. |
|
| ```Promise<Recognizer> createRecognizer(model: Model, sampleRate: float)```<br><br>```Promise<Recognizer> createRecognizerWithSpkModel(model: Model, spkModel: spkModel, sampleRate: float)```<br><br>```Promise<Recognizer> createRecognizerWithGrm(model: Model, grammar: string, sampleRate: float)``` | Create a ```Recognizer```, it will reuse the thread from ```model``` if it's the first user of ```model```, else it will use a new thread. |
|
||||||
| ```setLogLevel(lvl: int)``` | Set Vosk's log level (default: ```0```: Info) <br>```-2```: Error<br>```-1```: Warning<br>```1```: Verbose<br>```2```: More verbose<br>```3```: Debug |
|
| ```setLogLevel(lvl: int)``` | Set log level for Kaldi messages (default: ```0```: Info) <br>```-2```: Error<br>```-1```: Warning<br>```1```: Verbose<br>```2```: More verbose<br>```3```: Debug |
|
||||||
| ```Promise<AudioWorkletNode> createTransferer(ctx: AudioContext, bufferSize: int)``` | Create a node that transfer its inputs back to the main thread with custom buffer size (must be multiple of 128). Its port's ```onmessage``` handler can be set to get audio data. Has 1 input with 1 channel and 0 output. The the higher the size, the lesser the audio breaks up, but the higher the latency. Recomended value is around ```128 * 150```. |
|
| ```Promise<AudioWorkletNode> createTransferer(ctx: AudioContext, bufferSize: int)``` | Create a node that transfer its inputs back to the main thread with custom buffer size (must be multiple of 128). Its port's ```onmessage``` handler can be set to get audio data. Has 1 input with 1 channel and no output. The the higher the size, the lesser the audio breaks up, but the higher the latency. Recomended value is around ```128 * 150```. |
|
||||||
| ```cleanUp()``` | A convenience function that call ```delete()``` on all objects and revoke all URLs. **Put this at the end of your code!** |
|
| ```cleanUp()``` | A convenience function that call ```delete()``` on all objects and revoke all URLs. **Put this at the end of your code!** |
|
||||||
| ```epMode``` | Endpointer modes (enum) | See Vosk's description |
|
| ```epMode``` | Enum for endpointer modes | See Vosk's description |
|
||||||
|
|
||||||
|
## ```Model``` object
|
||||||
|
| Function/Object | Description |
|
||||||
|
|---|---|
|
||||||
|
| ```int findWord(word: string)``` | Check if a word can be recognized by the model, return the word symbol if ```word``` exists inside the model or ```-1``` otherwise. Word symbol ```0``` is for epsilon. |
|
||||||
|
|
||||||
## ```Recognizer``` object
|
## ```Recognizer``` object
|
||||||
| Function/Object | Description |
|
| Function/Object | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| ```acceptWaveform(audioData: Float32Array)``` | Recognize audio data in a ```Float32Array``` with elements from -1.0 to 1.0. |
|
| ```acceptWaveform(audioData: Float32Array)``` | Accept voice data in a ```Float32Array``` with elements from ```-1.0``` to ```1.0```. |
|
||||||
| ```setPartialWords(partialWords: bool)``` | See Vosk's description (default: false) |
|
| ```setWords(words: bool)``` | Enables words with times in the output (default: ```false```) |
|
||||||
| ```setWords(words: bool)``` | See Vosk's description (default: false) |
|
| ```setPartialWords(partialWords: bool)``` | Like above return words and confidences in partial results (default: ```false```) |
|
||||||
| ```setNLSML(nlsml: bool)``` | See Vosk's description (default: false) |
|
| ```setNLSML(nlsml: bool)``` | Set NLSML output (default: ```false```) |
|
||||||
| ```setMaxAlternatives(alts: int)``` | See Vosk's description (default: false) |
|
| ```setMaxAlternatives(alts: int)``` | Configures recognizer to output n-best results (default: ```false```) |
|
||||||
| ```setGrm(grm: string)``` | See Vosk's description (default: none) |
|
| ```setGrm(grm: string)``` | Reconfigures recognizer to use grammar |
|
||||||
| ```setSpkModel(mdl: SpkModel)``` | See Vosk's description (default: none) |
|
| ```setSpkModel(mdl: SpkModel)``` | Adds speaker model to already initialized recognizer |
|
||||||
| ```setEndpointerMode(mode: epMode)``` | See Vosk's description (default: ANSWER_DEFAULT) |
|
| ```setEndpointerMode(mode: epMode)``` | Set endpointer scaling factor (default: ```ANSWER_DEFAULT```) |
|
||||||
| ```setEndpointerDelays(tStartMax: float, tEnd: float, tMax: float)``` | See Vosk's description |
|
| ```setEndpointerDelays(tStartMax: float, tEnd: float, tMax: float)``` | Set endpointer delays |
|
||||||
|
|
||||||
| Event | Description |
|
| Event | Description |
|
||||||
|---|---|
|
|---|---|
|
||||||
| ```partialResult``` | There is a partial recognition result, check the event's *detail* property |
|
| ```partialResult``` | There is a partial recognition result, check the event's ```detail``` property |
|
||||||
| ```result``` | There is a full recognition result, check the event's *detail* property |
|
| ```result``` | There is a full recognition result, check the event's ```detail``` property |
|
||||||
|
|
||||||
# User agent notes
|
# User agent notes
|
||||||
## SharedArrayBuffer
|
## SharedArrayBuffer
|
||||||
Vosklet require SharedArrayBuffer to share threads' data, so these response headers must be set:
|
SharedArrayBuffer is necessary to share data between threads, so these response headers must be set:
|
||||||
- ***Cross-Origin-Embedder-Policy*** ---> ***require-corp***
|
- ```Cross-Origin-Embedder-Policy``` ⟶ ```require-corp```
|
||||||
- ***Cross-Origin-Opener-Policy*** ---> ***same-origin***
|
- ```Cross-Origin-Opener-Policy``` ⟶ ```same-origin```
|
||||||
|
|
||||||
If you can't set them, you may use a hacky workaround at *src/addCOI.js*.
|
If you can't set them, you may use a hacky workaround at *src/addCOI.js*.
|
||||||
|
|
||||||
@@ -58,6 +63,6 @@ cd Vosklet/src &&
|
|||||||
| Option | Description | Default value |
|
| Option | Description | Default value |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| MAX_MEMORY | Set max memory, valid suffixes: kb, mb, gb, tb or none (bytes) | ```300mb``` as [recommended](https://alphacephei.com/vosk/models) |
|
| MAX_MEMORY | Set max memory, valid suffixes: kb, mb, gb, tb or none (bytes) | ```300mb``` as [recommended](https://alphacephei.com/vosk/models) |
|
||||||
| MAX_THREADS | Set the max number of threads (>=1), this should be equal to the number of model or speaker model that is used in the program | ```1``` (1 recognizer, 1 model, 0 speaker model) |
|
| MAX_THREADS | Set the max number of threads (>=1), this should be equal to the number of model or speaker model that is used in the program | ```1``` (1 recognizer, 1 model, no speaker model) |
|
||||||
| JOBS | Set the number of jobs (threads) when building | ```$(nproc)``` |
|
| JOBS | Set the number of jobs (threads) when building | ```$(nproc)``` |
|
||||||
| EMSDK | Set EMSDK's path (will install EMSDK in root folder if unset) | ```../emsdk``` |
|
| EMSDK | Set EMSDK's path (will install EMSDK in root folder if unset) | ```../emsdk``` |
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
- Designed with basic/nothrow exception safety
|
- Designed with basic/nothrow exception safety
|
||||||
- See the *examples* folder for examples on using the API.
|
- See the *examples* folder for examples on using the API.
|
||||||
- See *API.md* for the API reference
|
- See *API.md* for the API reference
|
||||||
- See the *devel* folder for the build script for development
|
- See *test* for a developer build script for just the JS
|
||||||
|
|
||||||
# Compared to vosk-browser
|
# Compared to vosk-browser
|
||||||
- Support multiple models
|
- Support multiple models
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.0.0/Vosklet.js" async defer></script>
|
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.0.2/Vosklet.js" async defer></script>
|
||||||
<script>
|
<script>
|
||||||
async function start() {
|
async function start() {
|
||||||
// Make sure sample rate matches that in the training data
|
// Make sure sample rate matches that in the training data
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="../Vosklet.js" async defer></script>
|
|
||||||
<script>
|
|
||||||
async function start() {
|
|
||||||
let ctx = new AudioContext({sampleRate : 16000})
|
|
||||||
let micNode = ctx.createMediaStreamSource(await navigator.mediaDevices.getUserMedia({
|
|
||||||
video: false,
|
|
||||||
audio: {
|
|
||||||
echoCancellation: true,
|
|
||||||
noiseSuppression: true,
|
|
||||||
channelCount: 1,
|
|
||||||
sampleRate: 16000
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
let module = await loadVosklet()
|
|
||||||
let model = await module.createModel("en-model.tgz","model","ID")
|
|
||||||
let recognizer = await module.createRecognizer(model, 16000)
|
|
||||||
recognizer.addEventListener("result", ev => {
|
|
||||||
console.log("Result: ", ev.detail)
|
|
||||||
})
|
|
||||||
recognizer.addEventListener("partialResult", ev => {
|
|
||||||
console.log("Partial result: ", ev.detail)
|
|
||||||
})
|
|
||||||
let transferer = await module.createTransferer(ctx, 25600)
|
|
||||||
transferer.port.onmessage = ev => {
|
|
||||||
recognizer.acceptWaveform(ev.data)
|
|
||||||
}
|
|
||||||
micNode.connect(transferer)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<button onclick="start()">Start</button>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.0.0/Vosklet.js" async defer></script>
|
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.0.2/Vosklet.js" async defer></script>
|
||||||
<script>
|
<script>
|
||||||
async function start() {
|
async function start() {
|
||||||
// Make sure sample rate matches that in the training data
|
// Make sure sample rate matches that in the training data
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.0.0/Vosklet.js" async defer></script>
|
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.0.2/Vosklet.js" async defer></script>
|
||||||
<script>
|
<script>
|
||||||
async function start() {
|
async function start() {
|
||||||
// Make sure sample rate matches that in the training data
|
// Make sure sample rate matches that in the training data
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
# Overview
|
|
||||||
- A speech recognizer built on Vosk that can be run on the browser, inspired by [vosk-browser](https://github.com/ccoreilly/vosk-browser), but built from scratch and no code taken!
|
|
||||||
- Designed with basic/nothrow exception safety
|
|
||||||
- See the *examples* folder for examples on using the API.
|
|
||||||
- See *API.md* for the API reference
|
|
||||||
- See the *devel* folder for the build script for development
|
|
||||||
|
|
||||||
# Compared to vosk-browser
|
|
||||||
- Support multiple models
|
|
||||||
- Has models' storage path management
|
|
||||||
- Has models' ID management (for model updates)
|
|
||||||
- Has smaller JS size (>3.1MB vs 1.4MB gzipped)
|
|
||||||
- Has all related files (pthread worker, audio worklet processor,...) merged
|
|
||||||
- Has faster processing time
|
|
||||||
- Has shorter from-scratch build time
|
|
||||||
- Has more Vosk functions exposed
|
|
||||||
|
|
||||||
# Basic usage (microphone recognition)
|
|
||||||
- Result are logged to the console.
|
|
||||||
- Copied from *examples/fromMic.html*
|
|
||||||
```html
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.0.0/Vosklet.js" async defer></script>
|
|
||||||
<script>
|
|
||||||
async function start() {
|
|
||||||
// Make sure sample rate matches that in the training data
|
|
||||||
let ctx = new AudioContext({sampleRate : 16000})
|
|
||||||
// Setup mic with correct sample rate
|
|
||||||
let micNode = ctx.createMediaStreamSource(await navigator.mediaDevices.getUserMedia({
|
|
||||||
video: false,
|
|
||||||
audio: {
|
|
||||||
echoCancellation: true,
|
|
||||||
noiseSuppression: true,
|
|
||||||
channelCount: 1,
|
|
||||||
sampleRate: 16000
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
// Load Vosklet module, model and recognizer
|
|
||||||
let module = await loadVosklet()
|
|
||||||
let model = await module.createModel("en-model.tgz","model","ID")
|
|
||||||
let recognizer = await module.createRecognizer(model, 16000)
|
|
||||||
// Listen for result and partial result
|
|
||||||
recognizer.addEventListener("result", ev => {
|
|
||||||
console.log("Result: ", ev.detail)
|
|
||||||
})
|
|
||||||
recognizer.addEventListener("partialResult", ev => {
|
|
||||||
console.log("Partial result: ", ev.detail)
|
|
||||||
})
|
|
||||||
// Create a transferer node to get audio data on the main thread
|
|
||||||
let transferer = await module.createTransferer(ctx, 128 * 150)
|
|
||||||
// Recognize data on arrival
|
|
||||||
transferer.port.onmessage = ev => {
|
|
||||||
recognizer.acceptWaveform(ev.data)
|
|
||||||
}
|
|
||||||
// Connect to microphone
|
|
||||||
micNode.connect(transferer)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<!-- Start and create audio context only as a result of user's action -->
|
|
||||||
<button onclick="start()">Start</button>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
22
npm/index.js
22
npm/index.js
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
|||||||
"name": "vosklet",
|
"name": "vosklet",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"description": "A speech recognizer that can run on the browser, inspired by vosk-browser",
|
"description": "A speech recognizer that can run on the browser, inspired by vosk-browser",
|
||||||
"main": "index.js",
|
"main": "Vosklet.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
"example": "examples"
|
"example": "examples"
|
||||||
},
|
},
|
||||||
@@ -15,7 +15,8 @@ EMSCRIPTEN_BINDINGS() {
|
|||||||
|
|
||||||
class_<genericModel>("genericModel")
|
class_<genericModel>("genericModel")
|
||||||
.constructor<int, bool, std::string, std::string>(allow_raw_pointers())
|
.constructor<int, bool, std::string, std::string>(allow_raw_pointers())
|
||||||
.function("extractAndLoad", &genericModel::extractAndLoad, allow_raw_pointers());
|
.function("extractAndLoad", &genericModel::extractAndLoad, allow_raw_pointers())
|
||||||
|
.function("findWord", &genericModel::findWord, allow_raw_pointers());
|
||||||
|
|
||||||
class_<recognizer>("recognizer")
|
class_<recognizer>("recognizer")
|
||||||
.constructor<int, float, genericModel*>(allow_raw_pointers())
|
.constructor<int, float, genericModel*>(allow_raw_pointers())
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ void genericModel::extractAndLoad(int tarStart, int tarSize) {
|
|||||||
}};
|
}};
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
|
int genericModel::findWord(std::string word) {
|
||||||
|
return vosk_model_find_word(std::get<VoskModel*>(mdl), word.c_str());
|
||||||
|
}
|
||||||
genericModel::~genericModel() {
|
genericModel::~genericModel() {
|
||||||
archive_entry_free(entry);
|
archive_entry_free(entry);
|
||||||
if(normalMdl) vosk_model_free(std::get<VoskModel*>(mdl));
|
if(normalMdl) vosk_model_free(std::get<VoskModel*>(mdl));
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ struct genericModel {
|
|||||||
std::function<void()> func;
|
std::function<void()> func;
|
||||||
archive_entry* entry;
|
archive_entry* entry;
|
||||||
void extractAndLoad(int tarStart, int tarSize);
|
void extractAndLoad(int tarStart, int tarSize);
|
||||||
|
int findWord(std::string word);
|
||||||
genericModel(int index, bool normalMdl, std::string storepath, std::string id);
|
genericModel(int index, bool normalMdl, std::string storepath, std::string id);
|
||||||
~genericModel();
|
~genericModel();
|
||||||
};
|
};
|
||||||
|
|||||||
31
src/pre.js
31
src/pre.js
@@ -19,28 +19,30 @@ let processorURL = URL.createObjectURL(new Blob(['(', (() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}).toString(), ')()'], { type : "text/javascript" }))
|
}).toString(), ')()'], { type : "text/javascript" }))
|
||||||
|
|
||||||
Module.cleanUp = () => {
|
Module.cleanUp = () => {
|
||||||
objs.forEach(obj => obj.obj.delete())
|
objs.forEach(obj => obj.obj.delete())
|
||||||
URL.revokeObjectURL(processorURL)
|
URL.revokeObjectURL(processorURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
Module.createTransferer = async (ctx, bufferSize) => {
|
Module.createTransferer = async (ctx, bufferSize) => {
|
||||||
await ctx.audioWorklet.addModule(processorURL)
|
await ctx.audioWorklet.addModule(processorURL)
|
||||||
return new AudioWorkletNode(ctx, "VoskletTransferer", {
|
return new AudioWorkletNode(ctx, "VoskletTransferer", {
|
||||||
channelCountMode : "explicit",
|
channelCountMode : "explicit",
|
||||||
numberOfInputs : 1,
|
numberOfInputs : 1,
|
||||||
numberOfOutputs : 1,
|
numberOfOutputs : 0,
|
||||||
channelCount : 1,
|
channelCount : 1,
|
||||||
processorOptions : { maxCount: bufferSize / 128 }
|
processorOptions : { maxCount: bufferSize / 128 }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getFileHandle(path, create = false) {
|
async function getFileHandle(path, create = false) {
|
||||||
let components = path.split("/")
|
let components = path.split("/")
|
||||||
let prevDir = await navigator.storage.getDirectory()
|
let prevDir = await navigator.storage.getDirectory()
|
||||||
for(let component of components.slice(0, -1)) {
|
for(let component of components.slice(0, -1)) prevDir = await prevDir.getDirectoryHandle(component, { create : create })
|
||||||
prevDir = await prevDir.getDirectoryHandle(component, { create : create })
|
|
||||||
}
|
|
||||||
return prevDir.getFileHandle(components[components.length - 1], { create : create })
|
return prevDir.getFileHandle(components[components.length - 1], { create : create })
|
||||||
}
|
}
|
||||||
|
|
||||||
class genericModel extends EventTarget {
|
class genericModel extends EventTarget {
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
@@ -50,7 +52,10 @@ class genericModel extends EventTarget {
|
|||||||
let mdl = new genericModel()
|
let mdl = new genericModel()
|
||||||
let result = new Promise((resolve, reject) => {
|
let result = new Promise((resolve, reject) => {
|
||||||
mdl.addEventListener("0", ev => {
|
mdl.addEventListener("0", ev => {
|
||||||
if(ev.detail === "0") return resolve(mdl)
|
if(ev.detail == "0") {
|
||||||
|
if(normalMdl) mdl.findWord = (word) => mdl.obj.findWord(word)
|
||||||
|
return resolve(mdl)
|
||||||
|
}
|
||||||
mdl.delete()
|
mdl.delete()
|
||||||
reject(ev.detail)
|
reject(ev.detail)
|
||||||
}, { once : true })
|
}, { once : true })
|
||||||
@@ -60,15 +65,13 @@ class genericModel extends EventTarget {
|
|||||||
try {
|
try {
|
||||||
let dataFile = await (await getFileHandle(storepath + "/model.tgz")).getFile()
|
let dataFile = await (await getFileHandle(storepath + "/model.tgz")).getFile()
|
||||||
let idFile = await (await getFileHandle(storepath + "/id")).getFile()
|
let idFile = await (await getFileHandle(storepath + "/id")).getFile()
|
||||||
if(await idFile.text() !== id) throw ""
|
if(await idFile.text() != id) throw ""
|
||||||
tar = dataFile.stream()
|
tar = dataFile.stream()
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
try {
|
try {
|
||||||
let res = await fetch(url)
|
let res = await fetch(url)
|
||||||
if(!res.ok) {
|
if(!res.ok) throw "Unable to download model"
|
||||||
throw "Unable to download model"
|
|
||||||
}
|
|
||||||
let teedBody = res.body.tee()
|
let teedBody = res.body.tee()
|
||||||
let newDataFile = await (await getFileHandle(storepath + "/model.tgz", true)).createWritable()
|
let newDataFile = await (await getFileHandle(storepath + "/model.tgz", true)).createWritable()
|
||||||
await newDataFile.write(await new Response(teedBody[0]).arrayBuffer())
|
await newDataFile.write(await new Response(teedBody[0]).arrayBuffer())
|
||||||
@@ -79,7 +82,7 @@ class genericModel extends EventTarget {
|
|||||||
tar = teedBody[1]
|
tar = teedBody[1]
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
mdl.obj.delete()
|
mdl.delete()
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,12 +96,15 @@ class genericModel extends EventTarget {
|
|||||||
this.obj.delete()
|
this.obj.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Module.createModel = async (url, storepath, id) => {
|
Module.createModel = async (url, storepath, id) => {
|
||||||
return genericModel.create(url, storepath, id, true)
|
return genericModel.create(url, storepath, id, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
Module.createSpkModel = async (url, storepath, id) => {
|
Module.createSpkModel = async (url, storepath, id) => {
|
||||||
return genericModel.create(url, storepath, id, false)
|
return genericModel.create(url, storepath, id, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
class recognizer extends EventTarget {
|
class recognizer extends EventTarget {
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
@@ -113,7 +119,7 @@ class recognizer extends EventTarget {
|
|||||||
let rec = new recognizer()
|
let rec = new recognizer()
|
||||||
let result = new Promise((resolve, reject) => {
|
let result = new Promise((resolve, reject) => {
|
||||||
rec.addEventListener("0", ev => {
|
rec.addEventListener("0", ev => {
|
||||||
if(ev.detail === "0") return resolve(rec)
|
if(ev.detail == "0") return resolve(rec)
|
||||||
rec.delete()
|
rec.delete()
|
||||||
reject(ev.detail)
|
reject(ev.detail)
|
||||||
}, { once : true })
|
}, { once : true })
|
||||||
@@ -136,12 +142,15 @@ class recognizer extends EventTarget {
|
|||||||
this.obj.pushData(start, audioData.length)
|
this.obj.pushData(start, audioData.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Module.createRecognizer = (model, sampleRate) => {
|
Module.createRecognizer = (model, sampleRate) => {
|
||||||
return recognizer.create(model.obj, sampleRate, 1)
|
return recognizer.create(model.obj, sampleRate, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
Module.createRecognizerWithSpkModel = (model, sampleRate, spkModel) => {
|
Module.createRecognizerWithSpkModel = (model, sampleRate, spkModel) => {
|
||||||
return recognizer.create(model.obj, sampleRate, 2, null, spkModel)
|
return recognizer.create(model.obj, sampleRate, 2, null, spkModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
Module.createRecognizerWithGrm = (model, sampleRate, grammar) => {
|
Module.createRecognizerWithGrm = (model, sampleRate, grammar) => {
|
||||||
return recognizer.create(model.obj, sampleRate, 3, grammar, null)
|
return recognizer.create(model.obj, sampleRate, 3, grammar, null)
|
||||||
}
|
}
|
||||||
@@ -30,21 +30,20 @@ fi
|
|||||||
. $(realpath $EMSDK)/emsdk_env.sh &&
|
. $(realpath $EMSDK)/emsdk_env.sh &&
|
||||||
export PATH=:$PATH:$(realpath $EMSDK)/upstream/bin
|
export PATH=:$PATH:$(realpath $EMSDK)/upstream/bin
|
||||||
|
|
||||||
cd ..
|
|
||||||
KALDI=$(realpath kaldi)
|
KALDI=$(realpath kaldi)
|
||||||
VOSK=$(realpath vosk)
|
VOSK=$(realpath vosk)
|
||||||
OPENFST=$(realpath openfst)
|
OPENFST=$(realpath openfst)
|
||||||
LIBARCHIVE=$(realpath libarchive)
|
LIBARCHIVE=$(realpath libarchive)
|
||||||
CLAPACK_WASM=$(realpath clapack-wasm)
|
CLAPACK_WASM=$(realpath clapack-wasm)
|
||||||
|
|
||||||
cd $(realpath src)
|
cd src &&
|
||||||
MODE=1 && # 0: Ultra debug info, 1: Extremely optimized release, else custom
|
MODE=0 && # 0: Ultra debug info, 1: Optimized release, else custom
|
||||||
echo "Mode = $MODE" &&
|
echo "Mode = $MODE" &&
|
||||||
if [ $MODE = 0 ]; then
|
if [ $MODE = 0 ]; then
|
||||||
em++ -O0 link.cc genericModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sRUNTIME_DEBUG -sSTACK_OVERFLOW_CHECK=2 -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sASSERTIONS=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sDISABLE_EXCEPTION_CATCHING=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sPOLYFILL=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L$OPENFST/lib -l:libfst.a -l:libfstngram.a -L$CLAPACK_WASM -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto --emit-tsd Vosklet.d.ts -fsanitize=undefined -fsanitize=address -fsanitize=leak -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals -g3 --pre-js pre.js -o ../Vosklet.js
|
em++ -O0 link.cc genericModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sRUNTIME_DEBUG -sSTACK_OVERFLOW_CHECK=2 -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sASSERTIONS=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sDISABLE_EXCEPTION_CATCHING=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sPOLYFILL=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L$OPENFST/lib -l:libfst.a -l:libfstngram.a -L$CLAPACK_WASM -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto -fsanitize=undefined -fsanitize=address -fsanitize=leak -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals -g3 --pre-js pre.js -o ../test.js
|
||||||
elif [ $MODE = 1 ]; then
|
elif [ $MODE = 1 ]; then
|
||||||
em++ -O3 link.cc genericModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L$OPENFST/lib -l:libfst.a -l:libfstngram.a -L$CLAPACK_WASM -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js pre.js -o ../Vosklet.js
|
em++ -O3 link.cc genericModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L$OPENFST/lib -l:libfst.a -l:libfstngram.a -L$CLAPACK_WASM -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js pre.js -o ../test.js
|
||||||
else
|
else
|
||||||
em++ -O0 link.cc genericModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L$OPENFST/lib -l:libfst.a -l:libfstngram.a -L$CLAPACK_WASM -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js pre.js -o ../Vosklet.js
|
em++ -O0 link.cc genericModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L$OPENFST/lib -l:libfst.a -l:libfstngram.a -L$CLAPACK_WASM -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js pre.js -o ../test.js
|
||||||
fi
|
fi
|
||||||
rm -f Vosklet.worker.js
|
rm -f Vosklet.worker.js
|
||||||
Reference in New Issue
Block a user