Compare commits

...

6 Commits

Author SHA1 Message Date
Nickolay Shmyrev 8dd2166443 Another timestamp bugfix 2020-06-29 14:11:05 +02:00
Nickolay Shmyrev 7f3f25e170 Release memory when final result is received to reduce memory pressure. 2020-06-24 18:37:53 +02:00
Nickolay Shmyrev f48e4624bf Actually show the distance 2020-06-23 22:14:39 +02:00
Nickolay V. Shmyrev 856c935e92 Merge pull request #153 from He1nr1chK/master
Added cosine distance function
2020-06-23 21:54:47 +03:00
He1nr1chK 444123b37e Merge pull request #1 from He1nr1chK/He1nr1chK-Nodejs
Added cosine distance function
2020-06-23 20:11:22 +02:00
He1nr1chK 1a771e0172 Added cosine distance function 2020-06-23 20:10:14 +02:00
3 changed files with 93 additions and 34 deletions
+71 -28
View File
@@ -1,47 +1,90 @@
#!/usr/bin/env node
const wav = require('wav')
const fs = require('fs')
const fs = require("fs");
const { Readable } = require("stream");
const wav = require("wav");
const { Model, KaldiRecognizer, SpkModel } = require("..");
const {Readable} = require('stream')
const {Model, KaldiRecognizer, SpkModel} = require('..')
try {
fs.accessSync("model", fs.constants.R_OK);
} catch(err) {
console.error("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.");
process.exit(1);
fs.accessSync('model', fs.constants.R_OK)
} catch (err) {
console.error("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.")
process.exit(1)
}
try {
fs.accessSync("model-spk", fs.constants.R_OK);
} catch(err) {
console.error("Please download the speaker model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model-spk' in the current folder.");
process.exit(1);
fs.accessSync('model-spk', fs.constants.R_OK)
} catch (err) {
console.error("Please download the speaker model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model-spk' in the current folder.")
process.exit(1)
}
const wfStream = fs.createReadStream('test.wav', { highWaterMark: 4096 })
const wfReader = new wav.Reader()
const wfStream = fs.createReadStream("test.wav", {'highWaterMark': 4096});
const wfReader = new wav.Reader();
const model = new Model('model')
const spkModel = new SpkModel('model-spk')
const model = new Model("model");
const spkModel = new SpkModel("model-spk");
const spk_sig = [4.658117, 1.277387, 3.346158, -1.473036, -2.15727,
2.461757, 3.76756, -1.241252, 2.333765, 0.642588, -2.848165, 1.229534,
3.907015, 1.726496, -1.188692, 1.16322, -0.668811, -0.623309, 4.628018,
0.407197, 0.089955, 0.920438, 1.47237, -0.311365, -0.437051, -0.531738,
-1.591781, 3.095415, 0.439524, -0.274787, 4.03165, 2.665864, 4.815553,
1.581063, 1.078242, 5.017717, -0.089395, -3.123428, 5.34038, 0.456982,
2.465727, 2.131833, 4.056272, 1.178392, -2.075712, -1.568503, 0.847139,
0.409214, 1.84727, 0.986758, 4.222116, 2.235512, 1.369377, 4.283126,
2.278125, -1.467577, -0.999971, 3.070041, 1.462214, 0.423204, 2.143578,
0.567174, -2.294655, 1.864723, 4.307356, 2.610872, -1.238721, 0.551861,
2.861954, 0.59613, -0.715396, -1.395357, 2.706177, -2.004444, 2.055255,
0.458283, 1.231968, 3.48234, 2.993858, 0.402819, 0.940885, 0.360162,
-2.173674, -2.504609, 0.329541, 3.653913, 3.638025, -1.406409, 2.14059,
1.662765, -0.991323, 0.770921, 0.010094, 3.775469, 1.847511, 2.074432,
-1.928593, 0.807414, 2.964505, 0.128597, 1.297962, 2.645227, 0.136405,
-2.543087, 0.932246, 2.405783, -2.122267, 3.044013, 0.486728, 4.395338,
0.474267, 0.781297, 1.694144, -0.831078, -0.462362, -0.964715, 3.187863,
6.008708, 1.725954, 3.667886, -1.467623, 3.370667, 2.72555, -0.796541,
2.416543, 0.675401, -0.737634, -1.709676]
function dotp(x, y) {
function dotp_sum(a, b) {
return a + b
}
function dotp_times(a, i) {
return x[i] * y[i]
}
return x.map(dotp_times).reduce(dotp_sum, 0)
}
function cosineSimilarity(A, B) {
var similarity =
dotp(A, B) / (Math.sqrt(dotp(A, A)) * Math.sqrt(dotp(B, B)))
return similarity
}
function cosine_dist(x, y) {
return 1 - cosineSimilarity(x, y)
}
wfReader.on('format', async ({ audioFormat, sampleRate, channels }) => {
if (audioFormat != 1 || channels != 1) {
console.error("Audio file must be WAV format mono PCM.");
process.exit(1);
console.error('Audio file must be WAV format mono PCM.')
process.exit(1)
}
const rec = new KaldiRecognizer(model, spkModel, sampleRate);
const rec = new KaldiRecognizer(model, spkModel, sampleRate)
for await (const data of new Readable().wrap(wfReader)) {
const result = await rec.AcceptWaveform(data);
if (result != 0) {
console.log(await rec.Result());
const endOfSpeech = await rec.AcceptWaveform(data)
if (endOfSpeech) {
res = await JSON.parse(rec.Result());
console.log(res)
console.log('X-vector:', JSON.stringify(res['spk']))
console.log('Speaker distance:', cosine_dist(spk_sig, res['spk']))
} else {
console.log(await rec.PartialResult());
console.log(await rec.PartialResult())
}
}
console.log(await rec.FinalResult());
});
res = await JSON.parse(rec.FinalResult());
console.log(res)
console.log('X-vector:', JSON.stringify(res['spk']))
console.log('Speaker distance:', cosine_dist(spk_sig, res['spk']))
})
wfStream.pipe(wfReader);
wfStream.pipe(wfReader)
+1 -1
View File
@@ -73,7 +73,7 @@ vosk_ext = Extension('vosk._vosk',
setuptools.setup(
name="vosk", # Replace with your own username
version="0.3.9",
version="0.3.10",
author="Alpha Cephei Inc",
author_email="contact@alphacephei.com",
description="API for Kaldi and Vosk",
+21 -5
View File
@@ -125,9 +125,9 @@ KaldiRecognizer::KaldiRecognizer(Model *model, SpkModel *spk_model, float sample
}
KaldiRecognizer::~KaldiRecognizer() {
delete decoder_;
delete feature_pipeline_;
delete silence_weighting_;
delete decoder_;
delete g_fst_;
delete decode_fst_;
delete spk_feature_;
@@ -164,12 +164,13 @@ void KaldiRecognizer::CleanUp()
delete silence_weighting_;
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_->trans_model_, model_->feature_info_.silence_weighting_config, 3);
if (spk_feature_) {
if (spk_model_) {
delete spk_feature_;
spk_feature_ = new OnlineMfcc(spk_model_->spkvector_mfcc_opts);
}
frame_offset_ += decoder_->NumFramesDecoded();
if (decoder_)
frame_offset_ += decoder_->NumFramesDecoded();
// Each 10 minutes we drop the pipeline to save frontend memory in continuous processing
// here we drop few frames remaining in the feature pipeline but hope it will not
@@ -177,8 +178,9 @@ void KaldiRecognizer::CleanUp()
// Also restart if we retrieved final result already
if (frame_offset_ > 20000 || state_ == RECOGNIZER_FINALIZED) {
if (decoder_ == NULL || state_ == RECOGNIZER_FINALIZED || frame_offset_ > 20000) {
samples_round_start_ += samples_processed_;
samples_processed_ = 0;
frame_offset_ = 0;
delete decoder_;
@@ -454,7 +456,21 @@ const char* KaldiRecognizer::FinalResult()
decoder_->AdvanceDecoding();
decoder_->FinalizeDecoding();
state_ = RECOGNIZER_FINALIZED;
return GetResult();
GetResult();
// Free some memory while we are finalized, next
// iteration will reinitialize them anyway
delete decoder_;
delete feature_pipeline_;
delete silence_weighting_;
delete spk_feature_;
feature_pipeline_ = NULL;
silence_weighting_ = NULL;
decoder_ = NULL;
spk_feature_ = NULL;
return last_result_.c_str();
}
// Store result in recognizer and return as const string