Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4333c3c242 | |||
| b831c9ad57 | |||
| e5c08f7710 | |||
| 51c2968595 | |||
| 5993376322 | |||
| c4281622b9 | |||
| 9d26014de2 | |||
| f6c115d215 | |||
| 6bd102d778 | |||
| d3d6af5712 | |||
| 876093446f | |||
| 336f219f09 | |||
| 584251cbdc | |||
| a34995a788 | |||
| 998e5da227 | |||
| e04c15e367 | |||
| b81f69d407 | |||
| 0ac2064281 | |||
| 1d00bd244e | |||
| 8f5efc58c9 | |||
| a0c5ae1b5e | |||
| 99f48f9de1 | |||
| 1948b23f32 | |||
| c9eb572fc5 | |||
| 7d9895ff81 | |||
| d507210ef8 | |||
| db0a3d23d5 | |||
| f4f920f3cd | |||
| 75993ea276 | |||
| ee9bacb092 | |||
| b1e775c67b | |||
| d631e567aa | |||
| 9edf45be42 | |||
| 8b4b3c646a | |||
| 31bb0557d9 | |||
| 4593183cf9 | |||
| fdc45f1187 | |||
| b3d3c6d12c | |||
| f5f0794def | |||
| 55664fcca0 | |||
| afbf330f16 | |||
| 25aadf61bc | |||
| be47056467 | |||
| 8f623e0aea | |||
| 78025435e4 | |||
| 910455802e | |||
| b12914955c | |||
| dfe11eaf83 | |||
| 37fbe1a52b | |||
| af11bb2361 | |||
| 8da8697c1e | |||
| 944dc87531 | |||
| 5c4dd4644e | |||
| 9bbd172cfd | |||
| dbf9de77c3 | |||
| 8b790cd162 | |||
| 80219066e9 | |||
| 26fa5f098f | |||
| d75bb36131 | |||
| 30c5e8ca79 | |||
| c00e36fab6 | |||
| 80e60b9118 | |||
| e3a95a44bc | |||
| 86caf526f5 | |||
| e09f32b4b4 | |||
| 3803ab345d | |||
| 889b43136f | |||
| b517cf46af | |||
| ffd810fe00 | |||
| a1a0ed70a1 | |||
| 1554d9ede7 | |||
| 6f3190d83d | |||
| 3caaa32ec0 | |||
| 3facf3ccf5 | |||
| fad954e6e3 | |||
| c4809cb618 | |||
| a241423baf | |||
| 1e9421dd38 | |||
| b09ffda760 | |||
| aeff663a7c | |||
| fcd17fcd4c | |||
| feffb2711d | |||
| f76e5b592f | |||
| 71bdc900e3 | |||
| 96bbf5abc2 | |||
| df9424a228 | |||
| 3310acaf54 | |||
| e8722d462d | |||
| 14b2c13ed6 | |||
| 19af324096 | |||
| 0ca7b94e08 | |||
| 04ed310229 | |||
| 7ac33d521c | |||
| 08ada63da4 | |||
| cef3fd72fb | |||
| bca0b86e37 | |||
| bf973ff434 | |||
| a172d60b20 | |||
| 060e4395c2 | |||
| 03f1417454 |
+25
-2
@@ -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/*.cc
|
||||
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
|
||||
|
||||
@@ -1,114 +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
|
||||
|
||||
[](https://travis-ci.com/alphacep/vosk-api)
|
||||
|
||||
Language bindings for Vosk and Kaldi to access speech recognition from various languages and on various platforms
|
||||
### Models for different languages
|
||||
|
||||
* Python on Linux, Windows and RPi
|
||||
* Node
|
||||
* Android
|
||||
* iOS
|
||||
For information about models see [the documentation on available models](https://alphacephei.com/vosk/models.html).
|
||||
|
||||
## Android build
|
||||
### Contact Us
|
||||
|
||||
```
|
||||
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.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
#### 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
|
||||
```
|
||||
|
||||
## 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
|
||||
python3 ./test_simple.py test.wav
|
||||
```
|
||||
|
||||
There are models for other languages (English, Chinese, Spanish, Portuguese, German, French, Russian) available too at https://github.com/alphacep/kaldi-android-demo/releases
|
||||
|
||||
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)
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -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")
|
||||
@@ -23,6 +26,8 @@ set(API_SOURCES
|
||||
"${PROJECT_SOURCE_DIR}/../src/model.h"
|
||||
"${PROJECT_SOURCE_DIR}/../src/spk_model.cc"
|
||||
"${PROJECT_SOURCE_DIR}/../src/spk_model.h"
|
||||
"${PROJECT_SOURCE_DIR}/../src/vosk_api.cc"
|
||||
"${PROJECT_SOURCE_DIR}/../src/vosk_api.h"
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DFST_NO_DYNAMIC_LINKING")
|
||||
@@ -43,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
|
||||
|
||||
+30
-19
@@ -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 \
|
||||
@@ -125,6 +136,6 @@ CXX=$CXX CXXFLAGS="$ARCHFLAGS -O3 -DFST_NO_DYNAMIC_LINKING" ./configure --use-cu
|
||||
--fst-root=${WORKDIR}/local --fst-version=${OPENFST_VERSION}
|
||||
|
||||
make -j 8 depend
|
||||
make -j 8 online2
|
||||
make -j 8 online2 lm
|
||||
|
||||
done
|
||||
|
||||
@@ -31,7 +31,7 @@ android {
|
||||
}
|
||||
}
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64', 'x86'
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="edu.cmu.pocketsphinx">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.kaldi">
|
||||
</manifest>
|
||||
@@ -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);
|
||||
|
||||
@@ -31,7 +31,7 @@ import android.util.Log;
|
||||
/**
|
||||
* Main class to access recognizer functions. After configuration this class
|
||||
* starts a listener thread which records the data and recognizes it using
|
||||
* Pocketsphinx engine. Recognition events are passed to a client using
|
||||
* VOSK engine. Recognition events are passed to a client using
|
||||
* {@link RecognitionListener}
|
||||
*
|
||||
*/
|
||||
@@ -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,8 +164,7 @@ public class SpeechRecognizer {
|
||||
public boolean stop() {
|
||||
boolean result = stopRecognizerThread();
|
||||
if (result) {
|
||||
Log.i(TAG, "Stop recognition");
|
||||
mainHandler.post(new ResultEvent(recognizer.FinalResult(), true));
|
||||
mainHandler.post(new ResultEvent(recognizer.Result(), true));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -162,10 +177,7 @@ public class SpeechRecognizer {
|
||||
*/
|
||||
public boolean cancel() {
|
||||
boolean result = stopRecognizerThread();
|
||||
if (result) {
|
||||
Log.i(TAG, "Cancel recognition");
|
||||
}
|
||||
|
||||
recognizer.Result(); // Reset recognizer state
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -206,8 +218,6 @@ public class SpeechRecognizer {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.d(TAG, "Starting decoding");
|
||||
|
||||
short[] buffer = new short[bufferSize];
|
||||
|
||||
while (!interrupted()
|
||||
|
||||
+14
-7
@@ -11,6 +11,7 @@ KALDI_LIBS = \
|
||||
${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 \
|
||||
@@ -21,7 +22,7 @@ KALDI_LIBS = \
|
||||
${KALDI_ROOT}/tools/openfst/lib/libfst.a \
|
||||
${KALDI_ROOT}/tools/openfst/lib/libfstngram.a \
|
||||
${KALDI_ROOT}/tools/OpenBLAS/libopenblas.a \
|
||||
-lgfortran
|
||||
-lgfortran -lstdc++
|
||||
|
||||
all: test.exe
|
||||
|
||||
@@ -29,20 +30,26 @@ test.exe: libkaldiwrap.so test.cs
|
||||
mcs test.cs gen/*.cs
|
||||
|
||||
VOSK_SOURCES = \
|
||||
vosk_wrap.cc \
|
||||
vosk_wrap.c \
|
||||
../src/kaldi_recognizer.cc \
|
||||
../src/kaldi_recognizer.h \
|
||||
../src/model.cc \
|
||||
../src/model.h \
|
||||
../src/spk_model.cc \
|
||||
../src/spk_model.h
|
||||
../src/spk_model.h \
|
||||
../src/vosk_api.cc \
|
||||
../src/vosk_api.h
|
||||
|
||||
libkaldiwrap.so: $(VOSK_SOURCES)
|
||||
$(CXX) -fpermissive $(CFLAGS) $(CPPFLAGS) -shared -o $@ $(VOSK_SOURCES) $(KALDI_LIBS)
|
||||
|
||||
vosk_wrap.cc: ../src/vosk.i
|
||||
swig -csharp -dllimport "libkaldiwrap.so" \
|
||||
-namespace "Kaldi" -c++ -outdir gen -o vosk_wrap.cc ../src/vosk.i
|
||||
vosk_wrap.c: ../src/vosk.i
|
||||
mkdir -p gen
|
||||
swig -csharp -DSWIG_CSHARP_NO_EXCEPTION_HELPER -dllimport "libkaldiwrap" \
|
||||
-namespace "Kaldi" -outdir gen -o vosk_wrap.c ../src/vosk.i
|
||||
|
||||
run: test.exe
|
||||
mono test.exe
|
||||
|
||||
clean:
|
||||
$(RM) *.so vosk_wrap.cc *.o gen/*.cs test.exe
|
||||
$(RM) *.so vosk_wrap.c *.o gen/*.cs test.exe
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
See https://alphacephei.com/vosk/accuracy.html
|
||||
@@ -0,0 +1 @@
|
||||
See https://alphacephei.com/vosk/adaptation.html
|
||||
@@ -1,42 +0,0 @@
|
||||
## 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.
|
||||
@@ -0,0 +1 @@
|
||||
See https://alphacephei.com/vosk/models.html
|
||||
@@ -0,0 +1,3 @@
|
||||
This is a baseline for the vosk-api iOS demo. It requires a build of a
|
||||
Vosk-API library, mail contact@alphacephei.com for the details.
|
||||
|
||||
@@ -0,0 +1,477 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
92375222240C550B00DD6076 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92375221240C550B00DD6076 /* AppDelegate.swift */; };
|
||||
92375224240C550B00DD6076 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92375223240C550B00DD6076 /* ViewController.swift */; };
|
||||
92375227240C550B00DD6076 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 92375225240C550B00DD6076 /* Main.storyboard */; };
|
||||
92375229240C550B00DD6076 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 92375228240C550B00DD6076 /* Assets.xcassets */; };
|
||||
9237522C240C550B00DD6076 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9237522A240C550B00DD6076 /* LaunchScreen.storyboard */; };
|
||||
92375234240C558900DD6076 /* Vosk.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92375233240C558900DD6076 /* Vosk.swift */; };
|
||||
9237523C240C642000DD6076 /* libkaldiwrap.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9237523A240C642000DD6076 /* libkaldiwrap.a */; };
|
||||
92375244240C6DAF00DD6076 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92375243240C6DAF00DD6076 /* Accelerate.framework */; };
|
||||
92375246240C6DC900DD6076 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 92375245240C6DC900DD6076 /* libstdc++.tbd */; };
|
||||
92375266240C6EFE00DD6076 /* disambig_tid.int in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375248240C6E3D00DD6076 /* disambig_tid.int */; };
|
||||
92375267240C6EFE00DD6076 /* final.mdl in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375249240C6E3D00DD6076 /* final.mdl */; };
|
||||
92375268240C6EFE00DD6076 /* Gr.fst in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9237524A240C6E3D00DD6076 /* Gr.fst */; };
|
||||
92375269240C6EFE00DD6076 /* HCLr.fst in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9237524B240C6E3D00DD6076 /* HCLr.fst */; };
|
||||
9237526A240C6EFE00DD6076 /* mfcc.conf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375253240C6E3D00DD6076 /* mfcc.conf */; };
|
||||
9237526B240C6EFE00DD6076 /* word_boundary.int in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375254240C6E3D00DD6076 /* word_boundary.int */; };
|
||||
9237526C240C6EFE00DD6076 /* words.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375255240C6E3D00DD6076 /* words.txt */; };
|
||||
9237526E240C6F1500DD6076 /* final.dubm in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9237524D240C6E3D00DD6076 /* final.dubm */; };
|
||||
9237526F240C6F1500DD6076 /* final.ie in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9237524E240C6E3D00DD6076 /* final.ie */; };
|
||||
92375270240C6F1500DD6076 /* final.mat in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9237524F240C6E3D00DD6076 /* final.mat */; };
|
||||
92375271240C6F1500DD6076 /* global_cmvn.stats in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375250240C6E3D00DD6076 /* global_cmvn.stats */; };
|
||||
92375272240C6F1500DD6076 /* online_cmvn.conf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375251240C6E3D00DD6076 /* online_cmvn.conf */; };
|
||||
92375273240C6F1500DD6076 /* splice.conf in CopyFiles */ = {isa = PBXBuildFile; fileRef = 92375252240C6E3D00DD6076 /* splice.conf */; };
|
||||
92375274240C6F1E00DD6076 /* 10001-90210-01803.wav in Resources */ = {isa = PBXBuildFile; fileRef = 92375256240C6E3D00DD6076 /* 10001-90210-01803.wav */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
92375265240C6ECF00DD6076 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "model-en";
|
||||
dstSubfolderSpec = 7;
|
||||
files = (
|
||||
92375266240C6EFE00DD6076 /* disambig_tid.int in CopyFiles */,
|
||||
92375267240C6EFE00DD6076 /* final.mdl in CopyFiles */,
|
||||
92375268240C6EFE00DD6076 /* Gr.fst in CopyFiles */,
|
||||
92375269240C6EFE00DD6076 /* HCLr.fst in CopyFiles */,
|
||||
9237526A240C6EFE00DD6076 /* mfcc.conf in CopyFiles */,
|
||||
9237526B240C6EFE00DD6076 /* word_boundary.int in CopyFiles */,
|
||||
9237526C240C6EFE00DD6076 /* words.txt in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9237526D240C6F0400DD6076 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "model-en/ivector";
|
||||
dstSubfolderSpec = 7;
|
||||
files = (
|
||||
9237526E240C6F1500DD6076 /* final.dubm in CopyFiles */,
|
||||
9237526F240C6F1500DD6076 /* final.ie in CopyFiles */,
|
||||
92375270240C6F1500DD6076 /* final.mat in CopyFiles */,
|
||||
92375271240C6F1500DD6076 /* global_cmvn.stats in CopyFiles */,
|
||||
92375272240C6F1500DD6076 /* online_cmvn.conf in CopyFiles */,
|
||||
92375273240C6F1500DD6076 /* splice.conf in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9237521E240C550B00DD6076 /* VoskApiTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VoskApiTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
92375221240C550B00DD6076 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
92375223240C550B00DD6076 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
92375226240C550B00DD6076 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
92375228240C550B00DD6076 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
9237522B240C550B00DD6076 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
9237522D240C550B00DD6076 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
92375233240C558900DD6076 /* Vosk.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vosk.swift; sourceTree = "<group>"; };
|
||||
9237523A240C642000DD6076 /* libkaldiwrap.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libkaldiwrap.a; sourceTree = "<group>"; };
|
||||
92375243240C6DAF00DD6076 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
|
||||
92375245240C6DC900DD6076 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
|
||||
92375248240C6E3D00DD6076 /* disambig_tid.int */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = disambig_tid.int; sourceTree = "<group>"; };
|
||||
92375249240C6E3D00DD6076 /* final.mdl */ = {isa = PBXFileReference; lastKnownFileType = file; path = final.mdl; sourceTree = "<group>"; };
|
||||
9237524A240C6E3D00DD6076 /* Gr.fst */ = {isa = PBXFileReference; lastKnownFileType = file; path = Gr.fst; sourceTree = "<group>"; };
|
||||
9237524B240C6E3D00DD6076 /* HCLr.fst */ = {isa = PBXFileReference; lastKnownFileType = file; path = HCLr.fst; sourceTree = "<group>"; };
|
||||
9237524D240C6E3D00DD6076 /* final.dubm */ = {isa = PBXFileReference; lastKnownFileType = file; path = final.dubm; sourceTree = "<group>"; };
|
||||
9237524E240C6E3D00DD6076 /* final.ie */ = {isa = PBXFileReference; lastKnownFileType = file; path = final.ie; sourceTree = "<group>"; };
|
||||
9237524F240C6E3D00DD6076 /* final.mat */ = {isa = PBXFileReference; lastKnownFileType = file; path = final.mat; sourceTree = "<group>"; };
|
||||
92375250240C6E3D00DD6076 /* global_cmvn.stats */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = global_cmvn.stats; sourceTree = "<group>"; };
|
||||
92375251240C6E3D00DD6076 /* online_cmvn.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = online_cmvn.conf; sourceTree = "<group>"; };
|
||||
92375252240C6E3D00DD6076 /* splice.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = splice.conf; sourceTree = "<group>"; };
|
||||
92375253240C6E3D00DD6076 /* mfcc.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mfcc.conf; sourceTree = "<group>"; };
|
||||
92375254240C6E3D00DD6076 /* word_boundary.int */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = word_boundary.int; sourceTree = "<group>"; };
|
||||
92375255240C6E3D00DD6076 /* words.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = words.txt; sourceTree = "<group>"; };
|
||||
92375256240C6E3D00DD6076 /* 10001-90210-01803.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "10001-90210-01803.wav"; sourceTree = "<group>"; };
|
||||
92AA22AD244CDD1200DA464B /* vosk_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vosk_api.h; sourceTree = "<group>"; };
|
||||
92AA22AE244CDD5200DA464B /* bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bridging.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
9237521B240C550B00DD6076 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
92375246240C6DC900DD6076 /* libstdc++.tbd in Frameworks */,
|
||||
92375244240C6DAF00DD6076 /* Accelerate.framework in Frameworks */,
|
||||
9237523C240C642000DD6076 /* libkaldiwrap.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
92375215240C550A00DD6076 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92375239240C642000DD6076 /* Vosk */,
|
||||
92375220240C550B00DD6076 /* VoskApiTest */,
|
||||
9237521F240C550B00DD6076 /* Products */,
|
||||
92375242240C6DAF00DD6076 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9237521F240C550B00DD6076 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9237521E240C550B00DD6076 /* VoskApiTest.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92375220240C550B00DD6076 /* VoskApiTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92AA22AE244CDD5200DA464B /* bridging.h */,
|
||||
92375221240C550B00DD6076 /* AppDelegate.swift */,
|
||||
92375223240C550B00DD6076 /* ViewController.swift */,
|
||||
92375225240C550B00DD6076 /* Main.storyboard */,
|
||||
92375228240C550B00DD6076 /* Assets.xcassets */,
|
||||
9237522A240C550B00DD6076 /* LaunchScreen.storyboard */,
|
||||
9237522D240C550B00DD6076 /* Info.plist */,
|
||||
92375233240C558900DD6076 /* Vosk.swift */,
|
||||
);
|
||||
path = VoskApiTest;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92375239240C642000DD6076 /* Vosk */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92375247240C6E3D00DD6076 /* model-android */,
|
||||
92375256240C6E3D00DD6076 /* 10001-90210-01803.wav */,
|
||||
92AA22AD244CDD1200DA464B /* vosk_api.h */,
|
||||
9237523A240C642000DD6076 /* libkaldiwrap.a */,
|
||||
);
|
||||
name = Vosk;
|
||||
path = VoskApiTest/Vosk;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92375242240C6DAF00DD6076 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92375245240C6DC900DD6076 /* libstdc++.tbd */,
|
||||
92375243240C6DAF00DD6076 /* Accelerate.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
92375247240C6E3D00DD6076 /* model-android */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
92375248240C6E3D00DD6076 /* disambig_tid.int */,
|
||||
92375249240C6E3D00DD6076 /* final.mdl */,
|
||||
9237524A240C6E3D00DD6076 /* Gr.fst */,
|
||||
9237524B240C6E3D00DD6076 /* HCLr.fst */,
|
||||
9237524C240C6E3D00DD6076 /* ivector */,
|
||||
92375253240C6E3D00DD6076 /* mfcc.conf */,
|
||||
92375254240C6E3D00DD6076 /* word_boundary.int */,
|
||||
92375255240C6E3D00DD6076 /* words.txt */,
|
||||
);
|
||||
path = "model-android";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9237524C240C6E3D00DD6076 /* ivector */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9237524D240C6E3D00DD6076 /* final.dubm */,
|
||||
9237524E240C6E3D00DD6076 /* final.ie */,
|
||||
9237524F240C6E3D00DD6076 /* final.mat */,
|
||||
92375250240C6E3D00DD6076 /* global_cmvn.stats */,
|
||||
92375251240C6E3D00DD6076 /* online_cmvn.conf */,
|
||||
92375252240C6E3D00DD6076 /* splice.conf */,
|
||||
);
|
||||
path = ivector;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
9237521D240C550B00DD6076 /* VoskApiTest */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 92375230240C550B00DD6076 /* Build configuration list for PBXNativeTarget "VoskApiTest" */;
|
||||
buildPhases = (
|
||||
9237521A240C550B00DD6076 /* Sources */,
|
||||
9237521B240C550B00DD6076 /* Frameworks */,
|
||||
9237521C240C550B00DD6076 /* Resources */,
|
||||
92375265240C6ECF00DD6076 /* CopyFiles */,
|
||||
9237526D240C6F0400DD6076 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = VoskApiTest;
|
||||
productName = VoskApiTest;
|
||||
productReference = 9237521E240C550B00DD6076 /* VoskApiTest.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
92375216240C550A00DD6076 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0830;
|
||||
LastUpgradeCheck = 0920;
|
||||
ORGANIZATIONNAME = "Alpha Cephei";
|
||||
TargetAttributes = {
|
||||
9237521D240C550B00DD6076 = {
|
||||
CreatedOnToolsVersion = 8.3.2;
|
||||
LastSwiftMigration = 0920;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 92375219240C550A00DD6076 /* Build configuration list for PBXProject "VoskApiTest" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 92375215240C550A00DD6076;
|
||||
productRefGroup = 9237521F240C550B00DD6076 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
9237521D240C550B00DD6076 /* VoskApiTest */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
9237521C240C550B00DD6076 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
92375274240C6F1E00DD6076 /* 10001-90210-01803.wav in Resources */,
|
||||
9237522C240C550B00DD6076 /* LaunchScreen.storyboard in Resources */,
|
||||
92375229240C550B00DD6076 /* Assets.xcassets in Resources */,
|
||||
92375227240C550B00DD6076 /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
9237521A240C550B00DD6076 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
92375224240C550B00DD6076 /* ViewController.swift in Sources */,
|
||||
92375222240C550B00DD6076 /* AppDelegate.swift in Sources */,
|
||||
92375234240C558900DD6076 /* Vosk.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
92375225240C550B00DD6076 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
92375226240C550B00DD6076 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9237522A240C550B00DD6076 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
9237522B240C550B00DD6076 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
9237522E240C550B00DD6076 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = bridging.h;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9237522F240C550B00DD6076 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = bridging.h;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
92375231240C550B00DD6076 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = VoskApiTest/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/VoskApiTest/Vosk",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alphacephei.VoskApiTest;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_INSTALL_OBJC_HEADER = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = VoskApiTest/bridging.h;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
92375232240C550B00DD6076 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = VoskApiTest/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/VoskApiTest/Vosk",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alphacephei.VoskApiTest;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_INSTALL_OBJC_HEADER = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = VoskApiTest/bridging.h;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
92375219240C550A00DD6076 /* Build configuration list for PBXProject "VoskApiTest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
9237522E240C550B00DD6076 /* Debug */,
|
||||
9237522F240C550B00DD6076 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
92375230240C550B00DD6076 /* Build configuration list for PBXNativeTarget "VoskApiTest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
92375231240C550B00DD6076 /* Debug */,
|
||||
92375232240C550B00DD6076 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 92375216240C550A00DD6076 /* Project object */;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:VoskApiTest.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// AppDelegate.swift
|
||||
// VoskApiTest
|
||||
//
|
||||
// Created by Niсkolay Shmyrev on 01.03.20.
|
||||
// Copyright © 2020 Alpha Cephei. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
|
||||
// Override point for customization after application launch.
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="VoskApiTest" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<textView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" textAlignment="natural" id="CtX-mx-X98">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
<connections>
|
||||
<outlet property="mainText" destination="CtX-mx-X98" id="oJy-5J-NKp"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="32.799999999999997" y="32.833583208395808"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// ViewController.swift
|
||||
// VoskApiTest
|
||||
//
|
||||
// Created by Niсkolay Shmyrev on 01.03.20.
|
||||
// Copyright © 2020 Alpha Cephei. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ViewController: UIViewController {
|
||||
|
||||
@IBOutlet var mainText: UITextView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
DispatchQueue.main.async {
|
||||
self.mainText.text = "Processing file..."
|
||||
}
|
||||
let vosk = Vosk()
|
||||
let res = vosk.recognizeFile()
|
||||
DispatchQueue.main.async {
|
||||
self.mainText.text = res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
super.didReceiveMemoryWarning()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Vosk.swift
|
||||
// VoskApiTest
|
||||
//
|
||||
// Created by Niсkolay Shmyrev on 01.03.20.
|
||||
// Copyright © 2020 Alpha Cephei. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public final class Vosk {
|
||||
|
||||
func recognizeFile() -> String {
|
||||
var sres = ""
|
||||
if let resourcePath = Bundle.main.resourcePath {
|
||||
|
||||
let modelPath = resourcePath + "/model-en"
|
||||
|
||||
let model = vosk_model_new(modelPath);
|
||||
let recognizer = vosk_recognizer_new(model, 16000.0)
|
||||
|
||||
let audioFile = URL(fileURLWithPath: resourcePath + "/10001-90210-01803.wav")
|
||||
if let data = try? Data(contentsOf: audioFile) {
|
||||
let _ = data.withUnsafeBytes {
|
||||
vosk_recognizer_accept_waveform(recognizer, $0, Int32(data.count))
|
||||
}
|
||||
let res = vosk_recognizer_final_result(recognizer);
|
||||
sres = String(validatingUTF8: res!)!;
|
||||
print(sres);
|
||||
}
|
||||
|
||||
vosk_recognizer_free(recognizer)
|
||||
vosk_model_free(model)
|
||||
}
|
||||
return sres
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef _VOSK_API_H_
|
||||
#define _VOSK_API_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct VoskModel VoskModel;
|
||||
typedef struct VoskSpkModel VoskSpkModel;
|
||||
typedef struct VoskRecognizer VoskRecognizer;
|
||||
|
||||
VoskModel *vosk_model_new(const char *model_path);
|
||||
void vosk_model_free(VoskModel *model);
|
||||
|
||||
VoskSpkModel *vosk_spk_model_new(const char *model_path);
|
||||
void vosk_spk_model_free(VoskSpkModel *model);
|
||||
|
||||
VoskRecognizer *vosk_recognizer_new(VoskModel *model, float sample_rate);
|
||||
VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, VoskSpkModel *spk_model, float sample_rate);
|
||||
VoskRecognizer *vosk_recognizer_new_grm(VoskModel *model, float sample_rate, const char *grammar);
|
||||
int vosk_recognizer_accept_waveform(VoskRecognizer *recognizer, const char *data, int length);
|
||||
int vosk_recognizer_accept_waveform_s(VoskRecognizer *recognizer, const short *data, int length);
|
||||
int vosk_recognizer_accept_waveform_f(VoskRecognizer *recognizer, const float *data, int length);
|
||||
const char *vosk_recognizer_result(VoskRecognizer *recognizer);
|
||||
const char *vosk_recognizer_partial_result(VoskRecognizer *recognizer);
|
||||
const char *vosk_recognizer_final_result(VoskRecognizer *recognizer);
|
||||
void vosk_recognizer_free(VoskRecognizer *recognizer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VOSK_API_H_ */
|
||||
@@ -0,0 +1 @@
|
||||
#import "Vosk/vosk_api.h"
|
||||
+15
-7
@@ -11,6 +11,7 @@ KALDI_LIBS = \
|
||||
${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 \
|
||||
@@ -32,14 +33,16 @@ VOSK_SOURCES = \
|
||||
../src/model.cc \
|
||||
../src/model.h \
|
||||
../src/spk_model.cc \
|
||||
../src/spk_model.h
|
||||
../src/spk_model.h \
|
||||
../src/vosk_api.cc \
|
||||
../src/vosk_api.h
|
||||
|
||||
libvosk_jni.so: $(VOSK_SOURCES)
|
||||
$(CXX) -shared -o $@ $(CPPFLAGS) $(CFLAGS) $(VOSK_SOURCES) $(KALDI_LIBS)
|
||||
|
||||
vosk_wrap.cc: ../src/vosk.i
|
||||
mkdir -p org/kaldi
|
||||
swig -I../src -c++ \
|
||||
swig -c++ -I../src \
|
||||
-java -package org.kaldi \
|
||||
-outdir org/kaldi -o $@ $<
|
||||
|
||||
@@ -47,11 +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
|
||||
|
||||
run: model-en
|
||||
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 model-spk
|
||||
javac test/*.java org/kaldi/*.java
|
||||
java -Djava.library.path=. -cp . test.DecoderTest
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
Java API sample
|
||||
|
||||
Doesn't work on Windows or Mac yet, help to prepare the packaged jars is welcome.
|
||||
|
||||
For now to try it:
|
||||
|
||||
On Linux you can do
|
||||
|
||||
1. Build recent kaldi
|
||||
1. `git clone https://github.com/alphacep/vosk-api`
|
||||
1. `cd vosk-api/java`
|
||||
1. `export KALDI_ROOT=<KALDI_ROOT>`
|
||||
1. `export JAVA_HOME=<JAVA_HOME>`
|
||||
1. `make`
|
||||
1. `make run`
|
||||
|
||||
For details of the code you can check:
|
||||
|
||||
https://github.com/alphacep/vosk-api/blob/master/java/test/DecoderTest.java
|
||||
@@ -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,15 +19,17 @@ 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-en");
|
||||
Model model = new Model("model");
|
||||
SpkModel spkModel = new SpkModel("model-spk");
|
||||
KaldiRecognizer rec = new KaldiRecognizer(model, spkModel, 16000.0f);
|
||||
|
||||
int nbytes;
|
||||
byte[] b = new byte[4096];
|
||||
while ((nbytes = ais.read(b)) >= 0) {
|
||||
if (rec.AcceptWaveform(b, nbytes)) {
|
||||
if (rec.AcceptWaveform(b)) {
|
||||
System.out.println(rec.Result());
|
||||
} else {
|
||||
System.out.println(rec.PartialResult());
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
build
|
||||
node_modules
|
||||
vosk_wrap.cc
|
||||
@@ -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
|
||||
```
|
||||
@@ -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',
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require("fs");
|
||||
const { Readable } = require("stream");
|
||||
const wav = require("wav");
|
||||
|
||||
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");
|
||||
|
||||
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 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);
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +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 (Python COMPONENTS Interpreter Development)
|
||||
else()
|
||||
# docker case
|
||||
set(Python_INCLUDE_DIR "")
|
||||
set(Python_LIBRARY "")
|
||||
set(TOP_SRCDIR "/io")
|
||||
endif()
|
||||
|
||||
set(KALDI_ROOT "$ENV{KALDI_ROOT}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3 -DFST_NO_DYNAMIC_LINKING")
|
||||
include_directories("${TOP_SRCDIR}/src" "${KALDI_ROOT}/src" "${KALDI_ROOT}/tools/openfst/include" ${Python_INCLUDE_DIR})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{WHEEL_FLAGS}")
|
||||
|
||||
find_package(SWIG REQUIRED)
|
||||
include(${SWIG_USE_FILE})
|
||||
|
||||
set_property(SOURCE "${TOP_SRCDIR}/src/vosk.i" PROPERTY CPLUSPLUS ON)
|
||||
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.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/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)
|
||||
|
||||
set_target_properties(_vosk PROPERTIES LINK_FLAGS_RELEASE -s)
|
||||
@@ -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,10 +1,10 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from vosk import Model, KaldiRecognizer
|
||||
import sys
|
||||
import json
|
||||
|
||||
model = Model("model-en")
|
||||
model = Model("model")
|
||||
rec = KaldiRecognizer(model, 8000)
|
||||
|
||||
res = json.loads(rec.FinalResult())
|
||||
|
||||
Executable
+33
@@ -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())
|
||||
@@ -1,23 +1,23 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from vosk import Model, KaldiRecognizer
|
||||
import os
|
||||
|
||||
if not os.path.exists("model-en"):
|
||||
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.")
|
||||
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)
|
||||
|
||||
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-en")
|
||||
rec = KaldiRecognizer(model, 16000)
|
||||
|
||||
while True:
|
||||
data = stream.read(2000)
|
||||
data = stream.read(4000)
|
||||
if len(data) == 0:
|
||||
break
|
||||
if rec.AcceptWaveform(data):
|
||||
|
||||
@@ -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
|
||||
|
||||
if not os.path.exists("model-en"):
|
||||
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model-en' in the current folder.")
|
||||
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)
|
||||
|
||||
wf = wave.open(sys.argv[1], "rb")
|
||||
@@ -14,11 +16,11 @@ if wf.getnchannels() != 1 or wf.getsampwidth() != 2 or wf.getcomptype() != "NONE
|
||||
print ("Audio file must be WAV format mono PCM.")
|
||||
exit (1)
|
||||
|
||||
model = Model("model-en")
|
||||
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):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from vosk import Model, KaldiRecognizer, SpkModel
|
||||
import sys
|
||||
@@ -7,15 +7,15 @@ import json
|
||||
import os
|
||||
import numpy as np
|
||||
|
||||
model_path = "model-en"
|
||||
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())
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from vosk import Model, KaldiRecognizer
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
|
||||
if not os.path.exists("model-en"):
|
||||
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model-en' in the current folder.")
|
||||
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)
|
||||
|
||||
|
||||
model = Model("model-en")
|
||||
model = Model("model")
|
||||
|
||||
# Large vocabulary free form recognition
|
||||
rec = KaldiRecognizer(model, 16000)
|
||||
@@ -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):
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from vosk import Model, KaldiRecognizer
|
||||
import sys
|
||||
import os
|
||||
import wave
|
||||
|
||||
if not os.path.exists("model-en"):
|
||||
print ("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model-en' in the current folder.")
|
||||
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)
|
||||
|
||||
wf = wave.open(sys.argv[1], "rb")
|
||||
@@ -14,12 +14,12 @@ if wf.getnchannels() != 1 or wf.getsampwidth() != 2 or wf.getcomptype() != "NONE
|
||||
print ("Audio file must be WAV format mono PCM.")
|
||||
exit (1)
|
||||
|
||||
model = Model("model-en")
|
||||
model = Model("model")
|
||||
# You can also specify the possible word list
|
||||
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
@@ -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.3",
|
||||
version="0.3.9",
|
||||
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',
|
||||
)
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from multiprocessing.dummy import Pool
|
||||
from vosk import Model, KaldiRecognizer
|
||||
|
||||
import sys
|
||||
import os
|
||||
import wave
|
||||
import json
|
||||
|
||||
model = Model("model")
|
||||
|
||||
def recognize(line):
|
||||
uid, fn = line.split()
|
||||
wf = wave.open(fn, "rb")
|
||||
rec = KaldiRecognizer(model, wf.getframerate())
|
||||
|
||||
text = ""
|
||||
while True:
|
||||
data = wf.readframes(1000)
|
||||
if len(data) == 0:
|
||||
break
|
||||
if rec.AcceptWaveform(data):
|
||||
jres = json.loads(rec.Result())
|
||||
text = text + " " + jres['text']
|
||||
jres = json.loads(rec.FinalResult())
|
||||
text = text + " " + jres['text']
|
||||
return (uid + text)
|
||||
|
||||
def main():
|
||||
p = Pool(8)
|
||||
texts = p.map(recognize, open(sys.argv[1]).readlines())
|
||||
print ("\n".join(texts))
|
||||
|
||||
main()
|
||||
@@ -1 +1,2 @@
|
||||
from .vosk import KaldiRecognizer, Model, SpkModel
|
||||
from .vosk import KaldiRecognizer, Model, SpkModel, SetLogLevel
|
||||
|
||||
|
||||
+219
-97
@@ -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.
|
||||
@@ -20,120 +20,186 @@
|
||||
using namespace fst;
|
||||
using namespace kaldi::nnet3;
|
||||
|
||||
KaldiRecognizer::KaldiRecognizer(Model &model, float sample_frequency) : model_(model), spk_model_(0), sample_frequency_(sample_frequency) {
|
||||
KaldiRecognizer::KaldiRecognizer(Model *model, float sample_frequency) : model_(model), spk_model_(0), sample_frequency_(sample_frequency) {
|
||||
|
||||
feature_pipeline_ = new kaldi::OnlineNnet2FeaturePipeline (model_.feature_info_);
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_.trans_model_, model_.feature_info_.silence_weighting_config, 3);
|
||||
model_->Ref();
|
||||
|
||||
feature_pipeline_ = new kaldi::OnlineNnet2FeaturePipeline (model_->feature_info_);
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_->trans_model_, model_->feature_info_.silence_weighting_config, 3);
|
||||
|
||||
g_fst_ = NULL;
|
||||
decode_fst_ = NULL;
|
||||
|
||||
if (!model_.hclg_fst_) {
|
||||
if (model_.hcl_fst_ && model_.g_fst_) {
|
||||
decode_fst_ = LookaheadComposeFst(*model_.hcl_fst_, *model_.g_fst_, model_.disambig_);
|
||||
if (!model_->hclg_fst_) {
|
||||
if (model_->hcl_fst_ && model_->g_fst_) {
|
||||
decode_fst_ = LookaheadComposeFst(*model_->hcl_fst_, *model_->g_fst_, model_->disambig_);
|
||||
} else {
|
||||
KALDI_ERR << "Can't create decoding graph";
|
||||
}
|
||||
}
|
||||
|
||||
decoder_ = new kaldi::SingleUtteranceNnet3Decoder(model_.nnet3_decoding_config_,
|
||||
*model_.trans_model_,
|
||||
*model_.decodable_info_,
|
||||
model_.hclg_fst_ ? *model.hclg_fst_ : *decode_fst_,
|
||||
decoder_ = new kaldi::SingleUtteranceNnet3Decoder(model_->nnet3_decoding_config_,
|
||||
*model_->trans_model_,
|
||||
*model_->decodable_info_,
|
||||
model_->hclg_fst_ ? *model_->hclg_fst_ : *decode_fst_,
|
||||
feature_pipeline_);
|
||||
|
||||
frame_offset_ = 0;
|
||||
input_finalized_ = false;
|
||||
spk_feature_ = NULL;
|
||||
|
||||
InitState();
|
||||
InitRescoring();
|
||||
}
|
||||
|
||||
KaldiRecognizer::KaldiRecognizer(Model &model, float sample_frequency, char const *grammar) : model_(model), spk_model_(0), sample_frequency_(sample_frequency)
|
||||
KaldiRecognizer::KaldiRecognizer(Model *model, float sample_frequency, char const *grammar) : model_(model), spk_model_(0), sample_frequency_(sample_frequency)
|
||||
{
|
||||
feature_pipeline_ = new kaldi::OnlineNnet2FeaturePipeline (model_.feature_info_);
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_.trans_model_, model_.feature_info_.silence_weighting_config, 3);
|
||||
model_->Ref();
|
||||
|
||||
if (model_.hcl_fst_) {
|
||||
g_fst_.AddState();
|
||||
g_fst_.SetStart(0);
|
||||
g_fst_.AddState();
|
||||
g_fst_.SetFinal(1, fst::TropicalWeight::One());
|
||||
g_fst_.AddArc(1, StdArc(0, 0, fst::TropicalWeight::One(), 0));
|
||||
feature_pipeline_ = new kaldi::OnlineNnet2FeaturePipeline (model_->feature_info_);
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_->trans_model_, model_->feature_info_.silence_weighting_config, 3);
|
||||
|
||||
g_fst_ = new StdVectorFst();
|
||||
if (model_->hcl_fst_) {
|
||||
g_fst_->AddState();
|
||||
g_fst_->SetStart(0);
|
||||
g_fst_->AddState();
|
||||
g_fst_->SetFinal(1, fst::TropicalWeight::One());
|
||||
g_fst_->AddArc(1, StdArc(0, 0, fst::TropicalWeight::One(), 0));
|
||||
|
||||
// Create simple word loop FST
|
||||
std::stringstream ss(grammar);
|
||||
std::string token;
|
||||
stringstream ss(grammar);
|
||||
string token;
|
||||
|
||||
while (std::getline(ss, token, ' ')) {
|
||||
int32 id = model_.word_syms_->Find(token);
|
||||
g_fst_.AddArc(0, StdArc(id, id, fst::TropicalWeight::One(), 1));
|
||||
while (getline(ss, token, ' ')) {
|
||||
int32 id = model_->word_syms_->Find(token);
|
||||
g_fst_->AddArc(0, StdArc(id, id, fst::TropicalWeight::One(), 1));
|
||||
}
|
||||
ArcSort(&g_fst_, ILabelCompare<StdArc>());
|
||||
ArcSort(g_fst_, ILabelCompare<StdArc>());
|
||||
|
||||
decode_fst_ = LookaheadComposeFst(*model_.hcl_fst_, g_fst_, model_.disambig_);
|
||||
decode_fst_ = LookaheadComposeFst(*model_->hcl_fst_, *g_fst_, model_->disambig_);
|
||||
} else {
|
||||
decode_fst_ = NULL;
|
||||
KALDI_ERR << "Can't create decoding graph";
|
||||
}
|
||||
|
||||
decoder_ = new kaldi::SingleUtteranceNnet3Decoder(model_.nnet3_decoding_config_,
|
||||
*model_.trans_model_,
|
||||
*model_.decodable_info_,
|
||||
model_.hclg_fst_ ? *model.hclg_fst_ : *decode_fst_,
|
||||
decoder_ = new kaldi::SingleUtteranceNnet3Decoder(model_->nnet3_decoding_config_,
|
||||
*model_->trans_model_,
|
||||
*model_->decodable_info_,
|
||||
model_->hclg_fst_ ? *model_->hclg_fst_ : *decode_fst_,
|
||||
feature_pipeline_);
|
||||
|
||||
frame_offset_ = 0;
|
||||
input_finalized_ = false;
|
||||
spk_feature_ = NULL;
|
||||
|
||||
InitState();
|
||||
InitRescoring();
|
||||
}
|
||||
|
||||
KaldiRecognizer::KaldiRecognizer(Model *model, SpkModel *spk_model, float sample_frequency) : model_(model), spk_model_(spk_model), sample_frequency_(sample_frequency) {
|
||||
|
||||
KaldiRecognizer::KaldiRecognizer(Model &model, SpkModel *spk_model, float sample_frequency) : model_(model), spk_model_(spk_model), sample_frequency_(sample_frequency) {
|
||||
feature_pipeline_ = new kaldi::OnlineNnet2FeaturePipeline (model_.feature_info_);
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_.trans_model_, model_.feature_info_.silence_weighting_config, 3);
|
||||
model_->Ref();
|
||||
spk_model->Ref();
|
||||
|
||||
feature_pipeline_ = new kaldi::OnlineNnet2FeaturePipeline (model_->feature_info_);
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_->trans_model_, model_->feature_info_.silence_weighting_config, 3);
|
||||
|
||||
decode_fst_ = NULL;
|
||||
g_fst_ = NULL;
|
||||
|
||||
if (!model_.hclg_fst_) {
|
||||
if (model_.hcl_fst_ && model_.g_fst_) {
|
||||
decode_fst_ = LookaheadComposeFst(*model_.hcl_fst_, *model_.g_fst_, model_.disambig_);
|
||||
if (!model_->hclg_fst_) {
|
||||
if (model_->hcl_fst_ && model_->g_fst_) {
|
||||
decode_fst_ = LookaheadComposeFst(*model_->hcl_fst_, *model_->g_fst_, model_->disambig_);
|
||||
} else {
|
||||
KALDI_ERR << "Can't create decoding graph";
|
||||
}
|
||||
}
|
||||
|
||||
decoder_ = new kaldi::SingleUtteranceNnet3Decoder(model_.nnet3_decoding_config_,
|
||||
*model_.trans_model_,
|
||||
*model_.decodable_info_,
|
||||
model_.hclg_fst_ ? *model.hclg_fst_ : *decode_fst_,
|
||||
decoder_ = new kaldi::SingleUtteranceNnet3Decoder(model_->nnet3_decoding_config_,
|
||||
*model_->trans_model_,
|
||||
*model_->decodable_info_,
|
||||
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 feature_pipeline_;
|
||||
delete silence_weighting_;
|
||||
delete decoder_;
|
||||
delete g_fst_;
|
||||
delete decode_fst_;
|
||||
delete spk_feature_;
|
||||
delete lm_fst_;
|
||||
|
||||
model_->Unref();
|
||||
if (spk_model_)
|
||||
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_) {
|
||||
fst::CacheOptions cache_opts(true, 50000);
|
||||
fst::MapFstOptions mapfst_opts(cache_opts);
|
||||
fst::StdToLatticeMapper<kaldi::BaseFloat> mapper;
|
||||
lm_fst_ = new fst::MapFst<fst::StdArc, kaldi::LatticeArc, fst::StdToLatticeMapper<kaldi::BaseFloat> >(*model_->std_lm_fst_, mapper, mapfst_opts);
|
||||
} else {
|
||||
lm_fst_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void KaldiRecognizer::CleanUp()
|
||||
{
|
||||
delete silence_weighting_;
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_.trans_model_, model_.feature_info_.silence_weighting_config, 3);
|
||||
silence_weighting_ = new kaldi::OnlineSilenceWeighting(*model_->trans_model_, model_->feature_info_.silence_weighting_config, 3);
|
||||
|
||||
if (spk_feature_) {
|
||||
delete spk_feature_;
|
||||
spk_feature_ = new OnlineMfcc(spk_model_->spkvector_mfcc_opts);
|
||||
}
|
||||
|
||||
frame_offset_ += decoder_->NumFramesDecoded();
|
||||
decoder_->InitDecoding(frame_offset_);
|
||||
|
||||
// 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 (frame_offset_ > 20000 || state_ == RECOGNIZER_FINALIZED) {
|
||||
samples_round_start_ += samples_processed_;
|
||||
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()
|
||||
{
|
||||
if (silence_weighting_->Active() && feature_pipeline_->NumFramesReady() > 0 &&
|
||||
feature_pipeline_->IvectorFeature() != NULL) {
|
||||
std::vector<std::pair<int32, BaseFloat> > delta_weights;
|
||||
vector<pair<int32, BaseFloat> > delta_weights;
|
||||
silence_weighting_->ComputeCurrentTraceback(decoder_->Decoder());
|
||||
silence_weighting_->GetDeltaWeights(feature_pipeline_->NumFramesReady(),
|
||||
frame_offset_ * 3,
|
||||
@@ -171,27 +237,32 @@ 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);
|
||||
}
|
||||
|
||||
if (decoder_->EndpointDetected(model_.endpoint_config_)) {
|
||||
if (decoder_->EndpointDetected(model_->endpoint_config_)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Computes an xvector from a chunk of speech features.
|
||||
static void RunNnetComputation(const MatrixBase<BaseFloat> &features,
|
||||
const nnet3::Nnet &nnet, nnet3::CachingOptimizingCompiler *compiler,
|
||||
@@ -208,7 +279,7 @@ static void RunNnetComputation(const MatrixBase<BaseFloat> &features,
|
||||
output_spec.indexes.resize(1);
|
||||
request.outputs.resize(1);
|
||||
request.outputs[0].Swap(&output_spec);
|
||||
std::shared_ptr<const nnet3::NnetComputation> computation = compiler->Compile(request);
|
||||
shared_ptr<const nnet3::NnetComputation> computation = compiler->Compile(request);
|
||||
nnet3::Nnet *nnet_to_update = NULL; // we're not doing any update.
|
||||
nnet3::NnetComputer computer(nnet3::NnetComputeOptions(), *computation,
|
||||
nnet, nnet_to_update);
|
||||
@@ -221,14 +292,24 @@ static void RunNnetComputation(const MatrixBase<BaseFloat> &features,
|
||||
xvector->CopyFromVec(cu_output.Row(0));
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
@@ -242,54 +323,70 @@ void KaldiRecognizer::GetSpkVector(Vector<BaseFloat> &xvector)
|
||||
RunNnetComputation(features, spk_model_->speaker_nnet, &compiler, &xvector);
|
||||
}
|
||||
|
||||
|
||||
std::string KaldiRecognizer::Result()
|
||||
const char* KaldiRecognizer::GetResult()
|
||||
{
|
||||
|
||||
if (!input_finalized_) {
|
||||
decoder_->FinalizeDecoding();
|
||||
input_finalized_ = true;
|
||||
}
|
||||
|
||||
if (decoder_->NumFramesDecoded() == 0) {
|
||||
return "{\"text\": \"\"}";
|
||||
return StoreReturn("{\"text\": \"\"}");
|
||||
}
|
||||
|
||||
kaldi::CompactLattice clat;
|
||||
decoder_->GetLattice(true, &clat);
|
||||
fst::ScaleLattice(fst::LatticeScale(8.0, 10.0), &clat);
|
||||
|
||||
if (model_->std_lm_fst_) {
|
||||
Lattice lat1;
|
||||
|
||||
ConvertLattice(clat, &lat1);
|
||||
fst::ScaleLattice(fst::GraphLatticeScale(-1.0), &lat1);
|
||||
fst::ArcSort(&lat1, fst::OLabelCompare<kaldi::LatticeArc>());
|
||||
kaldi::Lattice composed_lat;
|
||||
fst::Compose(lat1, *lm_fst_, &composed_lat);
|
||||
fst::Invert(&composed_lat);
|
||||
kaldi::CompactLattice determinized_lat;
|
||||
DeterminizeLattice(composed_lat, &determinized_lat);
|
||||
fst::ScaleLattice(fst::GraphLatticeScale(-1), &determinized_lat);
|
||||
fst::ArcSort(&determinized_lat, fst::OLabelCompare<kaldi::CompactLatticeArc>());
|
||||
|
||||
kaldi::ConstArpaLmDeterministicFst const_arpa_fst(model_->const_arpa_);
|
||||
kaldi::CompactLattice composed_clat;
|
||||
kaldi::ComposeCompactLatticeDeterministic(determinized_lat, &const_arpa_fst, &composed_clat);
|
||||
kaldi::Lattice composed_lat1;
|
||||
ConvertLattice(composed_clat, &composed_lat1);
|
||||
fst::Invert(&composed_lat1);
|
||||
DeterminizeLattice(composed_lat1, &clat);
|
||||
}
|
||||
|
||||
fst::ScaleLattice(fst::LatticeScale(9.0, 10.0), &clat);
|
||||
CompactLattice aligned_lat;
|
||||
if (model_.winfo_) {
|
||||
WordAlignLattice(clat, *model_.trans_model_, *model_.winfo_, 0, &aligned_lat);
|
||||
if (model_->winfo_) {
|
||||
WordAlignLattice(clat, *model_->trans_model_, *model_->winfo_, 0, &aligned_lat);
|
||||
} else {
|
||||
aligned_lat = clat;
|
||||
}
|
||||
|
||||
MinimumBayesRisk mbr(aligned_lat);
|
||||
const std::vector<BaseFloat> &conf = mbr.GetOneBestConfidences();
|
||||
const std::vector<int32> &words = mbr.GetOneBest();
|
||||
const std::vector<std::pair<BaseFloat, BaseFloat> > × =
|
||||
const vector<BaseFloat> &conf = mbr.GetOneBestConfidences();
|
||||
const vector<int32> &words = mbr.GetOneBest();
|
||||
const vector<pair<BaseFloat, BaseFloat> > × =
|
||||
mbr.GetOneBestTimes();
|
||||
|
||||
int size = words.size();
|
||||
|
||||
json::JSON obj;
|
||||
std::stringstream text;
|
||||
stringstream text;
|
||||
|
||||
// Create JSON object
|
||||
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["word"] = model_->word_syms_->Find(words[i]);
|
||||
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);
|
||||
|
||||
if (i) {
|
||||
text << " ";
|
||||
}
|
||||
text << model_.word_syms_->Find(words[i]);
|
||||
text << model_->word_syms_->Find(words[i]);
|
||||
}
|
||||
obj["text"] = text.str();
|
||||
|
||||
@@ -301,43 +398,68 @@ std::string KaldiRecognizer::Result()
|
||||
}
|
||||
}
|
||||
|
||||
return obj.dump();
|
||||
return StoreReturn(obj.dump());
|
||||
}
|
||||
|
||||
std::string KaldiRecognizer::PartialResult()
|
||||
|
||||
const char* KaldiRecognizer::PartialResult()
|
||||
{
|
||||
if (state_ != RECOGNIZER_RUNNING) {
|
||||
return StoreReturn("{\"text\": \"\"}");
|
||||
}
|
||||
|
||||
json::JSON res;
|
||||
|
||||
if (decoder_->NumFramesDecoded() == 0) {
|
||||
res["partial"] = "";
|
||||
return res.dump();
|
||||
return StoreReturn(res.dump());
|
||||
}
|
||||
|
||||
kaldi::Lattice lat;
|
||||
decoder_->GetBestPath(false, &lat);
|
||||
std::vector<kaldi::int32> alignment, words;
|
||||
vector<kaldi::int32> alignment, words;
|
||||
LatticeWeight weight;
|
||||
GetLinearSymbolSequence(lat, &alignment, &words, &weight);
|
||||
|
||||
std::ostringstream text;
|
||||
ostringstream text;
|
||||
for (size_t i = 0; i < words.size(); i++) {
|
||||
if (i) {
|
||||
text << " ";
|
||||
}
|
||||
text << model_.word_syms_->Find(words[i]);
|
||||
text << model_->word_syms_->Find(words[i]);
|
||||
}
|
||||
res["partial"] = text.str();
|
||||
|
||||
return res.dump();
|
||||
return StoreReturn(res.dump());
|
||||
}
|
||||
|
||||
std::string KaldiRecognizer::FinalResult()
|
||||
const char* KaldiRecognizer::Result()
|
||||
{
|
||||
if (!input_finalized_) {
|
||||
feature_pipeline_->InputFinished();
|
||||
UpdateSilenceWeights();
|
||||
decoder_->AdvanceDecoding();
|
||||
decoder_->FinalizeDecoding();
|
||||
input_finalized_ = true;
|
||||
if (state_ != RECOGNIZER_RUNNING) {
|
||||
return StoreReturn("{\"text\": \"\"}");
|
||||
}
|
||||
return Result();
|
||||
decoder_->FinalizeDecoding();
|
||||
state_ = RECOGNIZER_ENDPOINT;
|
||||
return GetResult();
|
||||
}
|
||||
|
||||
const char* KaldiRecognizer::FinalResult()
|
||||
{
|
||||
if (state_ != RECOGNIZER_RUNNING) {
|
||||
return StoreReturn("{\"text\": \"\"}");
|
||||
}
|
||||
|
||||
feature_pipeline_->InputFinished();
|
||||
UpdateSilenceWeights();
|
||||
decoder_->AdvanceDecoding();
|
||||
decoder_->FinalizeDecoding();
|
||||
state_ = RECOGNIZER_FINALIZED;
|
||||
return GetResult();
|
||||
}
|
||||
|
||||
// Store result in recognizer and return as const string
|
||||
const char *KaldiRecognizer::StoreReturn(const string &res)
|
||||
{
|
||||
last_result_ = res;
|
||||
return last_result_.c_str();
|
||||
}
|
||||
|
||||
+27
-9
@@ -29,36 +29,54 @@
|
||||
|
||||
using namespace kaldi;
|
||||
|
||||
enum KaldiRecognizerState {
|
||||
RECOGNIZER_INITIALIZED,
|
||||
RECOGNIZER_RUNNING,
|
||||
RECOGNIZER_ENDPOINT,
|
||||
RECOGNIZER_FINALIZED
|
||||
};
|
||||
|
||||
class KaldiRecognizer {
|
||||
public:
|
||||
KaldiRecognizer(Model &model, float sample_frequency);
|
||||
KaldiRecognizer(Model &model, SpkModel *spk_model, float sample_frequency);
|
||||
KaldiRecognizer(Model &model, float sample_frequency, char const *grammar);
|
||||
KaldiRecognizer(Model *model, float sample_frequency);
|
||||
KaldiRecognizer(Model *model, SpkModel *spk_model, float sample_frequency);
|
||||
KaldiRecognizer(Model *model, float sample_frequency, char const *grammar);
|
||||
~KaldiRecognizer();
|
||||
bool AcceptWaveform(const char *data, int len);
|
||||
bool AcceptWaveform(const short *sdata, int len);
|
||||
bool AcceptWaveform(const float *fdata, int len);
|
||||
std::string Result();
|
||||
std::string FinalResult();
|
||||
std::string PartialResult();
|
||||
const char* Result();
|
||||
const char* FinalResult();
|
||||
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_;
|
||||
Model *model_;
|
||||
SingleUtteranceNnet3Decoder *decoder_;
|
||||
fst::LookaheadFst<fst::StdArc, int32> *decode_fst_;
|
||||
fst::StdVectorFst g_fst_; // dynamically constructed grammar
|
||||
fst::StdVectorFst *g_fst_; // dynamically constructed grammar
|
||||
OnlineNnet2FeaturePipeline *feature_pipeline_;
|
||||
OnlineSilenceWeighting *silence_weighting_;
|
||||
|
||||
SpkModel *spk_model_;
|
||||
OnlineBaseFeature *spk_feature_;
|
||||
|
||||
fst::MapFst<fst::StdArc, kaldi::LatticeArc, fst::StdToLatticeMapper<kaldi::BaseFloat> > *lm_fst_;
|
||||
|
||||
float sample_frequency_;
|
||||
int32 frame_offset_;
|
||||
bool input_finalized_;
|
||||
|
||||
int64 samples_processed_;
|
||||
int64 samples_round_start_;
|
||||
|
||||
KaldiRecognizerState state_;
|
||||
string last_result_;
|
||||
};
|
||||
|
||||
+187
-57
@@ -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,24 +33,101 @@ 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::Model(const char *model_path) : model_path_str_(model_path) {
|
||||
|
||||
#ifdef __ANDROID__
|
||||
SetLogHandler(AndroidLogHandler);
|
||||
#endif
|
||||
SetLogHandler(KaldiLogHandler);
|
||||
|
||||
const char *usage = "Read the docs";
|
||||
struct stat buffer;
|
||||
string am_path = model_path_str_ + "/am/final.mdl";
|
||||
if (stat(am_path.c_str(), &buffer) == 0) {
|
||||
ConfigureV2();
|
||||
} else {
|
||||
ConfigureV1();
|
||||
}
|
||||
|
||||
ReadDataFiles();
|
||||
|
||||
ref_cnt_ = 1;
|
||||
}
|
||||
|
||||
// Old model layout without model configuration file
|
||||
|
||||
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",
|
||||
@@ -71,49 +136,70 @@ Model::Model(const char *model_path) {
|
||||
"--endpoint.rule2.min-trailing-silence=0.5",
|
||||
"--endpoint.rule3.min-trailing-silence=1.0",
|
||||
"--endpoint.rule4.min-trailing-silence=2.0",
|
||||
};
|
||||
std::string model_path_str(model_path);
|
||||
|
||||
kaldi::ParseOptions po(usage);
|
||||
"--print-args=false",
|
||||
};
|
||||
|
||||
kaldi::ParseOptions po("");
|
||||
nnet3_decoding_config_.Register(&po);
|
||||
endpoint_config_.Register(&po);
|
||||
decodable_opts_.Register(&po);
|
||||
|
||||
std::vector<const char*> args;
|
||||
vector<const char*> args;
|
||||
args.push_back("vosk");
|
||||
args.insert(args.end(), extra_args, extra_args + sizeof(extra_args) / sizeof(extra_args[0]));
|
||||
po.Read(args.size(), args.data());
|
||||
|
||||
nnet3_rxfilename_ = model_path_str_ + "/final.mdl";
|
||||
hclg_fst_rxfilename_ = model_path_str_ + "/HCLG.fst";
|
||||
hcl_fst_rxfilename_ = model_path_str_ + "/HCLr.fst";
|
||||
g_fst_rxfilename_ = model_path_str_ + "/Gr.fst";
|
||||
disambig_rxfilename_ = model_path_str_ + "/disambig_tid.int";
|
||||
word_syms_rxfilename_ = model_path_str_ + "/words.txt";
|
||||
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()
|
||||
{
|
||||
kaldi::ParseOptions po("something");
|
||||
nnet3_decoding_config_.Register(&po);
|
||||
endpoint_config_.Register(&po);
|
||||
decodable_opts_.Register(&po);
|
||||
po.ReadConfigFile(model_path_str_ + "/conf/model.conf");
|
||||
|
||||
|
||||
nnet3_rxfilename_ = model_path_str_ + "/am/final.mdl";
|
||||
hclg_fst_rxfilename_ = model_path_str_ + "/graph/HCLG.fst";
|
||||
hcl_fst_rxfilename_ = model_path_str_ + "/graph/HCLr.fst";
|
||||
g_fst_rxfilename_ = model_path_str_ + "/graph/Gr.fst";
|
||||
disambig_rxfilename_ = model_path_str_ + "/graph/disambig_tid.int";
|
||||
word_syms_rxfilename_ = model_path_str_ + "/graph/words.txt";
|
||||
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(model_path_str + "/mfcc.conf", &feature_info_.mfcc_opts);
|
||||
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 = "1:2:3:4:5:6:7:8:9:10";
|
||||
|
||||
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";
|
||||
ivector_extraction_opts.num_gselect = 5;
|
||||
ivector_extraction_opts.min_post = 0.025;
|
||||
ivector_extraction_opts.posterior_scale = 0.1;
|
||||
ivector_extraction_opts.max_remembered_frames = 1000;
|
||||
ivector_extraction_opts.max_count = 100;
|
||||
ivector_extraction_opts.ivector_period = 200;
|
||||
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";
|
||||
g_fst_rxfilename_ = model_path_str + "/Gr.fst";
|
||||
disambig_rxfilename_ = model_path_str + "/disambig_tid.int";
|
||||
word_syms_rxfilename_ = model_path_str + "/words.txt";
|
||||
winfo_rxfilename_ = model_path_str + "/word_boundary.int";
|
||||
feature_info_.silence_weighting_config.silence_phones_str = endpoint_config_.silence_phones;
|
||||
|
||||
trans_model_ = new kaldi::TransitionModel();
|
||||
nnet_ = new kaldi::nnet3::AmNnetSimple();
|
||||
@@ -126,19 +212,35 @@ Model::Model(const char *model_path) {
|
||||
SetDropoutTestMode(true, &(nnet_->GetNnet()));
|
||||
nnet3::CollapseModel(nnet3::CollapseModelConfig(), &(nnet_->GetNnet()));
|
||||
}
|
||||
|
||||
decodable_info_ = new nnet3::DecodableNnetSimpleLoopedInfo(decodable_opts_,
|
||||
nnet_);
|
||||
struct stat buffer;
|
||||
|
||||
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_);
|
||||
hcl_fst_ = NULL;
|
||||
g_fst_ = NULL;
|
||||
} else {
|
||||
KALDI_LOG << "Loading HCL and G from " << hcl_fst_rxfilename_ << " " << g_fst_rxfilename_;
|
||||
hclg_fst_ = NULL;
|
||||
hcl_fst_ = fst::StdFst::Read(hcl_fst_rxfilename_);
|
||||
g_fst_ = fst::StdFst::Read(g_fst_rxfilename_);
|
||||
|
||||
ReadIntegerVectorSimple(disambig_rxfilename_, &disambig_);
|
||||
}
|
||||
|
||||
@@ -149,6 +251,7 @@ Model::Model(const char *model_path) {
|
||||
word_syms_ = g_fst_->OutputSymbols();
|
||||
}
|
||||
if (!word_syms_) {
|
||||
KALDI_LOG << "Loading words from " << word_syms_rxfilename_;
|
||||
if (!(word_syms_ = fst::SymbolTable::ReadText(word_syms_rxfilename_)))
|
||||
KALDI_ERR << "Could not read symbol table from file "
|
||||
<< word_syms_rxfilename_;
|
||||
@@ -156,11 +259,38 @@ Model::Model(const char *model_path) {
|
||||
KALDI_ASSERT(word_syms_);
|
||||
|
||||
if (stat(winfo_rxfilename_.c_str(), &buffer) == 0) {
|
||||
KALDI_LOG << "Loading winfo " << winfo_rxfilename_;
|
||||
kaldi::WordBoundaryInfoNewOpts opts;
|
||||
winfo_ = new kaldi::WordBoundaryInfo(opts, winfo_rxfilename_);
|
||||
} else {
|
||||
winfo_ = NULL;
|
||||
}
|
||||
|
||||
if (stat(carpa_rxfilename_.c_str(), &buffer) == 0) {
|
||||
KALDI_LOG << "Loading CARPA model from " << carpa_rxfilename_;
|
||||
std_lm_fst_ = fst::ReadFstKaldi(std_fst_rxfilename_);
|
||||
fst::Project(std_lm_fst_, fst::PROJECT_OUTPUT);
|
||||
if (std_lm_fst_->Properties(fst::kILabelSorted, true) == 0) {
|
||||
fst::ILabelCompare<fst::StdArc> ilabel_comp;
|
||||
fst::ArcSort(std_lm_fst_, ilabel_comp);
|
||||
}
|
||||
ReadKaldiObject(carpa_rxfilename_, &const_arpa_);
|
||||
} else {
|
||||
std_lm_fst_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Model::Ref()
|
||||
{
|
||||
ref_cnt_++;
|
||||
}
|
||||
|
||||
void Model::Unref()
|
||||
{
|
||||
ref_cnt_--;
|
||||
if (ref_cnt_ == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
Model::~Model() {
|
||||
|
||||
+26
-9
@@ -32,6 +32,7 @@
|
||||
#include "rnnlm/rnnlm-utils.h"
|
||||
|
||||
using namespace kaldi;
|
||||
using namespace std;
|
||||
|
||||
class KaldiRecognizer;
|
||||
|
||||
@@ -39,18 +40,29 @@ class Model {
|
||||
|
||||
public:
|
||||
Model(const char *model_path);
|
||||
~Model();
|
||||
void Ref();
|
||||
void Unref();
|
||||
|
||||
protected:
|
||||
~Model();
|
||||
void ConfigureV1();
|
||||
void ConfigureV2();
|
||||
void ReadDataFiles();
|
||||
|
||||
friend class KaldiRecognizer;
|
||||
|
||||
std::string nnet3_rxfilename_;
|
||||
std::string hclg_fst_rxfilename_;
|
||||
std::string hcl_fst_rxfilename_;
|
||||
std::string g_fst_rxfilename_;
|
||||
std::string word_syms_rxfilename_;
|
||||
std::string winfo_rxfilename_;
|
||||
std::string disambig_rxfilename_;
|
||||
string model_path_str_;
|
||||
string nnet3_rxfilename_;
|
||||
string hclg_fst_rxfilename_;
|
||||
string hcl_fst_rxfilename_;
|
||||
string g_fst_rxfilename_;
|
||||
string disambig_rxfilename_;
|
||||
string word_syms_rxfilename_;
|
||||
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_;
|
||||
@@ -62,11 +74,16 @@ protected:
|
||||
kaldi::nnet3::AmNnetSimple *nnet_;
|
||||
const fst::SymbolTable *word_syms_;
|
||||
kaldi::WordBoundaryInfo *winfo_;
|
||||
std::vector<int32> disambig_;
|
||||
vector<int32> disambig_;
|
||||
|
||||
fst::Fst<fst::StdArc> *hclg_fst_;
|
||||
fst::Fst<fst::StdArc> *hcl_fst_;
|
||||
fst::Fst<fst::StdArc> *g_fst_;
|
||||
|
||||
fst::VectorFst<fst::StdArc> *std_lm_fst_;
|
||||
kaldi::ConstArpaLm const_arpa_;
|
||||
|
||||
int ref_cnt_;
|
||||
};
|
||||
|
||||
#endif /* MODEL_H_ */
|
||||
|
||||
@@ -24,4 +24,19 @@ SpkModel::SpkModel(const char *speaker_path) {
|
||||
SetBatchnormTestMode(true, &speaker_nnet);
|
||||
SetDropoutTestMode(true, &speaker_nnet);
|
||||
CollapseModel(nnet3::CollapseModelConfig(), &speaker_nnet);
|
||||
|
||||
ref_cnt_ = 1;
|
||||
}
|
||||
|
||||
void SpkModel::Ref()
|
||||
{
|
||||
ref_cnt_++;
|
||||
}
|
||||
|
||||
void SpkModel::Unref()
|
||||
{
|
||||
ref_cnt_--;
|
||||
if (ref_cnt_ == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,12 +27,17 @@ class SpkModel {
|
||||
|
||||
public:
|
||||
SpkModel(const char *spk_path);
|
||||
void Ref();
|
||||
void Unref();
|
||||
|
||||
protected:
|
||||
friend class KaldiRecognizer;
|
||||
~SpkModel() {};
|
||||
|
||||
kaldi::nnet3::Nnet speaker_nnet;
|
||||
MfccOptions spkvector_mfcc_opts;
|
||||
|
||||
int ref_cnt_;
|
||||
};
|
||||
|
||||
#endif /* SPK_MODEL_H_ */
|
||||
|
||||
+96
-32
@@ -1,7 +1,10 @@
|
||||
%module(package="vosk") vosk
|
||||
#if SWIGPYTHON
|
||||
%module(package="vosk", "threads"=1) vosk
|
||||
#else
|
||||
%module Vosk
|
||||
#endif
|
||||
|
||||
%include <typemaps.i>
|
||||
%include <std_string.i>
|
||||
|
||||
#if SWIGPYTHON
|
||||
%include <pybuffer.i>
|
||||
@@ -11,39 +14,12 @@
|
||||
%include <arrays_csharp.i>
|
||||
#endif
|
||||
|
||||
namespace kaldi {
|
||||
}
|
||||
|
||||
#if SWIGPYTHON
|
||||
%pybuffer_binary(const char *data, int len);
|
||||
%ignore KaldiRecognizer::AcceptWaveform(const short *sdata, int len);
|
||||
%ignore KaldiRecognizer::AcceptWaveform(const float *fdata, int len);
|
||||
%exception {
|
||||
try {
|
||||
$action
|
||||
} catch (kaldi::KaldiFatalError &e) {
|
||||
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(e.KaldiMessage()));
|
||||
SWIG_fail;
|
||||
} catch (std::exception &e) {
|
||||
PyErr_SetString(PyExc_RuntimeError, const_cast<char*>(e.what()));
|
||||
SWIG_fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SWIGJAVA
|
||||
%apply char *BYTE {const char *data};
|
||||
%ignore KaldiRecognizer::AcceptWaveform(const short *sdata, int len);
|
||||
%ignore KaldiRecognizer::AcceptWaveform(const float *fdata, int len);
|
||||
#endif
|
||||
|
||||
%{
|
||||
#include "kaldi_recognizer.h"
|
||||
#include "model.h"
|
||||
#include "spk_model.h"
|
||||
%}
|
||||
|
||||
#if SWIGJAVA
|
||||
%typemap(javaimports) KaldiRecognizer %{
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@@ -67,6 +43,94 @@ CSHARP_ARRAYS(char, byte)
|
||||
%apply short INPUT[] {const short *sdata};
|
||||
#endif
|
||||
|
||||
%include "kaldi_recognizer.h"
|
||||
%include "model.h"
|
||||
%include "spk_model.h"
|
||||
|
||||
#if SWIGJAVASCRIPT
|
||||
%begin %{
|
||||
#include <v8.h>
|
||||
#include <node.h>
|
||||
#include <node_buffer.h>
|
||||
%}
|
||||
#endif
|
||||
|
||||
%{
|
||||
#include "vosk_api.h"
|
||||
typedef struct VoskModel Model;
|
||||
typedef struct VoskSpkModel SpkModel;
|
||||
typedef struct VoskRecognizer KaldiRecognizer;
|
||||
%}
|
||||
|
||||
typedef struct {} Model;
|
||||
typedef struct {} SpkModel;
|
||||
typedef struct {} KaldiRecognizer;
|
||||
|
||||
%extend Model {
|
||||
Model(const char *model_path) {
|
||||
return vosk_model_new(model_path);
|
||||
}
|
||||
~Model() {
|
||||
vosk_model_free($self);
|
||||
}
|
||||
}
|
||||
|
||||
%extend SpkModel {
|
||||
SpkModel(const char *model_path) {
|
||||
return vosk_spk_model_new(model_path);
|
||||
}
|
||||
~SpkModel() {
|
||||
vosk_spk_model_free($self);
|
||||
}
|
||||
}
|
||||
|
||||
%extend KaldiRecognizer {
|
||||
KaldiRecognizer(Model *model, float sample_rate) {
|
||||
return vosk_recognizer_new(model, sample_rate);
|
||||
}
|
||||
KaldiRecognizer(Model *model, SpkModel *spk_model, float sample_rate) {
|
||||
return vosk_recognizer_new_spk(model, spk_model, sample_rate);
|
||||
}
|
||||
KaldiRecognizer(Model *model, float sample_rate, const char* grammar) {
|
||||
return vosk_recognizer_new_grm(model, sample_rate, grammar);
|
||||
}
|
||||
~KaldiRecognizer() {
|
||||
vosk_recognizer_free($self);
|
||||
}
|
||||
|
||||
#if SWIGCSHARP
|
||||
bool AcceptWaveform(const char *data, int len) {
|
||||
return vosk_recognizer_accept_waveform($self, data, len);
|
||||
}
|
||||
bool AcceptWaveform(const short *sdata, int len) {
|
||||
return vosk_recognizer_accept_waveform_s($self, sdata, len);
|
||||
}
|
||||
bool AcceptWaveform(const float *fdata, int len) {
|
||||
return vosk_recognizer_accept_waveform_f($self, fdata, len);
|
||||
}
|
||||
#elif SWIGJAVA
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* Result() {
|
||||
return vosk_recognizer_result($self);
|
||||
}
|
||||
const char* PartialResult() {
|
||||
return vosk_recognizer_partial_result($self);
|
||||
}
|
||||
const char* FinalResult() {
|
||||
return vosk_recognizer_final_result($self);
|
||||
}
|
||||
}
|
||||
|
||||
%rename(SetLogLevel) vosk_set_log_level;
|
||||
void vosk_set_log_level(int level);
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "vosk_api.h"
|
||||
#include "kaldi_recognizer.h"
|
||||
#include "model.h"
|
||||
#include "spk_model.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
using namespace kaldi;
|
||||
|
||||
VoskModel *vosk_model_new(const char *model_path)
|
||||
{
|
||||
return (VoskModel *)new Model(model_path);
|
||||
}
|
||||
|
||||
void vosk_model_free(VoskModel *model)
|
||||
{
|
||||
((Model *)model)->Unref();
|
||||
}
|
||||
|
||||
VoskSpkModel *vosk_spk_model_new(const char *model_path)
|
||||
{
|
||||
return (VoskSpkModel *)new SpkModel(model_path);
|
||||
}
|
||||
|
||||
void vosk_spk_model_free(VoskSpkModel *model)
|
||||
{
|
||||
((SpkModel *)model)->Unref();
|
||||
}
|
||||
|
||||
VoskRecognizer *vosk_recognizer_new(VoskModel *model, float sample_rate)
|
||||
{
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate);
|
||||
}
|
||||
|
||||
VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, VoskSpkModel *spk_model, float sample_rate)
|
||||
{
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, (SpkModel *)spk_model, sample_rate);
|
||||
}
|
||||
|
||||
VoskRecognizer *vosk_recognizer_new_grm(VoskModel *model, float sample_rate, const char *grammar)
|
||||
{
|
||||
return (VoskRecognizer *)new KaldiRecognizer((Model *)model, sample_rate, grammar);
|
||||
}
|
||||
|
||||
int vosk_recognizer_accept_waveform(VoskRecognizer *recognizer, const char *data, int length)
|
||||
{
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
}
|
||||
|
||||
int vosk_recognizer_accept_waveform_s(VoskRecognizer *recognizer, const short *data, int length)
|
||||
{
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
}
|
||||
|
||||
int vosk_recognizer_accept_waveform_f(VoskRecognizer *recognizer, const float *data, int length)
|
||||
{
|
||||
return ((KaldiRecognizer *)(recognizer))->AcceptWaveform(data, length);
|
||||
}
|
||||
|
||||
const char *vosk_recognizer_result(VoskRecognizer *recognizer)
|
||||
{
|
||||
return ((KaldiRecognizer *)recognizer)->Result();
|
||||
}
|
||||
|
||||
const char *vosk_recognizer_partial_result(VoskRecognizer *recognizer)
|
||||
{
|
||||
return ((KaldiRecognizer *)recognizer)->PartialResult();
|
||||
}
|
||||
|
||||
const char *vosk_recognizer_final_result(VoskRecognizer *recognizer)
|
||||
{
|
||||
return ((KaldiRecognizer *)recognizer)->FinalResult();
|
||||
}
|
||||
|
||||
void vosk_recognizer_free(VoskRecognizer *recognizer)
|
||||
{
|
||||
delete (KaldiRecognizer *)(recognizer);
|
||||
}
|
||||
|
||||
void vosk_set_log_level(int log_level)
|
||||
{
|
||||
SetVerboseLevel(log_level);
|
||||
}
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
// Copyright 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// 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_
|
||||
|
||||
#ifdef __cplusplus
|
||||
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
|
||||
|
||||
#endif /* _VOSK_API_H_ */
|
||||
+57
-15
@@ -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,21 +23,6 @@ RUN cd /opt \
|
||||
&& cd .. \
|
||||
&& rm -rf swig-4.0.1.tar.gz swig-4.0.1
|
||||
|
||||
ARG OPENBLAS_ARCH=ARMV7
|
||||
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 \
|
||||
&& ./configure --mathlib=OPENBLAS --shared --use-cuda=no \
|
||||
&& make -j 10 online2 \
|
||||
&& 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 \
|
||||
@@ -60,3 +48,57 @@ RUN cd /opt \
|
||||
&& make -j $(nproc) \
|
||||
&& make install \
|
||||
&& rm -rf /opt/cpython-3.7.6 /opt/cpython-3.7.6-cross /opt/v3.7.6.tar.gz
|
||||
|
||||
RUN cd /opt \
|
||||
&& wget -q https://github.com/python/cpython/archive/v3.6.10.tar.gz \
|
||||
&& tar xf v3.6.10.tar.gz \
|
||||
&& cp -r cpython-3.6.10 cpython-3.6.10-cross \
|
||||
&& cd /opt/cpython-3.6.10 \
|
||||
&& 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.6-cp3.6m" \
|
||||
&& make -j $(nproc) \
|
||||
&& make install \
|
||||
&& /opt/python/cp3.6-cp3.6m/bin/pip3 install -U pip \
|
||||
&& /opt/python/cp3.6-cp3.6m/bin/pip3 install -U wheel \
|
||||
&& cd /opt/cpython-3.6.10-cross \
|
||||
&& export PATH=/opt/python/cp3.6-cp3.6m/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.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 {} \;
|
||||
|
||||
+17
-21
@@ -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 \
|
||||
&& 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 \
|
||||
@@ -38,3 +20,17 @@ RUN cd /opt \
|
||||
&& 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 {} \;
|
||||
|
||||
@@ -4,5 +4,9 @@ set -e
|
||||
set -x
|
||||
|
||||
docker build --build-arg="DOCKCROSS_IMAGE=linux-armv7" --build-arg="OPENBLAS_ARCH=ARMV7" --file Dockerfile.dockcross --tag alphacep/kaldi-dockcross-armv7:latest .
|
||||
docker build --build-arg="DOCKCROSS_IMAGE=linux-armv6" --build-arg="OPENBLAS_ARCH=ARMV6" --file Dockerfile.dockcross --tag alphacep/kaldi-dockcross-armv6:latest .
|
||||
docker build --build-arg="DOCKCROSS_IMAGE=linux-armv6" --build-arg="OPENBLAS_ARCH=ARMV6" --build-arg="ARM_HARDWARE_OPTS=" --file Dockerfile.dockcross --tag alphacep/kaldi-dockcross-armv6:latest .
|
||||
docker build --build-arg="DOCKCROSS_IMAGE=linux-arm64" --build-arg="OPENBLAS_ARCH=ARMV8" --file Dockerfile.dockcross --tag alphacep/kaldi-dockcross-arm64:latest .
|
||||
|
||||
docker run --rm -v /home/shmyrev/travis/vosk-api/:/io alphacep/kaldi-dockcross-armv6 /io/travis/build-wheels-dockcross.sh
|
||||
docker run --rm -v /home/shmyrev/travis/vosk-api/:/io alphacep/kaldi-dockcross-armv7 /io/travis/build-wheels-dockcross.sh
|
||||
docker run --rm -v /home/shmyrev/travis/vosk-api/:/io alphacep/kaldi-dockcross-arm64 /io/travis/build-wheels-dockcross.sh
|
||||
|
||||
@@ -4,3 +4,4 @@ set -e
|
||||
set -x
|
||||
|
||||
docker build --file Dockerfile.manylinux --tag alphacep/kaldi-manylinux:latest .
|
||||
docker run --rm -e PLAT=manylinux2010_x86_64 -v /home/shmyrev/travis/vosk-api/:/io alphacep/kaldi-manylinux /io/travis/build-wheels.sh
|
||||
|
||||
@@ -1,20 +1,37 @@
|
||||
#!/bin/bash
|
||||
set -e -x
|
||||
|
||||
export KALDI_ROOT=/opt/kaldi
|
||||
export WHEEL_FLAGS=`$CROSS_ROOT/bin/python3-config --cflags`
|
||||
export PATH=/opt/python/cp3.7-cp3.7m/bin:$PATH
|
||||
echo $CROSS_TRIPLE
|
||||
case $CROSS_TRIPLE in
|
||||
*arm-*)
|
||||
export _PYTHON_HOST_PLATFORM=linux-armv6l
|
||||
;;
|
||||
*armv7-*)
|
||||
export _PYTHON_HOST_PLATFORM=linux-armv7l
|
||||
;;
|
||||
*aarch64-*)
|
||||
export _PYTHON_HOST_PLATFORM=linux-aarch64
|
||||
;;
|
||||
esac
|
||||
ORIG_PATH=$PATH
|
||||
for pyver in 3.6 3.7 3.8; do
|
||||
|
||||
pip3 wheel /io/python -w /io/wheelhouse
|
||||
export KALDI_ROOT=/opt/kaldi
|
||||
export PATH=/opt/python/cp${pyver}-cp${pyver}m/bin:$ORIG_PATH
|
||||
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
|
||||
|
||||
rm -rf /io/python/build
|
||||
pip${pyver} -v wheel /io/python -w /io/wheelhouse
|
||||
|
||||
done
|
||||
|
||||
@@ -4,10 +4,11 @@ set -e -x
|
||||
export KALDI_ROOT=/opt/kaldi
|
||||
|
||||
# Compile wheels
|
||||
for pypath in /opt/python/cp3*; do
|
||||
export WHEEL_FLAGS=`${pypath}/bin/python3-config --cflags`
|
||||
for pypath in /opt/python/cp3[56789]*; do
|
||||
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
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
exports.printMsg = function() {
|
||||
console.log("This is a message from the Vosk package");
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user