Merge pull request #31 from arbdevml/main

Updated documentaion and added a example of x-vector (voice fingerprint)
This commit is contained in:
msqr1
2025-09-21 22:50:14 -07:00
committed by GitHub
2 changed files with 96 additions and 2 deletions

View File

@@ -9,7 +9,7 @@
| 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 ```.tar.gz```/```.tgz``` format. Tar format must be USTAR. 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<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 ```.tar.gz```/```.tgz``` format. Tar format must be USTAR. 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``` | | ```Promise<Recognizer> createRecognizer(model: Model, sampleRate: float)```<br><br>```Promise<Recognizer> createRecognizerWithSpkModel(model: Model, sampleRate: float, spkModel: spkModel)```<br><br>```Promise<Recognizer> createRecognizerWithGrm(model: Model, grammar: string, sampleRate: float)``` | Create a ```Recognizer``` |
| ```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 | | ```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 no 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```. |
| ```Promise<void> cleanUp()``` | A convenience function that call ```delete()``` on all objects and revoke all URLs. **Run this when you're done!** | | ```Promise<void> cleanUp()``` | A convenience function that call ```delete()``` on all objects and revoke all URLs. **Run this when you're done!** |
@@ -74,4 +74,4 @@ cd Vosklet/src &&
| INITIAL_MEMORY | Set inital memory, valid suffixes: kb, mb, gb, tb or none (bytes) | ```315mb``` as [recommended](https://alphacephei.com/vosk/models) plus a bit of leeway. This memory will grow if usage exceeds this value. | | INITIAL_MEMORY | Set inital memory, valid suffixes: kb, mb, gb, tb or none (bytes) | ```315mb``` as [recommended](https://alphacephei.com/vosk/models) plus a bit of leeway. This memory will grow if usage exceeds this value. |
| MAX_THREADS | Set the max number of threads (>=1), this should be equal to the number of recognizers used in the program | ```1``` | | MAX_THREADS | Set the max number of threads (>=1), this should be equal to the number of recognizers used in the program | ```1``` |
| 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``` |

94
Examples/x-vector.html Normal file
View File

@@ -0,0 +1,94 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/gh/msqr1/Vosklet@1.2.1/Examples/Vosklet.js" async defer></script>
<script>
async function start() {
console.log("Starting speech recognition...");
let ctx = new AudioContext({sinkId: {type: "none"}});
let micNode = ctx.createMediaStreamSource(await navigator.mediaDevices.getUserMedia({
video: false,
audio: {
echoCancellation: true,
noiseSuppression: true,
channelCount: 1
},
}));
console.log("Microphone connected.");
let module;
try {
module = await loadVosklet();
console.log("Vosklet module loaded.");
} catch (error) {
console.error("Error loading Vosklet module:", error);
return;
}
let model;
try {
model = await module.createModel(
"https://ccoreilly.github.io/vosk-browser/models/vosk-model-small-en-us-0.15.tar.gz",
"English",
"vosk-model-small-en-us-0.15"
);
console.log("Speech recognition model loaded.");
} catch (error) {
console.error("Error loading speech recognition model:", error);
return;
}
let spkModel;
try {
spkModel = await module.createSpkModel(
"https://arbdevml.github.io/x-vector/vosk-model-spk-0.4.tar.gz",
"vosk-model-spk-0.4",
"vosk-model-spk-0.4"
);
console.log("Speaker identification model loaded.");
} catch (error) {
console.error("Error loading speaker identification model:", error);
return;
}
let recognizer;
try {
recognizer = await module.createRecognizerWithSpkModel(model, ctx.sampleRate, spkModel);
console.log("Recognizer with speaker model created.");
} catch (error) {
console.error("Error creating recognizer with speaker model:", error);
return;
}
recognizer.addEventListener("result", ev => {
const result = JSON.parse(ev.detail);
console.log("typeof ev.detail:", typeof ev.detail);
console.log("typeof result:", typeof result);
console.log("Speech recognized:", result);
console.log("spk:", result.spk);
console.log("ev:", ev);
});
recognizer.addEventListener("partialResult", ev => {
console.log("Partial result:", ev.detail);
});
let transferer;
try {
transferer = await module.createTransferer(ctx, 128 * 150);
console.log("Transferer created.");
} catch (error) {
console.error("Error creating transferer:", error);
return;
}
transferer.port.onmessage = ev => recognizer.acceptWaveform(ev.data);
micNode.connect(transferer);
console.log("Microphone data connected to Vosklet.");
}
</script>
</head>
<body>
<button onclick="start()">Start</button>
</body>
</html>