Compare commits

...

68 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
Nickolay Shmyrev 4333c3c242 Build dockcross with python 3.8 2020-06-23 01:11:07 +02:00
Nickolay V. Shmyrev b831c9ad57 Merge pull request #151 from hviana/patch-1
Add support for speaker model in Android
2020-06-23 00:07:26 +03:00
Nickolay Shmyrev e5c08f7710 Allow to continue after final result. See for discussion
https://github.com/alphacep/vosk-api/issues/146
2020-06-22 23:04:09 +02:00
Henrique Emanoel Viana 51c2968595 fix 2020-06-22 18:01:42 -03:00
Henrique Emanoel Viana 5993376322 Add suport to SpkModel 2020-06-22 17:51:55 -03:00
Nickolay Shmyrev c4281622b9 Added node speaker demo 2020-06-22 21:45:50 +02:00
Nickolay Shmyrev 9d26014de2 Use wider beams by default to avoid accuracy confusion 2020-06-19 16:10:30 +02:00
Nickolay Shmyrev f6c115d215 Update to 0.3.9 and use our fork of openfst based on openfst 1.7.7 2020-06-16 19:13:57 +02:00
Nickolay Shmyrev 6bd102d778 Fixes timing issue #125 2020-06-15 02:04:02 +02:00
Nickolay Shmyrev d3d6af5712 Define os in a single place 2020-06-12 10:35:58 +02:00
Nickolay V. Shmyrev 876093446f Merge pull request #127 from nnkalita/master
added android build support on macOS
2020-06-12 11:32:27 +03:00
Nickolay Shmyrev 336f219f09 No Qr code for wechat anymore 2020-06-11 12:57:32 +02:00
Nickolay Shmyrev 584251cbdc Remove chinese-only 2020-06-11 09:18:34 +02:00
Nickolay Shmyrev a34995a788 Process audio in chunks for imporved accuracy 2020-06-11 01:06:11 +02:00
Nickolay Shmyrev 998e5da227 Update rules for joining wechat 2020-06-10 15:07:10 +02:00
Nickolay Shmyrev e04c15e367 Fix 2020-06-06 11:15:23 +02:00
Nickolay Shmyrev b81f69d407 Avoid overflow. See issue #128 2020-06-06 10:43:44 +02:00
Nickolay Shmyrev 0ac2064281 Few more words 2020-06-06 10:07:12 +02:00
Nickolay Shmyrev 1d00bd244e Multithreaded testing 2020-06-06 00:40:15 +02:00
Nickolay Shmyrev 8f5efc58c9 Disable ivector pipeline without ivectors 2020-06-05 19:34:04 +02:00
Nayan Kalita a0c5ae1b5e Update build-kaldi.sh
added android build from mac.
2020-06-05 20:10:28 +05:30
Nayan Kalita 99f48f9de1 Merge remote-tracking branch 'upstream/master' 2020-06-05 19:15:42 +05:30
Nayan Kalita 1948b23f32 Update build-kaldi.sh
Updated based feedback.
2020-06-05 18:03:01 +05:30
Nickolay Shmyrev c9eb572fc5 Move documentation to our website 2020-06-05 01:31:13 +02:00
Nickolay Shmyrev 7d9895ff81 Add API documentation in the header 2020-06-04 22:47:54 +02:00
Nickolay Shmyrev d507210ef8 Add npmignore and pure javascript package 2020-06-03 17:47:15 +02:00
Nickolay Shmyrev db0a3d23d5 Add repackages librispeech model 2020-06-03 17:24:28 +02:00
Nickolay Shmyrev f4f920f3cd Proper cross-compilation with setuptools 2020-06-02 00:36:16 +02:00
Nickolay Shmyrev 75993ea276 Update to 0.3.8 2020-06-01 00:55:28 +02:00
Nickolay Shmyrev ee9bacb092 Reset pipeline to save memory 2020-06-01 00:54:47 +02:00
Nickolay Shmyrev b1e775c67b Better speaker identification without silence frames 2020-05-31 23:46:42 +02:00
Nickolay Shmyrev d631e567aa Add README 2020-05-31 02:21:07 +02:00
Nickolay Shmyrev 9edf45be42 Sync version 2020-05-31 02:08:35 +02:00
Nickolay Shmyrev 8b4b3c646a Nodejs support 2020-05-31 02:07:01 +02:00
Nickolay Shmyrev 31bb0557d9 Add mkl support 2020-05-30 23:22:14 +02:00
Nickolay Shmyrev 4593183cf9 Create gen if doens't exist. Thanks to BMI24. 2020-05-25 00:32:42 +02:00
Nickolay Shmyrev fdc45f1187 Better link on wechat 2020-05-23 21:13:23 +02:00
Nickolay Shmyrev b3d3c6d12c Fix mistake, thanks to Shaheen 2020-05-23 01:12:31 +02:00
Nickolay Shmyrev f5f0794def Add logo 2020-05-22 15:24:57 +02:00
Nickolay Shmyrev 55664fcca0 Add wechat group 2020-05-22 09:56:54 +02:00
Nickolay Shmyrev afbf330f16 Make ivector extractor optional 2020-05-18 23:56:42 +02:00
Nickolay Shmyrev 25aadf61bc Fix travis 2020-05-09 17:36:55 +02:00
Nickolay Shmyrev be47056467 Updates for osx 2020-05-09 15:49:24 +03:00
Nickolay Shmyrev 8f623e0aea Get rid of broken cmake 2020-05-09 14:32:46 +02:00
Nickolay Shmyrev 78025435e4 Windows is fully supported now 2020-05-09 09:18:10 +02:00
Nickolay Shmyrev 910455802e Don't link to the library explicitely to allow relocations 2020-05-08 15:16:50 +03:00
Nickolay Shmyrev b12914955c Add x86 build 2020-05-08 11:33:25 +02:00
Nickolay Shmyrev dfe11eaf83 Linux build fix 2020-05-08 09:04:14 +02:00
Nickolay Shmyrev 37fbe1a52b OSX build 2020-05-08 09:55:15 +03:00
Nickolay Shmyrev af11bb2361 No need for external dependencies 2020-05-07 21:48:03 +02:00
Nickolay Shmyrev 8da8697c1e Add ffmpeg test 2020-05-07 21:07:17 +02:00
Nickolay V. Shmyrev 944dc87531 Update readme to mention aarch64 2020-05-05 00:55:29 +02:00
Nickolay Shmyrev 5c4dd4644e Update version 2020-05-03 20:52:43 +02:00
Nickolay Shmyrev 9bbd172cfd Some more links 2020-05-02 01:37:10 +02:00
Nickolay Shmyrev dbf9de77c3 Document model training and model structure 2020-05-02 01:11:25 +02:00
Nickolay Shmyrev 8b790cd162 Better android logging 2020-05-01 20:02:46 +02:00
Nickolay Shmyrev 80219066e9 Expose verbose level in the API 2020-05-01 19:02:57 +02:00
Nickolay Shmyrev 26fa5f098f Updated link to English model 2020-04-30 15:19:13 +02:00
Nickolay Shmyrev d75bb36131 Fix model download path 2020-04-30 11:04:35 +02:00
Nickolay Shmyrev 30c5e8ca79 Link to lm library for rescoring 2020-04-30 10:52:15 +02:00
Nickolay Shmyrev c00e36fab6 Rearrange models 2020-04-30 10:47:10 +02:00
Nayan Kalita bca0b86e37 android build support on macOS 2020-03-06 20:57:56 +05:30
48 changed files with 1016 additions and 790 deletions
+24 -1
View File
@@ -24,14 +24,37 @@ wheelhouse
__pycache__
*.egg-info
python/dist
python/vosk/*.cc
python/vosk/*.c
python/vosk/*.h
python/vosk/*.i
python/vosk/vosk.py
python/vosk/vosk_wrap.cpp
python/test/db
python/test/hyp
python/test/model
python/test/ref
python/test/result.txt
python/test/wav.scp
# Java
*.so
java/org
java/model-en
java/*.cc
java/model-spk/
java/model/
# CSharp
csharp/gen
csharp/*.exe
csharp/*.c
csharp/model/
csharp/test.wav
# Node
nodejs/vosk_wrap.cc
nodejs/example/model
nodejs/example/test.wav
nodejs/node_modules
nodejs/package-lock.json
nodejs/build
+17 -133
View File
@@ -1,142 +1,26 @@
Vosk is an open source speech recognition toolkit which supports 9
languages - English, German, French, Spanish, Portuguese, Chinese,
Russian, Turkish, Vietnamese. Vosk works offline with small (50 Mb), but
accurate model, zero-latency response with streaming API, reconfigurable
vocabulary and speaker identification.
### Installation and usage
For Vosk installation instructions, examples and turorial and documentation visit https://alphacephei.com/vosk
### Build
[![Build Status](https://travis-ci.com/alphacep/vosk-api.svg?branch=master)](https://travis-ci.com/alphacep/vosk-api)
[РУС](README.ru.md)
### Models for different languages
[中文](README.zh.md)
For information about models see [the documentation on available models](https://alphacephei.com/vosk/models.html).
Vosk is a speech recognition toolkit. The best things in Vosk are:
### Contact Us
1. Supports 9 languages - English, German, French, Spanish, Portuguese, Chinese, Russian, Turkish, Vietnamese. More to come.
1. Works offline, even on lightweight devices - Raspberry Pi, Android, iOS
1. Installs with simple `pip3 install vosk`
1. Portable per-language models are only 50Mb each, but there are much bigger server models available.
1. Provides streaming API for the best user experience (unlike popular speech-recognition python packages)
1. There are bindings for different programming languages, too - java/csharp/javascript etc.
1. Allows quick reconfiguration of vocabulary for best accuracy.
1. Supports speaker identification beside simple speech recognition.
## Android build
```
cd android
gradle build
```
Please note that medium blog post about 64-bit is not relevant anymore, the script builds x86, arm64 and armv7 libraries automatically without any modifications.
For example of Android application using Vosk-API check https://github.com/alphacep/kaldi-android-demo project
## iOS build
Available on request. Drop as a mail at [contact@alphacephei.com](mailto:contact@alphacephei.com).
## Python installation from Pypi
The easiest way to install vosk api is with pip. You do not have to compile anything. We currently support only Linux on x86_64 and Raspberry Pi. Other systems (windows, mac) will come soon.
Make sure you have newer pip and python:
* Python version >= 3.4
* pip version >= 19.0
Uprade python and pip if needed. Then install vosk on Linux with a simple command
```
pip3 install vosk
```
## Websocket Server and GRPC server
We also provide a websocket server and grpc server which can be used in telephony and other applications. With bigger models adapted for 8khz audio it provides more accuracy.
The server is installed with docker and can run with a single command:
```
docker run -d -p 2700:2700 alphacep/kaldi-en:latest
```
For details see https://github.com/alphacep/vosk-server
## Compilation from source
If you still want to build from scratch, you can compile Kaldi and Vosk yourself. The compilation is straightforward but might be a little confusing for newbie. In case you want to follow this, please watch the errors.
#### Kaldi compilation for local python, node and java modules
```
git clone -b lookahead --single-branch https://github.com/alphacep/kaldi
cd kaldi/tools
make
```
install all dependencies and repeat `make` if needed
```
extras/install_openblas.sh
cd ../src
./configure --mathlib=OPENBLAS --shared --use-cuda=no
make -j 10
```
#### Python module build
Then build the python module
```
export KALDI_ROOT=<KALDI_ROOT>
cd python
python3 setup.py install
```
#### Running the example code with python
Run like this:
```
cd vosk-api/python/example
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-model-android-en-us-0.3.tar.gz
tar xf alphacep-model-android-en-us-0.3.tar.gz
mv alphacep-model-android-en-us-0.3 model-en
python3 ./test_simple.py test.wav
```
To run with your audio file make sure it has proper format - PCM 16khz 16bit mono, otherwise decoding will not work.
You can find other examples of using a microphone, decoding with a fixed small vocabulary or speaker identification setup in [python/example subfolder](https://github.com/alphacep/vosk-api/tree/master/python/example)
#### Java example API build
Or Java
```
cd java && KALDI_ROOT=<KALDI_ROOT> make
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-model-android-en-us-0.3.tar.gz
tar xf alphacep-model-android-en-us-0.3.tar.gz
mv alphacep-model-android-en-us-0.3 model
make run
```
#### C# build
Or C#
```
cd csharp && KALDI_ROOT=<KALDI_ROOT> make
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-model-android-en-us-0.3.tar.gz
tar xf alphacep-model-android-en-us-0.3.tar.gz
mv alphacep-model-android-en-us-0.3 model
mono test.exe
```
## Models for different languages
For information about models see [the documentation on available models](https://github.com/alphacep/vosk-api/blob/master/doc/models.md).
## Contact Us
If you have any questions, feel free to
If you have any questions, feel free to:
* Post an issue here on github
* Send us an e-mail at [contact@alphacephei.com](mailto:contact@alphacephei.com)
* Join our group dedicated to speech recognition on Telegram [@speech_recognition](https://t.me/speech_recognition)
* We have a Wechat group which is pretty big, so it is invitation-only. Mail us to join the group and provide some information about yourself.
-149
View File
@@ -1,149 +0,0 @@
[![Build Status](https://travis-ci.com/alphacep/vosk-api.svg?branch=master)](https://travis-ci.com/alphacep/vosk-api)
[EN](README.md)
[中文](README.zh.md)
Библитека для распознавания речи "Воск". Преимущества библиотеки:
1. Поддерживает 9 языков - русский, английский, немецкий, французский, португальский, испанский, китайский, турецкий, вьетнамский. В скором времени будут добавлены и другие
1. Работает без доступа к сети даже на мобильных устройствах - Raspberry Pi, Android, iOS
1. Устанавливается с помощью простой команды `pip3 install vosk` без дополнительных шагов
1. Модели для каждого языка занимают всего 50Мб, но есть и гораздо более точные большие модели для более точного распознавания
1. Сделана для потоковой обработки звука, что позволяет реализовать мгновенную реакцию на команды
1. Поддерживает несколько популярных языков программирования - Java, C#, Javascript
1. Позволяет быстро настраивать словарь распознавания для улучшения точности распознавания
1. Позволяет идентифицировать говорящего
## Сборка для Android
```
cd android
gradle build
```
Сборка включает платформы x86, armv7, arm64
Для примера приложения, созданного с помощью библиотеки "Воск" смотрите [демо проект](https://github.com/alphacep/kaldi-android-demo).
## Сборка для iOS
Доступна позапросу. Напишите нам [contact@alphacephei.com](mailto:contact@alphacephei.com).
## Установка для работы Python из Pypi
Проще всего установить "Воск" с помощью pip. Собирать ничего не нужно. Мы поддерживаем платформы Linux, RPi и Windows. Сборка для OSX будет скоро доступна.
Для начала убедитесь, что используются достаточно новые версии pip и Python:
* Python версия >= 3.5
* pip версия >= 19.0
Обновите Python и Pip если нужно, а затем установите "Воск" такой командой:
```
pip3 install vosk
```
Для использования "Воск" смотрите примеры ниже.
## Сервер для протоколов Websocket и GRPC
We also provide a websocket server and grpc server which can be used in telephony and other applications. With bigger models adapted for 8khz audio it provides more accuracy.
The server is installed with docker and can run with a single command:
```
docker run -d -p 2700:2700 alphacep/kaldi-en:latest
```
Смотрите проект https://github.com/alphacep/vosk-server
## Сборка из исходников
Если нужно собрать проект из исходного кода, необходимо будет собрать
Kaldi самостоятельно. Сборка досаточно простая и прямолинейная, но может
быть непривычной для начинающих. Обращайте внимания на сообщения об ошибках
в процессе сборки.
#### Сборка Kaldi для модулей на Python, Java, C#
```
git clone https://github.com/kaldi-asr/kaldi
cd kaldi/tools
make
```
установите все рекомандуемые пакеты и повторите `make` если потребуется.
```
extras/install_openblas.sh
cd ../src
./configure --mathlib=OPENBLAS --shared --use-cuda=no
make -j 10
```
#### Сборка модуля на Python
После Kaldi можно собрать модуль Python
```
export KALDI_ROOT=<KALDI_ROOT>
cd python
python3 setup.py install
```
#### Запуск примера для Python
Выполните следующие команды:
```
cd vosk-api/python/example
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-model-android-en-us-0.3.tar.gz
tar xf alphacep-model-android-en-us-0.3.tar.gz
mv alphacep-model-android-en-us-0.3 model-en
python3 ./test_simple.py test.wav
```
Для того, чтобы распознавать другой файл, переведите его в нужный формат - PCM 16кГц 16бит 1канал. Это можно сделать с помощью ffmpeg.
Другие примеры, в том числе использования микрофона, распознавание с небольшим словарём и распознавание говорящего можно найти в [каталоге python/example](https://github.com/alphacep/vosk-api/tree/master/python/example)
#### Сборка для Java
Перейдите в каталог Java и запустите сборку
```
cd java && KALDI_ROOT=<KALDI_ROOT> make
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-model-android-en-us-0.3.tar.gz
tar xf alphacep-model-android-en-us-0.3.tar.gz
mv alphacep-model-android-en-us-0.3 model
make run
```
#### Сборка для C#
Для сборки в среде Mono.
```
cd csharp && KALDI_ROOT=<KALDI_ROOT> make
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-model-android-en-us-0.3.tar.gz
tar xf alphacep-model-android-en-us-0.3.tar.gz
mv alphacep-model-android-en-us-0.3 model
mono test.exe
```
.NET тоже должен работать, хотя мы не пробовали.
## Модели для разных языков
По информации о моделях смотрите соответствующую [страницу документации](https://github.com/alphacep/vosk-api/blob/master/doc/models.md).
## Contact Us
Если возникли вопросы, свяжитесь с нами:
* Создайте проблему тут на github
* Напишите нам по почте [contact@alphacephei.com](mailto:contact@alphacephei.com)
* Заходите в нашу группу в Телеграмме [@speech_recognition_ru](https://t.me/speech_recognition_ru)
-12
View File
@@ -1,12 +0,0 @@
[![Build Status](https://travis-ci.com/alphacep/vosk-api.svg?branch=master)](https://travis-ci.com/alphacep/vosk-api)
Vosk是言语识别工具包。Vosk最好的事情是:
1. 支持九种语言 - 中文, 英语,德语,法语,西班牙语,葡萄牙语,俄语,土耳其语,越南语
1. 移动设备上脱机工作-Raspberry PiAndroidiOS
1. 使用简单的 pip3 install vosk 安装
1. 每种语言的手提式模型只有是50Mb, 但还有更大的服务器模型可用
1. 提供流媒体API,以提供最佳用户体验(与流行的语音识别python包不同)
1. 还有用于不同编程语言的包装器-java / csharp / javascript等
1. 可以快速重新配置词汇以实现最佳准确性
1. 支持说话人识别
+4
View File
@@ -8,6 +8,9 @@ set(KALDI_SUFFIX "arm_32")
elseif ("x${ANDROID_ABI}" STREQUAL "xarm64-v8a")
set(OPENBLAS_ARCH "armv8")
set(KALDI_SUFFIX "arm_64")
elseif ("x${ANDROID_ABI}" STREQUAL "xx86")
set(OPENBLAS_ARCH "atom")
set(KALDI_SUFFIX "x86")
else ("x${ANDROID_ABI}" STREQUAL "xarmeabi-v7a")
set(OPENBLAS_ARCH "atom")
set(KALDI_SUFFIX "x86_64")
@@ -45,6 +48,7 @@ target_link_libraries( kaldi_jni
${KALDI_ROOT}/src/tree/kaldi-tree.a
${KALDI_ROOT}/src/feat/kaldi-feat.a
${KALDI_ROOT}/src/lat/kaldi-lat.a
${KALDI_ROOT}/src/lm/kaldi-lm.a
${KALDI_ROOT}/src/hmm/kaldi-hmm.a
${KALDI_ROOT}/src/transform/kaldi-transform.a
${KALDI_ROOT}/src/cudamatrix/kaldi-cudamatrix.a
+29 -18
View File
@@ -31,36 +31,38 @@ fi
set -x
OS_NAME=`echo $(uname -s) | tr '[:upper:]' '[:lower:]'`
ANDROID_NDK_HOME=$ANDROID_SDK_HOME/ndk-bundle
ANDROID_TOOLCHAIN_PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
ANDROID_TOOLCHAIN_PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/${OS_NAME}-x86_64
WORKDIR_X86=`pwd`/build/kaldi_x86
WORKDIR_X86_64=`pwd`/build/kaldi_x86_64
WORKDIR_ARM32=`pwd`/build/kaldi_arm_32
WORKDIR_ARM64=`pwd`/build/kaldi_arm_64
PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin
PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/${OS_NAME}-x86_64/bin
OPENFST_VERSION=1.6.7
mkdir -p $WORKDIR_ARM64/local/lib $WORKDIR_ARM32/local/lib $WORKDIR_X86_64/local/lib
mkdir -p $WORKDIR_ARM64/local/lib $WORKDIR_ARM32/local/lib $WORKDIR_X86_64/local/lib $WORKDIR_X86/local/lib
# Build standalone CLAPACK since gfortran is missing
cd build
git clone https://github.com/simonlynen/android_libs
cd android_libs/lapack
sed -i 's/APP_STL := gnustl_static/APP_STL := c++_static/g' jni/Application.mk && \
sed -i 's/android-10/android-21/g' project.properties && \
sed -i 's/APP_ABI := armeabi armeabi-v7a/APP_ABI := armeabi-v7a arm64-v8a x86_64/g' jni/Application.mk && \
sed -i 's/LOCAL_MODULE:= testlapack/#LOCAL_MODULE:= testlapack/g' jni/Android.mk && \
sed -i 's/LOCAL_SRC_FILES:= testclapack.cpp/#LOCAL_SRC_FILES:= testclapack.cpp/g' jni/Android.mk && \
sed -i 's/LOCAL_STATIC_LIBRARIES := lapack/#LOCAL_STATIC_LIBRARIES := lapack/g' jni/Android.mk && \
sed -i 's/include $(BUILD_SHARED_LIBRARY)/#include $(BUILD_SHARED_LIBRARY)/g' jni/Android.mk && \
sed -i.bak -e 's/APP_STL := gnustl_static/APP_STL := c++_static/g' jni/Application.mk && \
sed -i.bak -e 's/android-10/android-21/g' project.properties && \
sed -i.bak -e 's/APP_ABI := armeabi armeabi-v7a/APP_ABI := armeabi-v7a arm64-v8a x86_64 x86/g' jni/Application.mk && \
sed -i.bak -e 's/LOCAL_MODULE:= testlapack/#LOCAL_MODULE:= testlapack/g' jni/Android.mk && \
sed -i.bak -e 's/LOCAL_SRC_FILES:= testclapack.cpp/#LOCAL_SRC_FILES:= testclapack.cpp/g' jni/Android.mk && \
sed -i.bak -e 's/LOCAL_STATIC_LIBRARIES := lapack/#LOCAL_STATIC_LIBRARIES := lapack/g' jni/Android.mk && \
sed -i.bak -e 's/include $(BUILD_SHARED_LIBRARY)/#include $(BUILD_SHARED_LIBRARY)/g' jni/Android.mk && \
${ANDROID_NDK_HOME}/ndk-build && \
cp obj/local/armeabi-v7a/*.a ${WORKDIR_ARM32}/local/lib && \
cp obj/local/arm64-v8a/*.a ${WORKDIR_ARM64}/local/lib
cp obj/local/x86_64/*.a ${WORKDIR_X86_64}/local/lib
cp obj/local/x86/*.a ${WORKDIR_X86}/local/lib
# Architecture-specific part
for arch in arm32 arm64 x86_64; do
for arch in arm32 arm64 x86_64 x86; do
#for arch in x86_64; do
case $arch in
@@ -91,6 +93,15 @@ case $arch in
CXX=x86_64-linux-android21-clang++
ARCHFLAGS=""
;;
x86)
BLAS_ARCH=ATOM
WORKDIR=$WORKDIR_X86
HOST=i686-linux-android
AR=i686-linux-android-ar
CC=i686-linux-android21-clang
CXX=i686-linux-android21-clang++
ARCHFLAGS=""
;;
esac
# openblas first
@@ -101,12 +112,9 @@ make -C OpenBLAS install PREFIX=$WORKDIR/local
# tools directory --> we'll only compile OpenFST
cd $WORKDIR
wget -c -T 10 -t 1 http://www.openfst.org/twiki/pub/FST/FstDownload/openfst-${OPENFST_VERSION}.tar.gz || \
wget -c -T 10 -t 3 http://www.openslr.org/resources/2/openfst-${OPENFST_VERSION}.tar.gz
tar -zxvf openfst-${OPENFST_VERSION}.tar.gz
cd openfst-${OPENFST_VERSION}
git clone https://github.com/alphacep/openfst
cd openfst
autoreconf -i
CXX=$CXX CXXFLAGS="$ARCHFLAGS -O3 -DFST_NO_DYNAMIC_LINKING" ./configure --prefix=${WORKDIR}/local \
--enable-shared --enable-static --with-pic --disable-bin \
--enable-lookahead-fsts --enable-ngram-fsts --host=$HOST --build=x86-linux-gnu
@@ -117,6 +125,9 @@ make install
cd $WORKDIR
git clone -b android-mix --single-branch https://github.com/alphacep/kaldi
cd $WORKDIR/kaldi/src
if [ "`uname`" == "Darwin" ]; then
sed -i.bak -e 's/libfst.dylib/libfst.a/' configure
fi
CXX=$CXX CXXFLAGS="$ARCHFLAGS -O3 -DFST_NO_DYNAMIC_LINKING" ./configure --use-cuda=no \
--mathlib=OPENBLAS --shared \
+1 -1
View File
@@ -31,7 +31,7 @@ android {
}
}
ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64', 'x86'
}
}
sourceSets {
@@ -241,10 +241,6 @@ public class Assets {
if (!items.get(path).equals(externalItems.get(path))
|| !(new File(externalDir, path).exists()))
newItems.add(path);
else
Log.i(TAG,
String.format("Skipping asset %s: checksums are equal", path));
}
unusedItems.addAll(externalItems.keySet());
@@ -252,13 +248,11 @@ public class Assets {
for (String path : newItems) {
File file = copy(path);
Log.i(TAG, String.format("Copying asset %s to %s", path, file));
}
for (String path : unusedItems) {
File file = new File(externalDir, path);
file.delete();
Log.i(TAG, String.format("Removing asset %s", file));
}
updateItemList(items);
@@ -74,6 +74,22 @@ public class SpeechRecognizer {
}
}
public SpeechRecognizer(Model model, SpkModel spkModel) throws IOException {
recognizer = new KaldiRecognizer(model, spkModel, 16000.0f);
sampleRate = 16000;
bufferSize = Math.round(sampleRate * BUFFER_SIZE_SECONDS);
recorder = new AudioRecord(
AudioSource.VOICE_RECOGNITION, sampleRate,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, bufferSize * 2);
if (recorder.getState() == AudioRecord.STATE_UNINITIALIZED) {
recorder.release();
throw new IOException(
"Failed to initialize recorder. Microphone might be already in use.");
}
}
/**
* Adds listener.
*/
@@ -148,7 +164,6 @@ public class SpeechRecognizer {
public boolean stop() {
boolean result = stopRecognizerThread();
if (result) {
Log.i(TAG, "Stop recognition");
mainHandler.post(new ResultEvent(recognizer.Result(), true));
}
return result;
@@ -163,10 +178,6 @@ public class SpeechRecognizer {
public boolean cancel() {
boolean result = stopRecognizerThread();
recognizer.Result(); // Reset recognizer state
if (result) {
Log.i(TAG, "Cancel recognition");
}
return result;
}
@@ -207,8 +218,6 @@ public class SpeechRecognizer {
return;
}
Log.d(TAG, "Starting decoding");
short[] buffer = new short[bufferSize];
while (!interrupted()
+3 -2
View File
@@ -44,10 +44,11 @@ libkaldiwrap.so: $(VOSK_SOURCES)
$(CXX) -fpermissive $(CFLAGS) $(CPPFLAGS) -shared -o $@ $(VOSK_SOURCES) $(KALDI_LIBS)
vosk_wrap.c: ../src/vosk.i
swig -csharp -DSWIG_CSHARP_NO_EXCEPTION_HELPER -dllimport "libkaldiwrap.so" \
mkdir -p gen
swig -csharp -DSWIG_CSHARP_NO_EXCEPTION_HELPER -dllimport "libkaldiwrap" \
-namespace "Kaldi" -outdir gen -o vosk_wrap.c ../src/vosk.i
run:
run: test.exe
mono test.exe
clean:
+1
View File
@@ -7,6 +7,7 @@ public class Test
public static void Main()
{
Vosk.SetLogLevel(0);
Model model = new Model("model");
KaldiRecognizer rec = new KaldiRecognizer(model, 16000.0f);
+1 -21
View File
@@ -1,21 +1 @@
## Accuracy issues
Accuracy of modern systems is still unstable, that means sometimes you can have a very good accuracy and sometimes it could be bad.
It is hard to make a system that will work good. And there could be many reasons for that:
* Audio has very bad quality
* Vocabulary of the system doesn't match (yes, we still use fixed vocabulary)
* Audio conditions like accent were not really the ones that were used in training
* Some unpredictable audio issues like frame drop or frame coding bugs
* Software bugs
It is hard to guess what is going on under the hood without getting your hands dirty. For that reason in case of any accuracy
issues you must provide the following for analysis:
* Who are you, where are you from and why are you doing that. We don't like dealing with anonymous
* The complete and exact description of the system you want to build - what is it going to do, what do you want to build
* The precise description of hardware you are trying to run the system on
* The detailed list of software versions you are using
* Audio samples to demonstrate the problem together with the reference transcription for those samples
Remember, the more information you provide the faster you get a solution.
See https://alphacephei.com/vosk/accuracy.html
+1 -42
View File
@@ -1,42 +1 @@
## Updating the language model
The Kaldi model used in Vosk is compiled from 3 data sources:
* dictionary
* acoustic model
* language model
You can rebuild all three with different level of effort, but sometimes you just
need to adjust the probability of the words to improve the recognition. For
that it is enough to recompile the language model from the text. To do that
1) Take a text that reflects the speech you want to recognize
2) Remove punctuation, convert everything to the lowercase, you can do it with a python script
3) Build openfst and opengrm inside kaldi
```
export KALDI_ROOT=`pwd`/kaldi
git clone https://github.com/kaldi-asr/kaldi
cd kaldi/tools
make
# install all required dependencies and repeat `make` if needed
extras/install_opengrm.sh
```
4) Now lets build a grammar
```
export PATH=$KALDI_ROOT/tools/openfst/bin:$PATH
export LD_LIBRARY_PATH=$KALDI_ROOT/tools/openfst/lib/fst
cd model
fstsymbols --save_osymbols=words.txt Gr.fst > /dev/null
farcompilestrings --fst_type=compact --symbols=words.txt --keep_symbols text.txt | \
ngramcount | ngrammake | \
fstconvert --fst_type=ngram > Gr.fst
```
Use created Gr.fst instead of standard one in your model.
For more details see OpenGRM documentation http://www.opengrm.org/twiki/bin/view/GRM/NGramLibrary
You can not introduce new words this way, that is something we will cover later.
See https://alphacephei.com/vosk/adaptation.html
+1 -75
View File
@@ -1,75 +1 @@
# Models
This is the list of models compatible with Vosk-API.
To add a new model here create an issue on Github.
### English
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [kaldi-en-us-aspire-0.1](http://alphacephei.com/kaldi/kaldi-en-us-aspire-0.1.tar.gz) | 363M | TBD | Trained on Fisher + more or less recent LM. Pretty outdated but still ok even even for calls |
| [alphacep-model-android-en-us-0.3](http://alphacephei.com/kaldi/alphacep-model-android-en-us-0.3.tar.gz) | 36M | TBD | Lightweight wideband model for Android and RPi |
### Chinese
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [kaldi-cn-0.1.tar.gz](http://alphacephei.com/kaldi/kaldi-cn-0.1.tar.gz) | 195M | TBD | Big narrowband Chinese model for server processing |
| [alphacep-model-android-cn-0.3](http://alphacephei.com/kaldi/alphacep-model-android-cn-0.3.tar.gz) | 32M | TBD | Lightweight wideband model for Android and RPi |
### Russian
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [kaldi-ru-0.10.tar.gz](http://alphacephei.com/kaldi/kaldi-ru-0.10.tar.gz) | 2.5G | TBD | Big narrowband Russian model for server processing |
| [alphacep-model-android-ru-0.3](http://alphacephei.com/kaldi/alphacep-model-android-ru-0.3.tar.gz) | 39M | TBD | Lightweight wideband model for Android and RPi |
### French
| Model | Size | Accuracy | Notes |
|-------------------------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [alphacep-model-android-fr-pguyot-0.3](http://alphacephei.com/kaldi/alphacep-model-android-fr-pguyot-0.3.tar.gz) | 39M | TBD | Lightweight wideband model for Android and RPi trained by [Paul Guyot](https://github.com/pguyot/zamia-speech/releases) |
### German
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|------------------------------------------------------------------------------------------------------|
| [tuda-de](http://ltdata1.informatik.uni-hamburg.de/kaldi_tuda_de/de_400k_nnet3chain_tdnn1f_2048_sp_bi.tar.bz2) | 566M | TBD | Wideband server model from [tuda-de](https://github.com/uhh-lt/kaldi-tuda-de) |
| [alphacep-model-android-de-zamia-0.3](http://alphacephei.com/kaldi/alphacep-model-android-de-zamia-0.3.tar.gz) | 49M | TBD | Lightweight wideband model for Android and RPi |
### Spanish
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [alphacep-model-android-es-0.3](http://alphacephei.com/kaldi/alphacep-model-android-es-0.3.tar.gz) | 33M | TBD | Lightweight wideband model for Android and RPi |
### Portuguese
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [alphacep-model-android-pt-0.3](http://alphacephei.com/kaldi/alphacep-model-android-pt-0.3.tar.gz) | 31M | TBD | Lightweight wideband model for Android and RPi |
### Dutch
https://github.com/opensource-spraakherkenning-nl/Kaldi_NL
### Greek
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [kaldi-el-gr-0.6.tar.gz](http://alphacephei.com/kaldi/kaldi-el-gr-0.6.tar.gz) | 1.1G | TBD | Big narrowband Greek model for server processing, not extremely accurate though |
### Turkish
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [alphacep-model-android-tr-0.3](http://alphacephei.com/kaldi/alphacep-model-android-tr-0.3.tar.gz) | 35M | TBD | Lightweight wideband model for Android and RPi |
### Vietnamese
| Model | Size | Accuracy | Notes |
|-----------------------------------------------------------------------------------------------------------|-------|------------|----------------------------------------------------------------------------------------------|
| [alphacep-model-android-vn-0.3](http://alphacephei.com/kaldi/alphacep-model-android-vn-0.3.tar.gz) | 32M | TBD | Lightweight wideband model for Android and RPi |
See https://alphacephei.com/vosk/models.html
+8 -8
View File
@@ -50,16 +50,16 @@ clean:
$(RM) *.so *_wrap.cc *_wrap.o test/*.class
$(RM) -r org model-en
model-en:
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-model-android-en-us-0.3.tar.gz
tar xf alphacep-model-android-en-us-0.3.tar.gz && rm alphacep-model-android-en-us-0.3.tar.gz
mv alphacep-model-android-en-us-0.3 model-en
model:
wget https://alphacephei.com/kaldi/models/vosk-model-small-en-us-0.3.zip
unzip vosk-model-small-en-us-0.3.zip && rm vosk-model-small-en-us-0.3.zip
mv vosk-model-small-en-us-0.3 model
model-spk:
wget https://github.com/alphacep/kaldi-android-demo/releases/download/2020-01/alphacep-spk-model-0.3.tar.gz
tar xf alphacep-spk-model-0.3.tar.gz && rm alphacep-spk-model-0.3.tar.gz
mv alphacep-spk-model-0.3 model-spk
wget https://alphacephei.com/kaldi/models/vosk-model-spk-0.3.zip
unzip vosk-model-spk-0.3.zip && rm vosk-model-spk-0.3.zip
mv vosk-model-spk-0.3 model-spk
run: model-en model-spk
run: model model-spk
javac test/*.java org/kaldi/*.java
java -Djava.library.path=. -cp . test.DecoderTest
+3
View File
@@ -11,6 +11,7 @@ import java.nio.*;
import org.kaldi.KaldiRecognizer;
import org.kaldi.Model;
import org.kaldi.SpkModel;
import org.kaldi.Vosk;
public class DecoderTest {
static {
@@ -18,6 +19,8 @@ public class DecoderTest {
}
public static void main(String args[]) throws IOException {
Vosk.SetLogLevel(-10);
FileInputStream ais = new FileInputStream(new File("../python/example/test.wav"));
Model model = new Model("model");
SpkModel spkModel = new SpkModel("model-spk");
+3
View File
@@ -0,0 +1,3 @@
build
node_modules
vosk_wrap.cc
+20
View File
@@ -0,0 +1,20 @@
Installation requires vosk-api checkout, it doesn't yet work with `npm
install vosk`. We have to figure out how to properly distribute native
modules for Vosk.
The build tested with node-0.10.15, node-0.12 is not yet supported by swig.
Still, you need swig of newest version 4.0.1
Build like this
```
npm install --kaldi_root=/home/suser/kaldi
```
Then test with
```
cd example
node test.js
```
+70
View File
@@ -0,0 +1,70 @@
{
'targets': [
{
'target_name': 'vosk',
'sources': [
'../src/kaldi_recognizer.cc',
'../src/model.cc',
'../src/spk_model.cc',
'../src/vosk_api.cc',
'vosk_wrap.cc',
],
'cflags': [
'-std=c++11',
'-DFST_NO_DYNAMIC_LINKING',
'-Wno-deprecated-declarations',
'-Wno-sign-compare',
'-Wno-unused-local-typedefs',
'-Wno-ignored-quaifiers',
'-Wno-extra',
],
'cflags_cc!' : [
'-fno-rtti',
'-fno-exceptions',
],
'actions': [
{
'action_name': 'swig',
'inputs': [
'../src/vosk.i',
],
'outputs': [
'vosk_wrap.cc',
],
'action': ['swig', '-c++', '-javascript', '-o', 'vosk_wrap.cc', '-v8', '-DV8_MAJOR_VERSION=10', '../src/vosk.i']
},
],
'include_dirs': [
'<@(kaldi_root)/src',
'<@(kaldi_root)/tools/openfst/include',
'../src',
],
'link_settings': {
'libraries': [
'<@(kaldi_root)/src/online2/kaldi-online2.a',
'<@(kaldi_root)/src/decoder/kaldi-decoder.a',
'<@(kaldi_root)/src/ivector/kaldi-ivector.a',
'<@(kaldi_root)/src/gmm/kaldi-gmm.a',
'<@(kaldi_root)/src/nnet3/kaldi-nnet3.a',
'<@(kaldi_root)/src/tree/kaldi-tree.a',
'<@(kaldi_root)/src/feat/kaldi-feat.a',
'<@(kaldi_root)/src/lat/kaldi-lat.a',
'<@(kaldi_root)/src/lm/kaldi-lm.a',
'<@(kaldi_root)/src/hmm/kaldi-hmm.a',
'<@(kaldi_root)/src/transform/kaldi-transform.a',
'<@(kaldi_root)/src/cudamatrix/kaldi-cudamatrix.a',
'<@(kaldi_root)/src/matrix/kaldi-matrix.a',
'<@(kaldi_root)/src/fstext/kaldi-fstext.a',
'<@(kaldi_root)/src/util/kaldi-util.a',
'<@(kaldi_root)/src/base/kaldi-base.a',
'<@(kaldi_root)/tools/openfst/lib/libfst.a',
'<@(kaldi_root)/tools/openfst/lib/libfstngram.a',
'<@(kaldi_root)/tools/OpenBLAS/libopenblas.a',
],
'library_dirs': [
'/usr/lib',
],
},
}
]
}
+90
View File
@@ -0,0 +1,90 @@
const wav = require('wav')
const fs = require('fs')
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)
}
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)
}
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 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)
}
const rec = new KaldiRecognizer(model, spkModel, sampleRate)
for await (const data of new Readable().wrap(wfReader)) {
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())
}
}
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)
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env node
const fs = require("fs");
const { Readable } = require("stream");
const wav = require("wav");
const { Model, KaldiRecognizer } = 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);
}
const wfStream = fs.createReadStream("test.wav", {'highWaterMark': 4096});
const wfReader = new wav.Reader();
const model = new Model("model");
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);
}
const rec = new KaldiRecognizer(model, sampleRate);
for await (const data of new Readable().wrap(wfReader)) {
const result = await rec.AcceptWaveform(data);
if (result != 0) {
console.log(await rec.Result());
} else {
console.log(await rec.PartialResult());
}
}
console.log(await rec.FinalResult());
});
wfStream.pipe(wfReader);
+3 -3
View File
@@ -1,3 +1,3 @@
exports.printMsg = function() {
console.log("This is a message from the Vosk package");
}
const voskNativeModule = require('./build/Release/vosk.node');
module.exports = voskNativeModule;
+9 -3
View File
@@ -1,6 +1,6 @@
{
"name": "vosk",
"version": "0.1.0",
"version": "0.3.8",
"description": "Node binding for continuous voice recoginition through pocketsphinx.",
"repository": {
"type": "git",
@@ -13,6 +13,12 @@
"voice"
],
"author": "Alpha Cephei Inc.",
"license": "Apache 2.0",
"engines": { "node" : ">= 12.x.x" }
"license": "Apache-2.0",
"engines": {
"node": ">= 10.x.x"
},
"dependencies": {
"node-gyp": "^5.1.1",
"wav": "^1.0.2"
}
}
-51
View File
@@ -1,51 +0,0 @@
cmake_minimum_required(VERSION 3.12.0)
project(vosk)
set(TOP_SRCDIR "${CMAKE_SOURCE_DIR}/..")
if("x$ENV{WHEEL_FLAGS}" STREQUAL "x")
find_package (Python3 COMPONENTS Interpreter Development)
else()
# docker case
set(Python3_INCLUDE_DIRS "")
set(TOP_SRCDIR "/io")
endif()
set(KALDI_ROOT "$ENV{KALDI_ROOT}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFST_NO_DYNAMIC_LINKING")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} $ENV{WHEEL_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} -std=c++11")
include_directories("${TOP_SRCDIR}/src" "${KALDI_ROOT}/src" "${KALDI_ROOT}/tools/openfst/include" ${Python3_INCLUDE_DIRS})
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
swig_add_library(vosk TYPE SHARED LANGUAGE Python OUTPUT_DIR "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" OUTFILE_DIR "."
SOURCES "${TOP_SRCDIR}/src/kaldi_recognizer.cc"
"${TOP_SRCDIR}/src/spk_model.cc"
"${TOP_SRCDIR}/src/model.cc"
"${TOP_SRCDIR}/src/vosk_api.cc"
"${TOP_SRCDIR}/src/vosk.i")
swig_link_libraries(vosk
${KALDI_ROOT}/src/online2/kaldi-online2.a
${KALDI_ROOT}/src/decoder/kaldi-decoder.a
${KALDI_ROOT}/src/ivector/kaldi-ivector.a
${KALDI_ROOT}/src/gmm/kaldi-gmm.a
${KALDI_ROOT}/src/nnet3/kaldi-nnet3.a
${KALDI_ROOT}/src/tree/kaldi-tree.a
${KALDI_ROOT}/src/feat/kaldi-feat.a
${KALDI_ROOT}/src/lat/kaldi-lat.a
${KALDI_ROOT}/src/lm/kaldi-lm.a
${KALDI_ROOT}/src/hmm/kaldi-hmm.a
${KALDI_ROOT}/src/transform/kaldi-transform.a
${KALDI_ROOT}/src/cudamatrix/kaldi-cudamatrix.a
${KALDI_ROOT}/src/matrix/kaldi-matrix.a
${KALDI_ROOT}/src/fstext/kaldi-fstext.a
${KALDI_ROOT}/src/util/kaldi-util.a
${KALDI_ROOT}/src/base/kaldi-base.a
${KALDI_ROOT}/tools/openfst/lib/libfst.a
${KALDI_ROOT}/tools/openfst/lib/libfstngram.a
${KALDI_ROOT}/tools/OpenBLAS/libopenblas.a
-lgfortran -lstdc++)
set_target_properties(_vosk PROPERTIES LINK_FLAGS_RELEASE -s)
-76
View File
@@ -1,76 +0,0 @@
# From https://github.com/raydouglass/cmake_setuptools
import os
import subprocess
import shutil
import sys
from setuptools import Extension
from setuptools.command.build_ext import build_ext
from setuptools.command.build_py import build_py
CMAKE_EXE = os.environ.get('CMAKE_EXE', shutil.which('cmake'))
def check_for_cmake():
if not CMAKE_EXE:
print('cmake executable not found. '
'Set CMAKE_EXE environment or update your path')
sys.exit(1)
class CMakeExtension(Extension):
"""
setuptools.Extension for cmake
"""
def __init__(self, name, pkg_name, sourcedir=''):
check_for_cmake()
Extension.__init__(self, name, sources=[])
self.sourcedir = os.path.abspath(sourcedir)
self.pkg_name = pkg_name
class CMakeBuildExt(build_ext):
"""
setuptools build_exit which builds using cmake & make
You can add cmake args with the CMAKE_COMMON_VARIABLES environment variable
"""
def build_extension(self, ext):
check_for_cmake()
if isinstance(ext, CMakeExtension):
output_dir = os.path.abspath(
os.path.dirname(self.get_ext_fullpath(ext.pkg_name + "/" + ext.name)))
build_type = 'Debug' if self.debug else 'Release'
cmake_args = [CMAKE_EXE,
ext.sourcedir,
'-Wno-dev',
'-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + output_dir,
'-DCMAKE_BUILD_TYPE=' + build_type]
cmake_args.extend(
[x for x in
os.environ.get('CMAKE_COMMON_VARIABLES', '').split(' ')
if x])
env = os.environ.copy()
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
subprocess.check_call(cmake_args,
cwd=self.build_temp,
env=env)
subprocess.check_call(['make', 'VERBOSE=1', ext.name],
cwd=self.build_temp,
env=env)
print()
else:
super().build_extension(ext)
class CMakeBuildExtFirst(build_py):
def run(self):
self.run_command("build_ext")
return super().run()
__all__ = ['CMakeBuildExt', 'CMakeExtension', 'CMakeBuildExtFirst']
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python3
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer
import sys
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer, SetLogLevel
import sys
import os
import wave
import subprocess
SetLogLevel(0)
if not os.path.exists("model"):
print ("Please download the model from https://github.com/alphacep/vosk-api/blob/master/doc/models.md and unpack as 'model' in the current folder.")
exit (1)
sample_rate=16000
model = Model("model")
rec = KaldiRecognizer(model, sample_rate)
process = subprocess.Popen(['ffmpeg', '-loglevel', 'quiet', '-i',
sys.argv[1],
'-ar', str(sample_rate) , '-ac', '1', '-f', 's16le', '-'],
stdout=subprocess.PIPE)
while True:
data = process.stdout.read(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
print(rec.Result())
else:
print(rec.PartialResult())
print(rec.FinalResult())
+6 -6
View File
@@ -1,23 +1,23 @@
#!/usr/bin/python3
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer
import os
if not os.path.exists("model"):
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.")
print ("Please download the model from https://github.com/alphacep/vosk-api/blob/master/doc/models.md and unpack as 'model' in the current folder.")
exit (1)
import pyaudio
model = Model("model")
rec = KaldiRecognizer(model, 16000)
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8000)
stream.start_stream()
model = Model("model")
rec = KaldiRecognizer(model, 16000)
while True:
data = stream.read(2000)
data = stream.read(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
+6 -4
View File
@@ -1,12 +1,14 @@
#!/usr/bin/python3
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer
from vosk import Model, KaldiRecognizer, SetLogLevel
import sys
import os
import wave
SetLogLevel(0)
if not os.path.exists("model"):
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.")
print ("Please download the model from https://github.com/alphacep/vosk-api/blob/master/doc/models.md and unpack as 'model' in the current folder.")
exit (1)
wf = wave.open(sys.argv[1], "rb")
@@ -18,7 +20,7 @@ model = Model("model")
rec = KaldiRecognizer(model, wf.getframerate())
while True:
data = wf.readframes(1000)
data = wf.readframes(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
+6 -5
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python3
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer, SpkModel
import sys
@@ -11,11 +11,11 @@ model_path = "model"
spk_model_path = "model-spk"
if not os.path.exists(model_path):
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as {} in the current folder.".format(model_path))
print ("Please download the model from https://github.com/alphacep/vosk-api/blob/master/doc/models.md and unpack as {} in the current folder.".format(model_path))
exit (1)
if not os.path.exists(spk_model_path):
print ("Please download the speaker model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as {} in the current folder.".format(spk_model_path))
print ("Please download the speaker model from https://github.com/alphacep/vosk-api/blob/master/doc/models.md and unpack as {} in the current folder.".format(spk_model_path))
exit (1)
wf = wave.open(sys.argv[1], "rb")
@@ -30,7 +30,7 @@ rec = KaldiRecognizer(model, spk_model, wf.getframerate())
# We compare speakers with cosine distance. We can keep one or several fingerprints for the speaker in a database
# to distingusih among users.
spk_sig = [5.64308, 4.23898, 1.119433, -0.810904, 2.115443, 2.328436, 6.135152, 1.348195, 2.60771, 1.020717, 4.324225, -0.873012, 6.123375, 4.903791, 0.064803, 4.66212, 3.502724, 2.535861, 5.452417, 7.081769, -0.823969, -5.167974, 8.568919, 4.159035, 5.314441, 3.688272, 5.730379, 4.463213, 7.227232, 3.538961, 3.316218, 1.269628, -1.902378, 3.512679, -1.947611, -1.520158, 3.80928, -2.721601, 5.359588, 2.942463, -7.474174, 3.788054, 0.303426, 4.951366, 1.72281, -1.867125, -3.574615, 3.622509, 4.803109, 2.829714, 1.528521, 6.408293, 0.820131, 5.066522, 2.836125, 2.867029, 3.725267, 0.505927, 1.462984, 5.001863, -3.838309, -2.45902, 3.992581, 4.451616, 2.865211, -1.148313, 4.996399, -3.473454, 2.876967, 3.940124, 7.553079, 0.373356, 1.396561, 2.686691, 2.094895, 0.913796, -0.286909, 3.540179, 4.904687, 0.84554, 7.585956, 1.017081, 0.168355, 6.672327, 4.092033, -4.240158, -2.017081, -0.813043, 6.468298, 4.115041, 2.231936, 2.370055, 4.972295, 5.58382, 6.022872, 2.706988, 5.248096, -1.918003, 8.259204, -0.900911, 1.961962, 2.349709, 3.290093, 3.344172, 3.307027, 4.203372, -0.315103, 5.61919, -3.229496, 3.777309, 4.328595, 1.461014, 2.622894, 0.315525, 5.447259, 5.407609, 5.339016, 1.604555, 5.359932, 0.090242, 0.535306, 4.724705, 4.692502, 0.5783, -5.436688, -4.915511, 1.959807, 2.825248]
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]
def cosine_dist(x, y):
nx = np.array(x)
@@ -38,12 +38,13 @@ def cosine_dist(x, y):
return 1 - np.dot(nx, ny) / np.linalg.norm(nx) / np.linalg.norm(ny)
while True:
data = wf.readframes(1000)
data = wf.readframes(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
res = json.loads(rec.Result())
print ("Text:", res['text'])
print ("X-vector:", res['spk'])
print ("Speaker distance:", cosine_dist(spk_sig, res['spk']))
res = json.loads(rec.FinalResult())
+3 -3
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python3
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer
import sys
@@ -6,7 +6,7 @@ import json
import os
if not os.path.exists("model"):
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.")
print ("Please download the model from https://github.com/alphacep/vosk-api/blob/master/doc/models.md and unpack as 'model' in the current folder.")
exit (1)
@@ -22,7 +22,7 @@ wf = open(sys.argv[1], "rb")
wf.read(44) # skip header
while True:
data = wf.read(2000)
data = wf.read(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
+3 -3
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python3
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer
import sys
@@ -6,7 +6,7 @@ import os
import wave
if not os.path.exists("model"):
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.")
print ("Please download the model from https://github.com/alphacep/vosk-api/blob/master/doc/models.md and unpack as 'model' in the current folder.")
exit (1)
wf = wave.open(sys.argv[1], "rb")
@@ -19,7 +19,7 @@ model = Model("model")
rec = KaldiRecognizer(model, wf.getframerate(), "zero oh one two three four five six seven eight nine")
while True:
data = wf.readframes(1000)
data = wf.readframes(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
+71 -5
View File
@@ -1,13 +1,79 @@
import os
import sys
import setuptools
from cmake import *
from setuptools import Extension
from setuptools.command.build_py import build_py as _build_py
import distutils.dir_util
import distutils.log
class build_py(_build_py):
def run(self):
self.run_command("build_ext")
return super().run()
kaldi_root = os.getenv('KALDI_ROOT')
kaldi_mkl = os.getenv('KALDI_MKL')
source_path = os.getenv("VOSK_SOURCE", os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "../src")))
if kaldi_root == None:
print("Define KALDI_ROOT")
exit(1)
distutils.log.set_verbosity(distutils.log.DEBUG)
distutils.dir_util.copy_tree(
source_path,
"vosk",
update=1,
verbose=1)
with open("README.md", "r") as fh:
long_description = fh.read()
kaldi_static_libs = ['src/online2/kaldi-online2.a',
'src/decoder/kaldi-decoder.a',
'src/ivector/kaldi-ivector.a',
'src/gmm/kaldi-gmm.a',
'src/nnet3/kaldi-nnet3.a',
'src/tree/kaldi-tree.a',
'src/feat/kaldi-feat.a',
'src/lat/kaldi-lat.a',
'src/lm/kaldi-lm.a',
'src/hmm/kaldi-hmm.a',
'src/transform/kaldi-transform.a',
'src/cudamatrix/kaldi-cudamatrix.a',
'src/matrix/kaldi-matrix.a',
'src/fstext/kaldi-fstext.a',
'src/util/kaldi-util.a',
'src/base/kaldi-base.a',
'tools/openfst/lib/libfst.a',
'tools/openfst/lib/libfstngram.a']
kaldi_link_args = ['-s']
kaldi_libraries = []
if sys.platform.startswith('darwin'):
kaldi_link_args.extend(['-Wl,-undefined,dynamic_lookup', '-framework', 'Accelerate'])
elif kaldi_mkl != None:
kaldi_link_args.extend(['-L/opt/intel/mkl/lib/intel64', '-Wl,-rpath=/opt/intel/mkl/lib/intel64'])
kaldi_libraries.extend(['mkl_rt', 'mkl_intel_lp64', 'mkl_core', 'mkl_sequential'])
else:
kaldi_static_libs.append('tools/OpenBLAS/libopenblas.a')
kaldi_libraries.append('gfortran')
sources = ['kaldi_recognizer.cc', 'model.cc', 'spk_model.cc', 'vosk_api.cc', 'vosk.i']
vosk_ext = Extension('vosk._vosk',
define_macros = [('FST_NO_DYNAMIC_LINKING', '1')],
include_dirs = [kaldi_root + '/src', kaldi_root + '/tools/openfst/include', 'vosk'],
swig_opts=['-outdir', 'vosk', '-c++'],
libraries = kaldi_libraries,
extra_objects = [kaldi_root + '/' + x for x in kaldi_static_libs],
sources = ['vosk/' + x for x in sources],
extra_link_args = kaldi_link_args,
extra_compile_args = ['-std=c++11', '-Wno-sign-compare', '-Wno-unused-variable', '-Wno-unused-local-typedefs'])
setuptools.setup(
name="vosk", # Replace with your own username
version="0.3.6",
version="0.3.10",
author="Alpha Cephei Inc",
author_email="contact@alphacephei.com",
description="API for Kaldi and Vosk",
@@ -15,8 +81,8 @@ setuptools.setup(
long_description_content_type="text/markdown",
url="https://github.com/alphacep/vosk-api",
packages=setuptools.find_packages(),
ext_modules=[CMakeExtension('_vosk', 'vosk')],
cmdclass={'build_ext': CMakeBuildExt, 'build_py' : CMakeBuildExtFirst},
ext_modules=[vosk_ext],
cmdclass = {'build_py' : build_py},
classifiers=[
'Programming Language :: Python :: 3',
'License :: OSI Approved :: Apache Software License',
@@ -25,5 +91,5 @@ setuptools.setup(
'Operating System :: MacOS :: MacOS X',
'Topic :: Software Development :: Libraries :: Python Modules'
],
python_requires='>=3.4',
python_requires='>=3.5',
)
+11 -3
View File
@@ -1,6 +1,8 @@
#!/usr/bin/python3
#!/usr/bin/env python3
from multiprocessing.dummy import Pool
from vosk import Model, KaldiRecognizer
import sys
import os
import wave
@@ -8,7 +10,7 @@ import json
model = Model("model")
for line in open(sys.argv[1]):
def recognize(line):
uid, fn = line.split()
wf = wave.open(fn, "rb")
rec = KaldiRecognizer(model, wf.getframerate())
@@ -23,5 +25,11 @@ for line in open(sys.argv[1]):
text = text + " " + jres['text']
jres = json.loads(rec.FinalResult())
text = text + " " + jres['text']
print (uid + text)
return (uid + text)
def main():
p = Pool(8)
texts = p.map(recognize, open(sys.argv[1]).readlines())
print ("\n".join(texts))
main()
+2 -1
View File
@@ -1 +1,2 @@
from .vosk import KaldiRecognizer, Model, SpkModel
from .vosk import KaldiRecognizer, Model, SpkModel, SetLogLevel
+122 -45
View File
@@ -1,4 +1,4 @@
// Copyright 2019 Alpha Cephei Inc.
// Copyright 2019-2020 Alpha Cephei Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -44,10 +44,9 @@ KaldiRecognizer::KaldiRecognizer(Model *model, float sample_frequency) : model_(
model_->hclg_fst_ ? *model_->hclg_fst_ : *decode_fst_,
feature_pipeline_);
frame_offset_ = 0;
input_finalized_ = false;
spk_feature_ = NULL;
InitState();
InitRescoring();
}
@@ -88,10 +87,9 @@ KaldiRecognizer::KaldiRecognizer(Model *model, float sample_frequency, char cons
model_->hclg_fst_ ? *model_->hclg_fst_ : *decode_fst_,
feature_pipeline_);
frame_offset_ = 0;
input_finalized_ = false;
spk_feature_ = NULL;
InitState();
InitRescoring();
}
@@ -120,18 +118,16 @@ KaldiRecognizer::KaldiRecognizer(Model *model, SpkModel *spk_model, float sample
model_->hclg_fst_ ? *model_->hclg_fst_ : *decode_fst_,
feature_pipeline_);
frame_offset_ = 0;
input_finalized_ = false;
spk_feature_ = new OnlineMfcc(spk_model_->spkvector_mfcc_opts);
InitState();
InitRescoring();
}
KaldiRecognizer::~KaldiRecognizer() {
delete decoder_;
delete feature_pipeline_;
delete silence_weighting_;
delete decoder_;
delete g_fst_;
delete decode_fst_;
delete spk_feature_;
@@ -142,6 +138,15 @@ KaldiRecognizer::~KaldiRecognizer() {
spk_model_->Unref();
}
void KaldiRecognizer::InitState()
{
frame_offset_ = 0;
samples_processed_ = 0;
samples_round_start_ = 0;
state_ = RECOGNIZER_INITIALIZED;
}
void KaldiRecognizer::InitRescoring()
{
if (model_->std_lm_fst_) {
@@ -159,8 +164,37 @@ void KaldiRecognizer::CleanUp()
delete silence_weighting_;
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_->trans_model_, model_->feature_info_.silence_weighting_config, 3);
frame_offset_ += decoder_->NumFramesDecoded();
decoder_->InitDecoding(frame_offset_);
if (spk_model_) {
delete spk_feature_;
spk_feature_ = new OnlineMfcc(spk_model_->spkvector_mfcc_opts);
}
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
// cause a huge accuracy drop since it happens not very frequently.
// Also restart if we retrieved final result already
if (decoder_ == NULL || state_ == RECOGNIZER_FINALIZED || frame_offset_ > 20000) {
samples_round_start_ += samples_processed_;
samples_processed_ = 0;
frame_offset_ = 0;
delete decoder_;
delete feature_pipeline_;
feature_pipeline_ = new kaldi::OnlineNnet2FeaturePipeline (model_->feature_info_);
decoder_ = new kaldi::SingleUtteranceNnet3Decoder(model_->nnet3_decoding_config_,
*model_->trans_model_,
*model_->decodable_info_,
model_->hclg_fst_ ? *model_->hclg_fst_ : *decode_fst_,
feature_pipeline_);
} else {
decoder_->InitDecoding(frame_offset_);
}
}
void KaldiRecognizer::UpdateSilenceWeights()
@@ -205,14 +239,20 @@ bool KaldiRecognizer::AcceptWaveform(const float *fdata, int len)
bool KaldiRecognizer::AcceptWaveform(Vector<BaseFloat> &wdata)
{
if (input_finalized_) {
// Cleanup if we finalized previous utterance or the whole feature pipeline
if (!(state_ == RECOGNIZER_RUNNING || state_ == RECOGNIZER_INITIALIZED)) {
CleanUp();
input_finalized_ = false;
}
state_ = RECOGNIZER_RUNNING;
feature_pipeline_->AcceptWaveform(sample_frequency_, wdata);
UpdateSilenceWeights();
decoder_->AdvanceDecoding();
int step = static_cast<int>(sample_frequency_ * 0.2);
for (int i = 0; i < wdata.Dim(); i+= step) {
SubVector<BaseFloat> r = wdata.Range(i, std::min(step, wdata.Dim() - i));
feature_pipeline_->AcceptWaveform(sample_frequency_, r);
UpdateSilenceWeights();
decoder_->AdvanceDecoding();
}
samples_processed_ += wdata.Dim();
if (spk_feature_) {
spk_feature_->AcceptWaveform(sample_frequency_, wdata);
@@ -256,11 +296,22 @@ static void RunNnetComputation(const MatrixBase<BaseFloat> &features,
void KaldiRecognizer::GetSpkVector(Vector<BaseFloat> &xvector)
{
int num_frames = spk_feature_->NumFramesReady() - frame_offset_ * 3;
vector<int32> nonsilence_frames;
if (silence_weighting_->Active() && feature_pipeline_->NumFramesReady() > 0) {
silence_weighting_->ComputeCurrentTraceback(decoder_->Decoder(), true);
silence_weighting_->GetNonsilenceFrames(feature_pipeline_->NumFramesReady(),
frame_offset_ * 3,
&nonsilence_frames);
}
int num_frames = spk_feature_->NumFramesReady();
Matrix<BaseFloat> mfcc(num_frames, spk_feature_->Dim());
for (int i = 0; i < num_frames; ++i) {
if (std::find(nonsilence_frames.begin(),
nonsilence_frames.end(), i % 3) == nonsilence_frames.end())
continue;
Vector<BaseFloat> feat(spk_feature_->Dim());
spk_feature_->GetFrame(i + frame_offset_ * 3, &feat);
spk_feature_->GetFrame(i, &feat);
mfcc.CopyRowFromVec(feat, i);
}
SlidingWindowCmnOptions cmvn_opts;
@@ -274,17 +325,10 @@ void KaldiRecognizer::GetSpkVector(Vector<BaseFloat> &xvector)
RunNnetComputation(features, spk_model_->speaker_nnet, &compiler, &xvector);
}
const char* KaldiRecognizer::Result()
const char* KaldiRecognizer::GetResult()
{
if (!input_finalized_) {
decoder_->FinalizeDecoding();
input_finalized_ = true;
}
if (decoder_->NumFramesDecoded() == 0) {
last_result_ = "{\"text\": \"\"}";
return last_result_.c_str();
return StoreReturn("{\"text\": \"\"}");
}
kaldi::CompactLattice clat;
@@ -336,8 +380,8 @@ const char* KaldiRecognizer::Result()
for (int i = 0; i < size; i++) {
json::JSON word;
word["word"] = model_->word_syms_->Find(words[i]);
word["start"] = (frame_offset_ + times[i].first) * 0.03;
word["end"] = (frame_offset_ + times[i].second) * 0.03;
word["start"] = samples_round_start_ / sample_frequency_ + (frame_offset_ + times[i].first) * 0.03;
word["end"] = samples_round_start_ / sample_frequency_ + (frame_offset_ + times[i].second) * 0.03;
word["conf"] = conf[i];
obj["result"].append(word);
@@ -356,17 +400,21 @@ const char* KaldiRecognizer::Result()
}
}
last_result_ = obj.dump();
return last_result_.c_str();
return StoreReturn(obj.dump());
}
const char* KaldiRecognizer::PartialResult()
{
if (state_ != RECOGNIZER_RUNNING) {
return StoreReturn("{\"text\": \"\"}");
}
json::JSON res;
if (decoder_->NumFramesDecoded() == 0) {
res["partial"] = "";
last_result_ = res.dump();
return last_result_.c_str();
return StoreReturn(res.dump());
}
kaldi::Lattice lat;
@@ -384,21 +432,50 @@ const char* KaldiRecognizer::PartialResult()
}
res["partial"] = text.str();
last_result_ = res.dump();
return last_result_.c_str();
return StoreReturn(res.dump());
}
const char* KaldiRecognizer::Result()
{
if (state_ != RECOGNIZER_RUNNING) {
return StoreReturn("{\"text\": \"\"}");
}
decoder_->FinalizeDecoding();
state_ = RECOGNIZER_ENDPOINT;
return GetResult();
}
const char* KaldiRecognizer::FinalResult()
{
if (!input_finalized_) {
feature_pipeline_->InputFinished();
UpdateSilenceWeights();
decoder_->AdvanceDecoding();
decoder_->FinalizeDecoding();
input_finalized_ = true;
return Result();
} else {
last_result_ = "{\"text\": \"\"}";
return last_result_.c_str();
if (state_ != RECOGNIZER_RUNNING) {
return StoreReturn("{\"text\": \"\"}");
}
feature_pipeline_->InputFinished();
UpdateSilenceWeights();
decoder_->AdvanceDecoding();
decoder_->FinalizeDecoding();
state_ = RECOGNIZER_FINALIZED;
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
const char *KaldiRecognizer::StoreReturn(const string &res)
{
last_result_ = res;
return last_result_.c_str();
}
+15 -1
View File
@@ -29,6 +29,13 @@
using namespace kaldi;
enum KaldiRecognizerState {
RECOGNIZER_INITIALIZED,
RECOGNIZER_RUNNING,
RECOGNIZER_ENDPOINT,
RECOGNIZER_FINALIZED
};
class KaldiRecognizer {
public:
KaldiRecognizer(Model *model, float sample_frequency);
@@ -43,11 +50,14 @@ class KaldiRecognizer {
const char* PartialResult();
private:
void InitState();
void InitRescoring();
void CleanUp();
void UpdateSilenceWeights();
bool AcceptWaveform(Vector<BaseFloat> &wdata);
void GetSpkVector(Vector<BaseFloat> &xvector);
const char *GetResult();
const char *StoreReturn(const string &res);
Model *model_;
SingleUtteranceNnet3Decoder *decoder_;
@@ -63,6 +73,10 @@ class KaldiRecognizer {
float sample_frequency_;
int32 frame_offset_;
bool input_finalized_;
int64 samples_processed_;
int64 samples_round_start_;
KaldiRecognizerState state_;
string last_result_;
};
+105 -60
View File
@@ -14,19 +14,7 @@
//
// Possible model layout:
//
// * Default kaldi model with HCLG.fst
//
// * Lookahead model with const G.fst
//
// * Lookahead model with ngram G.fst
//
// * File disambig_tid.int required only for lookadhead models
//
// * File word_boundary.int is required if we want to have precise word timing information
// otherwise we don't do any word alignment. Optionally lexicon alignment can be done
// with corresponding C++ code inside kaldi recognizer.
// For details of possible model layout see doc/models.md section model-structure
#include "model.h"
@@ -45,17 +33,79 @@ static FstRegisterer<NGramFst<StdArc>> NGramFst_StdArc_registerer;
#ifdef __ANDROID__
#include <android/log.h>
static void AndroidLogHandler(const LogMessageEnvelope &env, const char *message)
static void KaldiLogHandler(const LogMessageEnvelope &env, const char *message)
{
__android_log_print(ANDROID_LOG_VERBOSE, "KaldiDemo", message, 1);
int priority;
if (env.severity > GetVerboseLevel())
return;
if (env.severity > LogMessageEnvelope::kInfo) {
priority = ANDROID_LOG_VERBOSE;
} else {
switch (env.severity) {
case LogMessageEnvelope::kInfo:
priority = ANDROID_LOG_INFO;
break;
case LogMessageEnvelope::kWarning:
priority = ANDROID_LOG_WARN;
break;
case LogMessageEnvelope::kAssertFailed:
priority = ANDROID_LOG_FATAL;
break;
case LogMessageEnvelope::kError:
default: // If not the ERROR, it still an error!
priority = ANDROID_LOG_ERROR;
break;
}
}
std::stringstream full_message;
full_message << env.func << "():" << env.file << ':'
<< env.line << ") " << message;
__android_log_print(priority, "VoskAPI", "%s", full_message.str().c_str());
}
#else
static void KaldiLogHandler(const LogMessageEnvelope &env, const char *message)
{
if (env.severity > GetVerboseLevel())
return;
// Modified default Kaldi logging so we can disable LOG messages.
std::stringstream full_message;
if (env.severity > LogMessageEnvelope::kInfo) {
full_message << "VLOG[" << env.severity << "] (";
} else {
switch (env.severity) {
case LogMessageEnvelope::kInfo:
full_message << "LOG (";
break;
case LogMessageEnvelope::kWarning:
full_message << "WARNING (";
break;
case LogMessageEnvelope::kAssertFailed:
full_message << "ASSERTION_FAILED (";
break;
case LogMessageEnvelope::kError:
default: // If not the ERROR, it still an error!
full_message << "ERROR (";
break;
}
}
// Add other info from the envelope and the message text.
full_message << "VoskAPI" << ':'
<< env.func << "():" << env.file << ':'
<< env.line << ") " << message;
// Print the complete message to stderr.
full_message << "\n";
std::cerr << full_message.str();
}
#endif
Model::Model(const char *model_path) : model_path_str_(model_path) {
#ifdef __ANDROID__
SetLogHandler(AndroidLogHandler);
#endif
SetLogHandler(KaldiLogHandler);
struct stat buffer;
string am_path = model_path_str_ + "/am/final.mdl";
@@ -75,10 +125,9 @@ Model::Model(const char *model_path) : model_path_str_(model_path) {
void Model::ConfigureV1()
{
const char *extra_args[] = {
"--min-active=200",
"--max-active=3000",
"--beam=10.0",
"--lattice-beam=2.0",
"--max-active=7000",
"--beam=13.0",
"--lattice-beam=6.0",
"--acoustic-scale=1.0",
"--frame-subsampling-factor=3",
@@ -87,6 +136,8 @@ void Model::ConfigureV1()
"--endpoint.rule2.min-trailing-silence=0.5",
"--endpoint.rule3.min-trailing-silence=1.0",
"--endpoint.rule4.min-trailing-silence=2.0",
"--print-args=false",
};
kaldi::ParseOptions po("");
@@ -99,23 +150,6 @@ void Model::ConfigureV1()
args.insert(args.end(), extra_args, extra_args + sizeof(extra_args) / sizeof(extra_args[0]));
po.Read(args.size(), args.data());
feature_info_.feature_type = "mfcc";
ReadConfigFromFile(model_path_str_ + "/mfcc.conf", &feature_info_.mfcc_opts);
feature_info_.mfcc_opts.frame_opts.allow_downsample = true; // It is safe to downsample
feature_info_.silence_weighting_config.silence_weight = 1e-3;
feature_info_.silence_weighting_config.silence_phones_str = endpoint_config_.silence_phones;
OnlineIvectorExtractionConfig ivector_extraction_opts;
ivector_extraction_opts.splice_config_rxfilename = model_path_str_ + "/ivector/splice.conf";
ivector_extraction_opts.cmvn_config_rxfilename = model_path_str_ + "/ivector/online_cmvn.conf";
ivector_extraction_opts.lda_mat_rxfilename = model_path_str_ + "/ivector/final.mat";
ivector_extraction_opts.global_cmvn_stats_rxfilename = model_path_str_ + "/ivector/global_cmvn.stats";
ivector_extraction_opts.diag_ubm_rxfilename = model_path_str_ + "/ivector/final.dubm";
ivector_extraction_opts.ivector_extractor_rxfilename = model_path_str_ + "/ivector/final.ie";
feature_info_.use_ivectors = true;
feature_info_.ivector_extractor_info.Init(ivector_extraction_opts);
nnet3_rxfilename_ = model_path_str_ + "/final.mdl";
hclg_fst_rxfilename_ = model_path_str_ + "/HCLG.fst";
hcl_fst_rxfilename_ = model_path_str_ + "/HCLr.fst";
@@ -125,6 +159,8 @@ void Model::ConfigureV1()
winfo_rxfilename_ = model_path_str_ + "/word_boundary.int";
carpa_rxfilename_ = model_path_str_ + "/rescore/G.carpa";
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";
}
void Model::ConfigureV2()
@@ -135,27 +171,6 @@ void Model::ConfigureV2()
decodable_opts_.Register(&po);
po.ReadConfigFile(model_path_str_ + "/conf/model.conf");
KALDI_LOG << "Decoding params beam=" << nnet3_decoding_config_.beam <<
" max-active=" << nnet3_decoding_config_.max_active <<
" lattice-beam=" << nnet3_decoding_config_.lattice_beam;
KALDI_LOG << "Silence phones " << endpoint_config_.silence_phones;
feature_info_.feature_type = "mfcc";
ReadConfigFromFile(model_path_str_ + "/conf/mfcc.conf", &feature_info_.mfcc_opts);
feature_info_.mfcc_opts.frame_opts.allow_downsample = true; // It is safe to downsample
feature_info_.silence_weighting_config.silence_weight = 1e-3;
feature_info_.silence_weighting_config.silence_phones_str = endpoint_config_.silence_phones;
OnlineIvectorExtractionConfig ivector_extraction_opts;
ivector_extraction_opts.splice_config_rxfilename = model_path_str_ + "/ivector/splice.conf";
ivector_extraction_opts.cmvn_config_rxfilename = model_path_str_ + "/ivector/online_cmvn.conf";
ivector_extraction_opts.lda_mat_rxfilename = model_path_str_ + "/ivector/final.mat";
ivector_extraction_opts.global_cmvn_stats_rxfilename = model_path_str_ + "/ivector/global_cmvn.stats";
ivector_extraction_opts.diag_ubm_rxfilename = model_path_str_ + "/ivector/final.dubm";
ivector_extraction_opts.ivector_extractor_rxfilename = model_path_str_ + "/ivector/final.ie";
feature_info_.use_ivectors = true;
feature_info_.ivector_extractor_info.Init(ivector_extraction_opts);
nnet3_rxfilename_ = model_path_str_ + "/am/final.mdl";
hclg_fst_rxfilename_ = model_path_str_ + "/graph/HCLG.fst";
@@ -166,12 +181,26 @@ void Model::ConfigureV2()
winfo_rxfilename_ = model_path_str_ + "/graph/phones/word_boundary.int";
carpa_rxfilename_ = model_path_str_ + "/rescore/G.carpa";
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";
}
void Model::ReadDataFiles()
{
struct stat buffer;
KALDI_LOG << "Decoding params beam=" << nnet3_decoding_config_.beam <<
" max-active=" << nnet3_decoding_config_.max_active <<
" 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
feature_info_.silence_weighting_config.silence_weight = 1e-3;
feature_info_.silence_weighting_config.silence_phones_str = endpoint_config_.silence_phones;
trans_model_ = new kaldi::TransitionModel();
nnet_ = new kaldi::nnet3::AmNnetSimple();
{
@@ -186,6 +215,22 @@ void Model::ReadDataFiles()
decodable_info_ = new nnet3::DecodableNnetSimpleLoopedInfo(decodable_opts_,
nnet_);
if (stat(final_ie_rxfilename_.c_str(), &buffer) == 0) {
KALDI_LOG << "Loading i-vector extractor from " << final_ie_rxfilename_;
OnlineIvectorExtractionConfig ivector_extraction_opts;
ivector_extraction_opts.splice_config_rxfilename = model_path_str_ + "/ivector/splice.conf";
ivector_extraction_opts.cmvn_config_rxfilename = model_path_str_ + "/ivector/online_cmvn.conf";
ivector_extraction_opts.lda_mat_rxfilename = model_path_str_ + "/ivector/final.mat";
ivector_extraction_opts.global_cmvn_stats_rxfilename = model_path_str_ + "/ivector/global_cmvn.stats";
ivector_extraction_opts.diag_ubm_rxfilename = model_path_str_ + "/ivector/final.dubm";
ivector_extraction_opts.ivector_extractor_rxfilename = model_path_str_ + "/ivector/final.ie";
feature_info_.use_ivectors = true;
feature_info_.ivector_extractor_info.Init(ivector_extraction_opts);
} else {
feature_info_.use_ivectors = false;
}
if (stat(hclg_fst_rxfilename_.c_str(), &buffer) == 0) {
KALDI_LOG << "Loading HCLG from " << hclg_fst_rxfilename_;
hclg_fst_ = fst::ReadFstKaldiGeneric(hclg_fst_rxfilename_);
+2
View File
@@ -61,6 +61,8 @@ protected:
string winfo_rxfilename_;
string carpa_rxfilename_;
string std_fst_rxfilename_;
string final_ie_rxfilename_;
string mfcc_conf_rxfilename_;
kaldi::OnlineEndpointConfig endpoint_config_;
kaldi::LatticeFasterDecoderConfig nnet3_decoding_config_;
+21
View File
@@ -1,4 +1,8 @@
#if SWIGPYTHON
%module(package="vosk", "threads"=1) vosk
#else
%module Vosk
#endif
%include <typemaps.i>
@@ -40,6 +44,14 @@ CSHARP_ARRAYS(char, byte)
#endif
#if SWIGJAVASCRIPT
%begin %{
#include <v8.h>
#include <node.h>
#include <node_buffer.h>
%}
#endif
%{
#include "vosk_api.h"
typedef struct VoskModel Model;
@@ -97,6 +109,12 @@ typedef struct {} KaldiRecognizer;
bool AcceptWaveform(const char *data, int len) {
return vosk_recognizer_accept_waveform($self, data, len);
}
#elif SWIGJAVASCRIPT
bool AcceptWaveform(SWIG_Object ptr) {
char* data = (char*) node::Buffer::Data(ptr);
size_t length = node::Buffer::Length(ptr);
return vosk_recognizer_accept_waveform($self, data, length);
}
#else
int AcceptWaveform(const char *data, int len) {
return vosk_recognizer_accept_waveform($self, data, len);
@@ -113,3 +131,6 @@ typedef struct {} KaldiRecognizer;
return vosk_recognizer_final_result($self);
}
}
%rename(SetLogLevel) vosk_set_log_level;
void vosk_set_log_level(int level);
+5
View File
@@ -90,3 +90,8 @@ void vosk_recognizer_free(VoskRecognizer *recognizer)
{
delete (KaldiRecognizer *)(recognizer);
}
void vosk_set_log_level(int log_level)
{
SetVerboseLevel(log_level);
}
+162
View File
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* This header contains the C API for Vosk speech recognition system */
#ifndef _VOSK_API_H_
#define _VOSK_API_H_
@@ -20,27 +21,188 @@
extern "C" {
#endif
/** Model stores all the data required for recognition
* it contains static data and can be shared across processing
* threads. */
typedef struct VoskModel VoskModel;
/** Speaker model is the same as model but contains the data
* for speaker identification. */
typedef struct VoskSpkModel VoskSpkModel;
/** Recognizer object is the main object which processes data.
* Each recognizer usually runs in own thread and takes audio as input.
* Once audio is processed recognizer returns JSON object as a string
* which represent decoded information - words, confidences, times, n-best lists,
* speaker information and so on */
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 */
VoskModel *vosk_model_new(const char *model_path);
/** Releases the model memory
*
* The model object is reference-counted so if some recognizer
* depends on this model, model might still stay alive. When
* last recognizer is released, model will be released too. */
void vosk_model_free(VoskModel *model);
/** 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 */
VoskSpkModel *vosk_spk_model_new(const char *model_path);
/** Releases the model memory
*
* The model object is reference-counted so if some recognizer
* depends on this model, model might still stay alive. When
* last recognizer is released, model will be released too. */
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 */
VoskRecognizer *vosk_recognizer_new(VoskModel *model, float sample_rate);
/** Creates the recognizer object with speaker recognition
*
* With the speaker recognition mode the recognizer not just recognize
* text but also return speaker vectors one can use for speaker identification
*
* @param spk_model speaker model for speaker identification
* @param sample_rate The sample rate of the audio you going to feed into the recognizer
* @returns recognizer object */
VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, VoskSpkModel *spk_model, float sample_rate);
/** Creates the recognizer object with the grammar
*
* Sometimes when you want to improve recognition accuracy and when you don't need
* to recognize large vocabulary you can specify a list of words to recognize. This
* will improve recognizer speed and accuracy but might return [unk] if user said
* something different.
*
* 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 grammar The string with the list of words to recognize, for example "one two three four five [unk]"
*
* @returns recognizer object */
VoskRecognizer *vosk_recognizer_new_grm(VoskModel *model, float sample_rate, const char *grammar);
/** Accept voice data
*
* accept and process new chunk of voice data
*
* @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 */
int vosk_recognizer_accept_waveform(VoskRecognizer *recognizer, const char *data, int length);
/** Same as above but the version with the short data for language bindings where you have
* audio as array of shorts */
int vosk_recognizer_accept_waveform_s(VoskRecognizer *recognizer, const short *data, int length);
/** Same as above but the version with the float data for language bindings where you have
* audio as array of floats */
int vosk_recognizer_accept_waveform_f(VoskRecognizer *recognizer, const float *data, int length);
/** Returns speech recognition result
*
* @returns the result in JSON format which contains decoded line, decoded
* words, times in seconds and confidences. You can parse this result
* with any json parser
*
* <pre>
* {
* "result" : [{
* "conf" : 1.000000,
* "end" : 1.110000,
* "start" : 0.870000,
* "word" : "what"
* }, {
* "conf" : 1.000000,
* "end" : 1.530000,
* "start" : 1.110000,
* "word" : "zero"
* }, {
* "conf" : 1.000000,
* "end" : 1.950000,
* "start" : 1.530000,
* "word" : "zero"
* }, {
* "conf" : 1.000000,
* "end" : 2.340000,
* "start" : 1.950000,
* "word" : "zero"
* }, {
* "conf" : 1.000000,
* "end" : 2.610000,
* "start" : 2.340000,
* "word" : "one"
* }],
* "text" : "what zero zero zero one"
* }
* </pre>
*/
const char *vosk_recognizer_result(VoskRecognizer *recognizer);
/** Returns partial speech recognition
*
* @returns partial speech recognition text which is not yet finalized.
* result may change as recognizer process more data.
*
* <pre>
* {
* "partial" : "cyril one eight zero"
* }
* </pre>
*/
const char *vosk_recognizer_partial_result(VoskRecognizer *recognizer);
/** Returns speech recognition result. Same as result, but doesn't wait for silence
* You usually call it in the end of the stream to get final bits of audio. It
* flushes the feature pipeline, so all remaining audio chunks got processed.
*
* @returns speech result in JSON format.
*/
const char *vosk_recognizer_final_result(VoskRecognizer *recognizer);
/** Releases recognizer object
*
* Underlying model is also unreferenced and if needed released */
void vosk_recognizer_free(VoskRecognizer *recognizer);
/** Set log level for Kaldi messages
*
* @param log_level the level
* 0 - default value to print info and error messages but no debug
* less than 0 - don't print info messages
* greather than 0 - more verbose mode
*/
void vosk_set_log_level(int log_level);
#ifdef __cplusplus
}
#endif
+40 -18
View File
@@ -10,6 +10,9 @@ RUN apt-get update && \
libffi-dev \
libpcre3-dev \
zlib1g-dev \
automake \
autoconf \
libtool \
&& rm -rf /var/lib/apt/lists/*
RUN cd /opt \
@@ -20,24 +23,6 @@ RUN cd /opt \
&& cd .. \
&& rm -rf swig-4.0.1.tar.gz swig-4.0.1
ARG OPENBLAS_ARCH=ARMV7
ARG ARM_HARDWARE_OPTS="-mfloat-abi=hard -mfpu=neon"
RUN cd /opt \
&& export OPENFST_CONFIGURE="--enable-static --enable-shared --enable-far --enable-ngram-fsts --enable-lookahead-fsts --with-pic --disable-bin --host=${CROSS_TRIPLE} --build=x86-linux-gnu" \
&& git clone -b lookahead --single-branch https://github.com/alphacep/kaldi \
&& cd kaldi/tools \
&& git clone -b v0.3.7 --single-branch https://github.com/xianyi/OpenBLAS \
&& make PREFIX=$(pwd)/OpenBLAS/install TARGET="${OPENBLAS_ARCH}" HOSTCC=gcc USE_LOCKING=1 USE_THREAD=0 -C OpenBLAS all install \
&& sed -i 's:status=0:exit 0:g' extras/check_dependencies.sh \
&& make -j 10 openfst \
&& cd /opt/kaldi/src \
&& sed -i "s:TARGET_ARCH=\"\`uname -m\`\":TARGET_ARCH=$(echo $CROSS_TRIPLE|cut -d - -f 1):g" configure \
&& sed -i "s:-mfloat-abi=hard -mfpu=neon:${ARM_HARDWARE_OPTS}:g" makefiles/linux_openblas_arm.mk \
&& sed -i "s: -O1 : -O3 :g" makefiles/linux_openblas_arm.mk \
&& ./configure --mathlib=OPENBLAS --shared --use-cuda=no \
&& make -j 10 online2 lm \
&& find /opt/kaldi -name "*.o" -exec rm {} \;
RUN cd /opt \
&& wget -q https://github.com/openssl/openssl/archive/OpenSSL_1_0_2u.tar.gz \
&& tar xf OpenSSL_1_0_2u.tar.gz \
@@ -80,3 +65,40 @@ RUN cd /opt \
&& make -j $(nproc) \
&& make install \
&& rm -rf /opt/cpython-3.6.10 /opt/cpython-3.6.10-cross /opt/v3.6.10.tar.gz
RUN cd /opt \
&& wget -q https://github.com/python/cpython/archive/v3.8.3.tar.gz \
&& tar xf v3.8.3.tar.gz \
&& cp -r cpython-3.8.3 cpython-3.8.3-cross \
&& cd /opt/cpython-3.8.3 \
&& AR=/usr/bin/ar RANLIB=/usr/bin/ranlib CPP=/usr/bin/cpp CXX=/usr/bin/g++ CC=/usr/bin/gcc ./configure --prefix="/opt/python/cp3.8-cp3.8m" \
&& make -j $(nproc) \
&& make install \
&& /opt/python/cp3.8-cp3.8m/bin/pip3 install -U pip \
&& /opt/python/cp3.8-cp3.8m/bin/pip3 install -U wheel \
&& cd /opt/cpython-3.8.3-cross \
&& export PATH=/opt/python/cp3.8-cp3.8m/bin:$PATH \
&& ./configure --prefix=$CROSS_ROOT --with-openssl=$CROSS_ROOT --host=${CROSS_TRIPLE} --build=x86-linux-gnu --disable-ipv6 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no ac_cv_have_long_long_format=yes \
&& make -j $(nproc) \
&& make install \
&& rm -rf /opt/cpython-3.8.3 /opt/cpython-3.8.3-cross /opt/v3.8.3.tar.gz
ARG OPENBLAS_ARCH=ARMV7
ARG ARM_HARDWARE_OPTS="-mfloat-abi=hard -mfpu=neon"
RUN cd /opt \
&& git clone -b lookahead --single-branch https://github.com/alphacep/kaldi \
&& cd kaldi/tools \
&& git clone -b v0.3.7 --single-branch https://github.com/xianyi/OpenBLAS \
&& make PREFIX=$(pwd)/OpenBLAS/install TARGET="${OPENBLAS_ARCH}" HOSTCC=gcc USE_LOCKING=1 USE_THREAD=0 -C OpenBLAS all install \
&& git clone https://github.com/alphacep/openfst openfst \
&& cd openfst \
&& autoreconf -i \
&& ./configure --prefix=/opt/kaldi/tools/openfst --enable-static --enable-shared --enable-far --enable-ngram-fsts --enable-lookahead-fsts --with-pic --disable-bin --host=${CROSS_TRIPLE} --build=x86-linux-gnu \
&& make -j 10 && make install \
&& cd /opt/kaldi/src \
&& sed -i "s:TARGET_ARCH=\"\`uname -m\`\":TARGET_ARCH=$(echo $CROSS_TRIPLE|cut -d - -f 1):g" configure \
&& sed -i "s:-mfloat-abi=hard -mfpu=neon:${ARM_HARDWARE_OPTS}:g" makefiles/linux_openblas_arm.mk \
&& sed -i "s: -O1 : -O3 :g" makefiles/linux_openblas_arm.mk \
&& ./configure --mathlib=OPENBLAS --shared --use-cuda=no \
&& make -j 10 online2 lm \
&& find /opt/kaldi -name "*.o" -exec rm {} \;
+18 -21
View File
@@ -7,29 +7,11 @@ RUN yum -y update && yum -y install \
wget \
openssl-devel \
pcre-devel \
automake \
autoconf \
libtool \
&& yum clean all
RUN cd /opt \
&& wget https://github.com/Kitware/CMake/releases/download/v3.16.2/cmake-3.16.2.tar.gz \
&& tar xf cmake-3.16.2.tar.gz \
&& cd cmake-3.16.2 \
&& ./configure --prefix=/usr && make -j 10 && make install \
&& cd .. \
&& rm -rf cmake-3.16.2 cmake-3.16.2.tar.gz
RUN cd /opt \
&& export OPENFST_CONFIGURE="--enable-static --enable-shared --enable-far --enable-ngram-fsts --enable-lookahead-fsts --with-pic --disable-bin" \
&& git clone -b lookahead --single-branch https://github.com/alphacep/kaldi \
&& cd kaldi/tools \
&& git clone -b v0.3.7 --single-branch https://github.com/xianyi/OpenBLAS \
&& make PREFIX=$(pwd)/OpenBLAS/install TARGET=NEHALEM USE_LOCKING=1 USE_THREAD=0 -C OpenBLAS all install \
&& sed -i 's:status=0:exit 0:g' extras/check_dependencies.sh \
&& make -j 10 openfst \
&& cd ../src \
&& ./configure --mathlib=OPENBLAS --shared --use-cuda=no \
&& make -j 10 online2 lm \
&& find /opt/kaldi -name "*.o" -exec rm {} \;
RUN cd /opt \
&& wget -O swig-4.0.1.tar.gz https://sourceforge.net/projects/swig/files/swig/swig-4.0.1/swig-4.0.1.tar.gz/download \
&& tar xf swig-4.0.1.tar.gz \
@@ -37,3 +19,18 @@ RUN cd /opt \
&& ./configure --prefix=/usr && make -j 10 && make install \
&& cd .. \
&& rm -rf swig-4.0.1.tar.gz swig-4.0.1
RUN cd /opt \
&& git clone -b lookahead --single-branch https://github.com/alphacep/kaldi \
&& cd kaldi/tools \
&& git clone -b v0.3.7 --single-branch https://github.com/xianyi/OpenBLAS \
&& make PREFIX=$(pwd)/OpenBLAS/install TARGET=NEHALEM USE_LOCKING=1 USE_THREAD=0 -C OpenBLAS all install \
&& git clone https://github.com/alphacep/openfst openfst \
&& cd openfst \
&& autoreconf -i \
&& ./configure --prefix=/opt/kaldi/tools/openfst --enable-static --enable-shared --enable-far --enable-ngram-fsts --enable-lookahead-fsts --with-pic --disable-bin \
&& make -j 10 && make install \
&& cd /opt/kaldi/src \
&& ./configure --mathlib=OPENBLAS --shared --use-cuda=no \
&& make -j 10 online2 lm \
&& find /opt/kaldi -name "*.o" -exec rm {} \;
+16 -4
View File
@@ -2,24 +2,36 @@
set -e -x
ORIG_PATH=$PATH
for pyver in 3.6 3.7; do
for pyver in 3.6 3.7 3.8; do
export KALDI_ROOT=/opt/kaldi
export WHEEL_FLAGS=`$CROSS_ROOT/bin/python${pyver}-config --cflags`
export PATH=/opt/python/cp${pyver}-cp${pyver}m/bin:$ORIG_PATH
echo $CROSS_TRIPLE
export VOSK_SOURCE=/io/src
# Python 3.8 somehow changed syconfig file name
sysconfig_bit="m"
if [ $pyver == "3.8" ]; then
sysconfig_bit=""
fi
case $CROSS_TRIPLE in
*arm-*)
export _PYTHON_HOST_PLATFORM=linux-armv6l
export _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_${sysconfig_bit}_linux_arm-linux-gnueabihf
;;
*armv7-*)
export _PYTHON_HOST_PLATFORM=linux-armv7l
export _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_${sysconfig_bit}_linux_arm-linux-gnueabihf
;;
*aarch64-*)
export _PYTHON_HOST_PLATFORM=linux-aarch64
export _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_${sysconfig_bit}_linux_aarch64-linux-gnu
;;
esac
export PYTHONHOME=$CROSS_ROOT
export PYTHONPATH=/opt/python/cp${pyver}-cp${pyver}m/lib/python${pyver}/site-packages:/opt/python/cp${pyver}-cp${pyver}m/lib/python${pyver}/lib-dynload
pip3 wheel /io/python -w /io/wheelhouse
rm -rf /io/python/build
pip${pyver} -v wheel /io/python -w /io/wheelhouse
done
+3 -2
View File
@@ -5,9 +5,10 @@ export KALDI_ROOT=/opt/kaldi
# Compile wheels
for pypath in /opt/python/cp3[56789]*; do
export WHEEL_FLAGS=`${pypath}/bin/python3-config --cflags`
export VOSK_SOURCE=/io/src
mkdir -p /opt/wheelhouse
"${pypath}/bin/pip" wheel /io/python -w /opt/wheelhouse
rm -rf /io/python/build
"${pypath}/bin/pip" -v wheel /io/python -w /opt/wheelhouse
done
# Bundle external shared libraries into the wheels
+3
View File
@@ -0,0 +1,3 @@
exports.printMsg = function() {
console.log("This is a message from the Vosk package");
}
+20
View File
@@ -0,0 +1,20 @@
{
"name": "vosk-js",
"version": "0.3.0",
"description": "Node binding for continuous voice recoginition through vosk-api.",
"repository": {
"type": "git",
"url": "git://github.com/alphacep/vosk-api.git"
},
"main": "index.js",
"keywords": [
"speech",
"speech recognition",
"voice"
],
"author": "Alpha Cephei Inc.",
"license": "Apache 2.0",
"engines": {
"node": ">= 12.x.x"
}
}