Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c562e15a4 | |||
| 5bcdf454ec | |||
| 4ccdda44ac | |||
| 5e46825474 | |||
| fcab5a9581 | |||
| e7f5e0ac23 | |||
| 9a3906831b | |||
| 195db43b9e | |||
| 332553ec1e | |||
| 646af3f652 | |||
| f24ac65fcb | |||
| 14312c93f9 | |||
| 4346d4155d | |||
| 7790ac5040 |
@@ -105,7 +105,7 @@ make install
|
||||
|
||||
# Kaldi itself
|
||||
cd $WORKDIR
|
||||
git clone -b android-mix --single-branch https://github.com/alphacep/kaldi
|
||||
git clone -b vosk-android --single-branch https://github.com/alphacep/kaldi
|
||||
cd $WORKDIR/kaldi/src
|
||||
CXX=$CXX CXXFLAGS="$ARCHFLAGS -O3 -DFST_NO_DYNAMIC_LINKING" ./configure --use-cuda=no \
|
||||
--mathlib=OPENBLAS_CLAPACK --shared \
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Vosk" Version="0.3.30" />
|
||||
<PackageReference Include="Vosk" Version="0.3.31" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package>
|
||||
<metadata>
|
||||
<id>Vosk</id>
|
||||
<version>0.3.30</version>
|
||||
<version>0.3.32</version>
|
||||
<authors>Alpha Cephei Inc</authors>
|
||||
<owners>Alpha Cephei Inc</owners>
|
||||
<license type="expression">Apache-2.0</license>
|
||||
|
||||
@@ -21,13 +21,8 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
spkModel, err := vosk.NewSpkModel("model-spk")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
sampleRate := 16000.0
|
||||
rec, err := vosk.NewRecognizer(model, sampleRate, spkModel)
|
||||
rec, err := vosk.NewRecognizer(model, sampleRate)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -39,12 +34,6 @@ func main() {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
reader := bufio.NewReader(file)
|
||||
buf := make([]byte, 4096)
|
||||
|
||||
|
||||
+13
-1
@@ -18,6 +18,10 @@ func NewModel(modelPath string) (*VoskModel, error) {
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func (m *VoskModel) Free() {
|
||||
C.vosk_model_free(m.model)
|
||||
}
|
||||
|
||||
func freeModel(model *VoskModel) {
|
||||
C.vosk_model_free(model.model)
|
||||
}
|
||||
@@ -48,6 +52,10 @@ func freeSpkModel(model *VoskSpkModel) {
|
||||
C.vosk_spk_model_free(model.spkModel)
|
||||
}
|
||||
|
||||
func(s *VoskSpkModel) Free() {
|
||||
C.vosk_spk_model_free(s.spkModel)
|
||||
}
|
||||
|
||||
// VoskRecognizer contains a reference to the C VoskRecognizer
|
||||
type VoskRecognizer struct {
|
||||
rec *C.struct_VoskRecognizer
|
||||
@@ -57,6 +65,10 @@ func freeRecognizer(recognizer *VoskRecognizer) {
|
||||
C.vosk_recognizer_free(recognizer.rec)
|
||||
}
|
||||
|
||||
func (r *VoskRecognizer) Free() {
|
||||
C.vosk_recognizer_free(r.rec)
|
||||
}
|
||||
|
||||
// NewRecognizer creates a new VoskRecognizer instance
|
||||
func NewRecognizer(model *VoskModel, sampleRate float64) (*VoskRecognizer, error) {
|
||||
internal := C.vosk_recognizer_new(model.model, C.float(sampleRate))
|
||||
@@ -110,7 +122,7 @@ func (r *VoskRecognizer) Result() []byte {
|
||||
|
||||
// PartialResult returns a partial speech recognition result.
|
||||
func (r *VoskRecognizer) PartialResult() []byte {
|
||||
return []byte(C.GoString(C.vosk_recognizer_result(r.rec)))
|
||||
return []byte(C.GoString(C.vosk_recognizer_partial_result(r.rec)))
|
||||
}
|
||||
|
||||
// FinalResult returns a speech recognition result. Same as result, but doesn't wait
|
||||
|
||||
@@ -15,5 +15,5 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation group: 'net.java.dev.jna', name: 'jna', version: '5.7.0'
|
||||
implementation group: 'com.alphacephei', name: 'vosk', version: '0.3.30+'
|
||||
implementation group: 'com.alphacephei', name: 'vosk', version: '0.3.32+'
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
archivesBaseName = 'vosk'
|
||||
group = 'com.alphacephei'
|
||||
version = '0.3.30'
|
||||
version = '0.3.32'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package org.vosk;
|
||||
|
||||
import java.io.IOException;
|
||||
import com.sun.jna.PointerType;
|
||||
|
||||
public class Model extends PointerType implements AutoCloseable {
|
||||
public Model() {
|
||||
}
|
||||
|
||||
public Model(String path) {
|
||||
public Model(String path) throws IOException {
|
||||
super(LibVosk.vosk_model_new(path));
|
||||
|
||||
if (getPointer() == null) {
|
||||
throw new IOException("Failed to create a model");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package org.vosk;
|
||||
|
||||
import com.sun.jna.PointerType;
|
||||
import java.io.IOException;
|
||||
|
||||
public class Recognizer extends PointerType implements AutoCloseable {
|
||||
public Recognizer(Model model, float sampleRate) {
|
||||
public Recognizer(Model model, float sampleRate) throws IOException {
|
||||
super(LibVosk.vosk_recognizer_new(model, sampleRate));
|
||||
|
||||
if (getPointer() == null) {
|
||||
throw new IOException("Failed to create a recognizer");
|
||||
}
|
||||
}
|
||||
|
||||
public Recognizer(Model model, float sampleRate, SpeakerModel spkModel) {
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package org.vosk;
|
||||
|
||||
import com.sun.jna.PointerType;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SpeakerModel extends PointerType implements AutoCloseable {
|
||||
public SpeakerModel() {
|
||||
}
|
||||
|
||||
public SpeakerModel(String path) {
|
||||
public SpeakerModel(String path) throws IOException {
|
||||
super(LibVosk.vosk_spk_model_new(path));
|
||||
|
||||
if (getPointer() == null) {
|
||||
throw new IOException("Failed to create a speaker model");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -93,4 +93,10 @@ public class DecoderTest {
|
||||
}
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void decoderTestException() throws IOException {
|
||||
Model model = new Model("model_missing");
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vosk",
|
||||
"version": "0.3.30",
|
||||
"version": "0.3.32",
|
||||
"description": "Node binding for continuous offline voice recoginition with Vosk library.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ with open("README.md", "r") as fh:
|
||||
|
||||
setuptools.setup(
|
||||
name="vosk",
|
||||
version="0.3.31",
|
||||
version="0.3.32",
|
||||
author="Alpha Cephei Inc",
|
||||
author_email="contact@alphacephei.com",
|
||||
description="Offline open source speech recognition API based on Kaldi and Vosk",
|
||||
|
||||
+13
-1
@@ -25,6 +25,9 @@ class Model(object):
|
||||
def __init__(self, model_path):
|
||||
self._handle = _c.vosk_model_new(model_path.encode('utf-8'))
|
||||
|
||||
if self._handle == _ffi.NULL:
|
||||
raise Exception("Failed to create a model")
|
||||
|
||||
def __del__(self):
|
||||
_c.vosk_model_free(self._handle)
|
||||
|
||||
@@ -36,6 +39,9 @@ class SpkModel(object):
|
||||
def __init__(self, model_path):
|
||||
self._handle = _c.vosk_spk_model_new(model_path.encode('utf-8'))
|
||||
|
||||
if self._handle == _ffi.NULL:
|
||||
raise Exception("Failed to create a speaker model")
|
||||
|
||||
def __del__(self):
|
||||
_c.vosk_spk_model_free(self._handle)
|
||||
|
||||
@@ -51,6 +57,9 @@ class KaldiRecognizer(object):
|
||||
else:
|
||||
raise TypeError("Unknown arguments")
|
||||
|
||||
if self._handle == _ffi.NULL:
|
||||
raise Exception("Failed to create a recognizer")
|
||||
|
||||
def __del__(self):
|
||||
_c.vosk_recognizer_free(self._handle)
|
||||
|
||||
@@ -64,7 +73,10 @@ class KaldiRecognizer(object):
|
||||
_c.vosk_recognizer_set_spk_model(self._handle, spk_model._handle)
|
||||
|
||||
def AcceptWaveform(self, data):
|
||||
return _c.vosk_recognizer_accept_waveform(self._handle, data, len(data))
|
||||
res = _c.vosk_recognizer_accept_waveform(self._handle, data, len(data))
|
||||
if res < 0:
|
||||
raise Exception("Failed to process waveform")
|
||||
return res
|
||||
|
||||
def Result(self):
|
||||
return _ffi.string(_c.vosk_recognizer_result(self._handle)).decode('utf-8')
|
||||
|
||||
+8
-1
@@ -23,6 +23,13 @@ VOSK_SOURCES= \
|
||||
spk_model.cc \
|
||||
vosk_api.cc
|
||||
|
||||
VOSK_HEADERS= \
|
||||
kaldi_recognizer.h \
|
||||
language_model.h \
|
||||
model.h \
|
||||
spk_model.h \
|
||||
vosk_api.h
|
||||
|
||||
CFLAGS=-g -O3 -std=c++17 -fPIC -DFST_NO_DYNAMIC_LINKING \
|
||||
-I. -I$(KALDI_ROOT)/src -I$(OPENFST_ROOT)/include $(EXTRA_CFLAGS)
|
||||
|
||||
@@ -76,7 +83,7 @@ all: libvosk.$(EXT)
|
||||
libvosk.$(EXT): $(VOSK_SOURCES:.cc=.o)
|
||||
$(CXX) --shared -s -o $@ $^ $(LIBS) -lm -latomic $(EXTRA_LDFLAGS)
|
||||
|
||||
%.o: %.cc
|
||||
%.o: %.cc $(VOSK_HEADERS)
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
|
||||
+33
-23
@@ -143,11 +143,10 @@ KaldiRecognizer::~KaldiRecognizer() {
|
||||
delete decode_fst_;
|
||||
delete spk_feature_;
|
||||
|
||||
delete rnnlm_info_;
|
||||
delete lm_to_subtract_;
|
||||
delete lm_to_subtract_scale_;
|
||||
delete carpa_to_add_;
|
||||
delete carpa_to_add_scale_;
|
||||
delete rnnlm_info_;
|
||||
delete rnnlm_to_add_;
|
||||
delete rnnlm_to_add_scale_;
|
||||
|
||||
@@ -168,8 +167,12 @@ void KaldiRecognizer::InitState()
|
||||
void KaldiRecognizer::InitRescoring()
|
||||
{
|
||||
if (model_->graph_lm_fst_) {
|
||||
lm_to_subtract_ = new fst::BackoffDeterministicOnDemandFst<StdArc>(*model_->graph_lm_fst_);
|
||||
lm_to_subtract_scale_ = new fst::ScaleDeterministicOnDemandFst(-1.0, lm_to_subtract_);
|
||||
|
||||
fst::CacheOptions cache_opts(true, -1);
|
||||
fst::ArcMapFstOptions mapfst_opts(cache_opts);
|
||||
fst::StdToLatticeMapper<BaseFloat> mapper;
|
||||
|
||||
lm_to_subtract_ = new fst::ArcMapFst<fst::StdArc, LatticeArc, fst::StdToLatticeMapper<BaseFloat> >(*model_->graph_lm_fst_, mapper, mapfst_opts);
|
||||
carpa_to_add_ = new ConstArpaLmDeterministicFst(model_->const_arpa_);
|
||||
|
||||
if (model_->rnnlm_enabled_) {
|
||||
@@ -535,11 +538,12 @@ const char *KaldiRecognizer::NbestResult(CompactLattice &clat)
|
||||
for (int k = 0; k < nbest_lats.size(); k++) {
|
||||
|
||||
Lattice nlat = nbest_lats[k];
|
||||
RmEpsilon(&nlat);
|
||||
CompactLattice nclat;
|
||||
CompactLattice aligned_nclat;
|
||||
ConvertLattice(nlat, &nclat);
|
||||
|
||||
CompactLattice nclat;
|
||||
fst::Invert(&nlat);
|
||||
DeterminizeLattice(nlat, &nclat);
|
||||
|
||||
CompactLattice aligned_nclat;
|
||||
if (model_->winfo_) {
|
||||
WordAlignLattice(nclat, *model_->trans_model_, *model_->winfo_, 0, &aligned_nclat);
|
||||
} else {
|
||||
@@ -586,34 +590,40 @@ const char* KaldiRecognizer::GetResult()
|
||||
return StoreEmptyReturn();
|
||||
}
|
||||
|
||||
kaldi::CompactLattice clat;
|
||||
kaldi::CompactLattice rlat;
|
||||
// Original from decoder, subtracted graph weight, rescored with carpa, rescored with rnnlm
|
||||
CompactLattice clat, slat, tlat, rlat;
|
||||
|
||||
decoder_->GetLattice(true, &clat);
|
||||
|
||||
if (lm_to_subtract_scale_ && carpa_to_add_) {
|
||||
TopSortCompactLatticeIfNeeded(&clat);
|
||||
CompactLattice tlat;
|
||||
fst::ComposeDeterministicOnDemandFst<StdArc> combined_lm(lm_to_subtract_scale_, carpa_to_add_);
|
||||
ComposeCompactLatticeDeterministic(clat, &combined_lm, &tlat);
|
||||
if (lm_to_subtract_ && carpa_to_add_) {
|
||||
Lattice lat, composed_lat;
|
||||
|
||||
// Delete old score
|
||||
ConvertLattice(clat, &lat);
|
||||
fst::ScaleLattice(fst::GraphLatticeScale(-1.0), &lat);
|
||||
fst::Compose(lat, *lm_to_subtract_, &composed_lat);
|
||||
fst::Invert(&composed_lat);
|
||||
DeterminizeLattice(composed_lat, &slat);
|
||||
fst::ScaleLattice(fst::GraphLatticeScale(-1.0), &slat);
|
||||
|
||||
// Add CARPA score
|
||||
TopSortCompactLatticeIfNeeded(&slat);
|
||||
ComposeCompactLatticeDeterministic(slat, carpa_to_add_, &tlat);
|
||||
|
||||
// Rescore with RNNLM score on top if needed
|
||||
if (rnnlm_to_add_scale_) {
|
||||
ComposeLatticePrunedOptions compose_opts;
|
||||
compose_opts.lattice_compose_beam = 3.0;
|
||||
compose_opts.max_arcs = 3000;
|
||||
TopSortCompactLatticeIfNeeded(&tlat);
|
||||
fst::ComposeDeterministicOnDemandFst<StdArc> combined_rnnlm(carpa_to_add_scale_, rnnlm_to_add_scale_);
|
||||
|
||||
TopSortCompactLatticeIfNeeded(&tlat);
|
||||
ComposeCompactLatticePruned(compose_opts, tlat,
|
||||
&combined_rnnlm, &rlat);
|
||||
rnnlm_to_add_->Clear();
|
||||
} else {
|
||||
rlat = tlat;
|
||||
}
|
||||
|
||||
kaldi::Lattice slat;
|
||||
ConvertLattice(rlat, &slat);
|
||||
fst::Invert(&slat);
|
||||
DeterminizeLattice(slat, &rlat);
|
||||
|
||||
} else {
|
||||
rlat = clat;
|
||||
}
|
||||
@@ -642,7 +652,7 @@ const char* KaldiRecognizer::PartialResult()
|
||||
return StoreReturn(res.dump());
|
||||
}
|
||||
|
||||
kaldi::Lattice lat;
|
||||
Lattice lat;
|
||||
decoder_->GetBestPath(false, &lat);
|
||||
vector<kaldi::int32> alignment, words;
|
||||
LatticeWeight weight;
|
||||
|
||||
@@ -82,11 +82,9 @@ class KaldiRecognizer {
|
||||
OnlineBaseFeature *spk_feature_ = nullptr;
|
||||
|
||||
// Rescoring
|
||||
fst::BackoffDeterministicOnDemandFst<fst::StdArc> *lm_to_subtract_ = nullptr;
|
||||
fst::ScaleDeterministicOnDemandFst *lm_to_subtract_scale_ = nullptr;
|
||||
fst::ArcMapFst<fst::StdArc, LatticeArc, fst::StdToLatticeMapper<BaseFloat> > *lm_to_subtract_ = nullptr;
|
||||
kaldi::ConstArpaLmDeterministicFst *carpa_to_add_ = nullptr;
|
||||
fst::ScaleDeterministicOnDemandFst *carpa_to_add_scale_ = nullptr;
|
||||
|
||||
// RNNLM rescoring
|
||||
kaldi::rnnlm::KaldiRnnlmDeterministicFst* rnnlm_to_add_ = nullptr;
|
||||
fst::DeterministicOnDemandFst<fst::StdArc> *rnnlm_to_add_scale_ = nullptr;
|
||||
|
||||
+15
-5
@@ -109,10 +109,10 @@ Model::Model(const char *model_path) : model_path_str_(model_path) {
|
||||
|
||||
struct stat buffer;
|
||||
string am_v2_path = model_path_str_ + "/am/final.mdl";
|
||||
string mfcc_v2_path = model_path_str_ + "/conf/mfcc.conf";
|
||||
string model_conf_v2_path = model_path_str_ + "/conf/model.conf";
|
||||
string am_v1_path = model_path_str_ + "/final.mdl";
|
||||
string mfcc_v1_path = model_path_str_ + "/mfcc.conf";
|
||||
if (stat(am_v2_path.c_str(), &buffer) == 0 && stat(mfcc_v2_path.c_str(), &buffer) == 0) {
|
||||
if (stat(am_v2_path.c_str(), &buffer) == 0 && stat(model_conf_v2_path.c_str(), &buffer) == 0) {
|
||||
ConfigureV2();
|
||||
ReadDataFiles();
|
||||
} else if (stat(am_v1_path.c_str(), &buffer) == 0 && stat(mfcc_v1_path.c_str(), &buffer) == 0) {
|
||||
@@ -168,6 +168,7 @@ void Model::ConfigureV1()
|
||||
std_fst_rxfilename_ = model_path_str_ + "/rescore/G.fst";
|
||||
final_ie_rxfilename_ = model_path_str_ + "/ivector/final.ie";
|
||||
mfcc_conf_rxfilename_ = model_path_str_ + "/mfcc.conf";
|
||||
fbank_conf_rxfilename_ = model_path_str_ + "/fbank.conf";
|
||||
global_cmvn_stats_rxfilename_ = model_path_str_ + "/global_cmvn.stats";
|
||||
pitch_conf_rxfilename_ = model_path_str_ + "/pitch.conf";
|
||||
rnnlm_word_feats_rxfilename_ = model_path_str_ + "/rnnlm/word_feats.txt";
|
||||
@@ -196,6 +197,7 @@ void Model::ConfigureV2()
|
||||
std_fst_rxfilename_ = model_path_str_ + "/rescore/G.fst";
|
||||
final_ie_rxfilename_ = model_path_str_ + "/ivector/final.ie";
|
||||
mfcc_conf_rxfilename_ = model_path_str_ + "/conf/mfcc.conf";
|
||||
fbank_conf_rxfilename_ = model_path_str_ + "/conf/fbank.conf";
|
||||
global_cmvn_stats_rxfilename_ = model_path_str_ + "/am/global_cmvn.stats";
|
||||
pitch_conf_rxfilename_ = model_path_str_ + "/conf/pitch.conf";
|
||||
rnnlm_word_feats_rxfilename_ = model_path_str_ + "/rnnlm/word_feats.txt";
|
||||
@@ -213,9 +215,17 @@ void Model::ReadDataFiles()
|
||||
" lattice-beam=" << nnet3_decoding_config_.lattice_beam;
|
||||
KALDI_LOG << "Silence phones " << endpoint_config_.silence_phones;
|
||||
|
||||
feature_info_.feature_type = "mfcc";
|
||||
ReadConfigFromFile(mfcc_conf_rxfilename_, &feature_info_.mfcc_opts);
|
||||
feature_info_.mfcc_opts.frame_opts.allow_downsample = true; // It is safe to downsample
|
||||
if (stat(mfcc_conf_rxfilename_.c_str(), &buffer) == 0) {
|
||||
feature_info_.feature_type = "mfcc";
|
||||
ReadConfigFromFile(mfcc_conf_rxfilename_, &feature_info_.mfcc_opts);
|
||||
feature_info_.mfcc_opts.frame_opts.allow_downsample = true; // It is safe to downsample
|
||||
} else if (stat(fbank_conf_rxfilename_.c_str(), &buffer) == 0) {
|
||||
feature_info_.feature_type = "fbank";
|
||||
ReadConfigFromFile(fbank_conf_rxfilename_, &feature_info_.fbank_opts);
|
||||
feature_info_.fbank_opts.frame_opts.allow_downsample = true; // It is safe to downsample
|
||||
} else {
|
||||
KALDI_ERR << "Failed to find feature config file";
|
||||
}
|
||||
|
||||
feature_info_.silence_weighting_config.silence_weight = 1e-3;
|
||||
feature_info_.silence_weighting_config.silence_phones_str = endpoint_config_.silence_phones;
|
||||
|
||||
@@ -66,6 +66,7 @@ protected:
|
||||
string std_fst_rxfilename_;
|
||||
string final_ie_rxfilename_;
|
||||
string mfcc_conf_rxfilename_;
|
||||
string fbank_conf_rxfilename_;
|
||||
string global_cmvn_stats_rxfilename_;
|
||||
string pitch_conf_rxfilename_;
|
||||
|
||||
|
||||
+49
-8
@@ -27,11 +27,18 @@ using namespace kaldi;
|
||||
|
||||
VoskModel *vosk_model_new(const char *model_path)
|
||||
{
|
||||
return (VoskModel *)new Model(model_path);
|
||||
try {
|
||||
return (VoskModel *)new Model(model_path);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void vosk_model_free(VoskModel *model)
|
||||
{
|
||||
if (model == nullptr) {
|
||||
return;
|
||||
}
|
||||
((Model *)model)->Unref();
|
||||
}
|
||||
|
||||
@@ -42,27 +49,46 @@ int vosk_model_find_word(VoskModel *model, const char *word)
|
||||
|
||||
VoskSpkModel *vosk_spk_model_new(const char *model_path)
|
||||
{
|
||||
return (VoskSpkModel *)new SpkModel(model_path);
|
||||
try {
|
||||
return (VoskSpkModel *)new SpkModel(model_path);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void vosk_spk_model_free(VoskSpkModel *model)
|
||||
{
|
||||
if (model == nullptr) {
|
||||
return;
|
||||
}
|
||||
((SpkModel *)model)->Unref();
|
||||
}
|
||||
|
||||
VoskRecognizer *vosk_recognizer_new(VoskModel *model, float sample_rate)
|
||||
{
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate);
|
||||
try {
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, float sample_rate, VoskSpkModel *spk_model)
|
||||
{
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate, (SpkModel *)spk_model);
|
||||
try {
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate, (SpkModel *)spk_model);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VoskRecognizer *vosk_recognizer_new_grm(VoskModel *model, float sample_rate, const char *grammar)
|
||||
{
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate, grammar);
|
||||
try {
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate, grammar);
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void vosk_recognizer_set_max_alternatives(VoskRecognizer *recognizer, int max_alternatives)
|
||||
@@ -77,22 +103,37 @@ void vosk_recognizer_set_words(VoskRecognizer *recognizer, int words)
|
||||
|
||||
void vosk_recognizer_set_spk_model(VoskRecognizer *recognizer, VoskSpkModel *spk_model)
|
||||
{
|
||||
if (recognizer == nullptr || spk_model == nullptr) {
|
||||
return;
|
||||
}
|
||||
((KaldiRecognizer *)recognizer)->SetSpkModel((SpkModel *)spk_model);
|
||||
}
|
||||
|
||||
int vosk_recognizer_accept_waveform(VoskRecognizer *recognizer, const char *data, int length)
|
||||
{
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
try {
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
} catch (...) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int vosk_recognizer_accept_waveform_s(VoskRecognizer *recognizer, const short *data, int length)
|
||||
{
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
try {
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
} catch (...) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int vosk_recognizer_accept_waveform_f(VoskRecognizer *recognizer, const float *data, int length)
|
||||
{
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
try {
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
} catch (...) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *vosk_recognizer_result(VoskRecognizer *recognizer)
|
||||
|
||||
+24
-10
@@ -43,7 +43,7 @@ typedef struct VoskRecognizer VoskRecognizer;
|
||||
/** Loads model data from the file and returns the model object
|
||||
*
|
||||
* @param model_path: the path of the model on the filesystem
|
||||
@ @returns model object */
|
||||
* @returns model object or NULL if problem occured */
|
||||
VoskModel *vosk_model_new(const char *model_path);
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ int vosk_model_find_word(VoskModel *model, const char *word);
|
||||
/** Loads speaker model data from the file and returns the model object
|
||||
*
|
||||
* @param model_path: the path of the model on the filesystem
|
||||
* @returns model object */
|
||||
* @returns model object or NULL if problem occured */
|
||||
VoskSpkModel *vosk_spk_model_new(const char *model_path);
|
||||
|
||||
|
||||
@@ -79,9 +79,13 @@ void vosk_spk_model_free(VoskSpkModel *model);
|
||||
|
||||
/** Creates the recognizer object
|
||||
*
|
||||
* The recognizers process the speech and return text using shared model data
|
||||
* @param sample_rate The sample rate of the audio you going to feed into the recognizer
|
||||
* @returns recognizer object */
|
||||
* The recognizers process the speech and return text using shared model data
|
||||
* @param model VoskModel containing static data for recognizer. Model can be
|
||||
* shared across recognizers, even running in different threads.
|
||||
* @param sample_rate The sample rate of the audio you going to feed into the recognizer.
|
||||
* Make sure this rate matches the audio content, it is a common
|
||||
* issue causing accuracy problems.
|
||||
* @returns recognizer object or NULL if problem occured */
|
||||
VoskRecognizer *vosk_recognizer_new(VoskModel *model, float sample_rate);
|
||||
|
||||
|
||||
@@ -90,9 +94,13 @@ VoskRecognizer *vosk_recognizer_new(VoskModel *model, float sample_rate);
|
||||
* With the speaker recognition mode the recognizer not just recognize
|
||||
* text but also return speaker vectors one can use for speaker identification
|
||||
*
|
||||
* @param sample_rate The sample rate of the audio you going to feed into the recognizer
|
||||
* @param model VoskModel containing static data for recognizer. Model can be
|
||||
* shared across recognizers, even running in different threads.
|
||||
* @param sample_rate The sample rate of the audio you going to feed into the recognizer.
|
||||
* Make sure this rate matches the audio content, it is a common
|
||||
* issue causing accuracy problems.
|
||||
* @param spk_model speaker model for speaker identification
|
||||
* @returns recognizer object */
|
||||
* @returns recognizer object or NULL if problem occured */
|
||||
VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, float sample_rate, VoskSpkModel *spk_model);
|
||||
|
||||
|
||||
@@ -106,11 +114,15 @@ VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, float sample_rate, Vos
|
||||
* Only recognizers with lookahead models support this type of quick configuration.
|
||||
* Precompiled HCLG graph models are not supported.
|
||||
*
|
||||
* @param sample_rate The sample rate of the audio you going to feed into the recognizer
|
||||
* @param model VoskModel containing static data for recognizer. Model can be
|
||||
* shared across recognizers, even running in different threads.
|
||||
* @param sample_rate The sample rate of the audio you going to feed into the recognizer.
|
||||
* Make sure this rate matches the audio content, it is a common
|
||||
* issue causing accuracy problems.
|
||||
* @param grammar The string with the list of phrases to recognize as JSON array of strings,
|
||||
* for example "["one two three four five", "[unk]"]".
|
||||
*
|
||||
* @returns recognizer object */
|
||||
* @returns recognizer object or NULL if problem occured */
|
||||
VoskRecognizer *vosk_recognizer_new_grm(VoskModel *model, float sample_rate, const char *grammar);
|
||||
|
||||
|
||||
@@ -181,7 +193,9 @@ void vosk_recognizer_set_words(VoskRecognizer *recognizer, int words);
|
||||
*
|
||||
* @param data - audio data in PCM 16-bit mono format
|
||||
* @param length - length of the audio data
|
||||
* @returns true if silence is occured and you can retrieve a new utterance with result method */
|
||||
* @returns 1 if silence is occured and you can retrieve a new utterance with result method
|
||||
* 0 if decoding continues
|
||||
* -1 if exception occured */
|
||||
int vosk_recognizer_accept_waveform(VoskRecognizer *recognizer, const char *data, int length);
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ RUN apt-get update && \
|
||||
ARG OPENBLAS_ARCH=ARMV7
|
||||
ARG ARM_HARDWARE_OPTS="-mfloat-abi=hard -mfpu=neon"
|
||||
RUN cd /opt \
|
||||
&& git clone -b lookahead-1.8.0 --single-branch https://github.com/alphacep/kaldi \
|
||||
&& git clone -b vosk --single-branch https://github.com/alphacep/kaldi \
|
||||
&& cd kaldi/tools \
|
||||
&& git clone -b v0.3.13 --single-branch https://github.com/xianyi/OpenBLAS \
|
||||
&& git clone -b v3.2.1 --single-branch https://github.com/alphacep/clapack \
|
||||
|
||||
@@ -12,7 +12,7 @@ RUN yum -y update && yum -y install \
|
||||
&& yum clean all
|
||||
|
||||
RUN cd /opt \
|
||||
&& git clone -b lookahead-1.8.0 --single-branch https://github.com/alphacep/kaldi \
|
||||
&& git clone -b vosk --single-branch https://github.com/alphacep/kaldi \
|
||||
&& cd /opt/kaldi/tools \
|
||||
&& git clone -b v0.3.13 --single-branch https://github.com/xianyi/OpenBLAS \
|
||||
&& git clone -b v3.2.1 --single-branch https://github.com/alphacep/clapack \
|
||||
|
||||
Reference in New Issue
Block a user