Compare commits

...

59 Commits

Author SHA1 Message Date
Nickolay Shmyrev d917af21ab Better search for Windows dlls 2021-02-12 22:24:54 +01:00
Nickolay Shmyrev 948c8c7cfd Update to 0.3.21 2021-02-12 10:13:50 +01:00
Nickolay Shmyrev dec8e1acf3 Move to JNA instead of JNR-FFI for better Android compatibility 2021-02-11 00:04:19 +01:00
Nickolay Shmyrev 3c020526ce No need for byte buffer 2021-02-10 23:32:47 +01:00
Nickolay Shmyrev b0da19b07f Java API through JNR-FFI 2021-02-10 23:16:20 +01:00
Nickolay Shmyrev 70bcd9b018 Platform is hardcoded now 2021-02-09 23:43:56 +01:00
Nickolay Shmyrev d2604b609d Copy out lib files too 2021-02-09 23:36:32 +01:00
Nickolay Shmyrev e960e0cacf Proper libraries and demo 2021-02-09 21:43:21 +01:00
Nickolay Shmyrev 77b114d434 Rework node bindings to use node-ffi-napi 2021-02-08 23:00:56 +01:00
Nickolay V. Shmyrev 2860092cef Merge pull request #401 from proger/patch-1
test_microphone: AcceptWaveform wants bytes
2021-02-08 01:50:07 +03:00
Vlad Ki c6119c4835 test_microphone: AcceptWavform wants bytes 2021-02-08 00:38:28 +02:00
Nickolay Shmyrev 415d1927e0 Add win32 wheel 2021-02-07 23:08:27 +01:00
Nickolay Shmyrev 3d1e21d242 Update dockcross build to cffi 2021-02-07 21:33:39 +01:00
Nickolay Shmyrev 7a75e1c3f4 Add arm architectures 2021-02-07 20:28:14 +01:00
Nickolay Shmyrev c3430e448a Add build for Windows wheel 2021-02-07 18:11:38 +01:00
Nickolay Shmyrev ae49ea60d2 Rework manylinux to use cffi 2021-02-07 15:26:23 +01:00
Nickolay Shmyrev 02dc0ce0c8 Take source location from environment 2021-02-07 15:17:35 +01:00
Nickolay Shmyrev 15697a18e8 Platform-specific wheel 2021-02-07 14:58:10 +01:00
Nickolay Shmyrev 481881e59d Fully move python to cffi 2021-02-07 13:23:03 +01:00
Nickolay Shmyrev 11a25b26a7 Add cffi wrapper 2021-02-07 10:57:57 +01:00
Nickolay Shmyrev bf87358f6c Add win32 build 2021-02-07 10:12:32 +01:00
Nickolay Shmyrev 04a8242230 Add vosk-api build 2021-02-07 01:55:47 +01:00
Nickolay Shmyrev ceb96c301c Separate openfst root 2021-02-07 01:48:45 +01:00
Nickolay Shmyrev 307df8fdc0 Add Win cross-compilation docker 2021-02-07 01:41:37 +01:00
Nickolay Shmyrev c44875a2dd Build libvosk in src folder, will be used for many bindings 2021-02-07 00:42:25 +01:00
Nickolay Shmyrev 31f11990ca Rename voskrecognizer 2021-02-07 00:32:47 +01:00
Nickolay Shmyrev b79b85856d Refactor C# API to properly work with nuget and precompiled libvosk.so library 2021-02-06 23:10:51 +01:00
Nickolay Shmyrev 6e861c6a19 Add nuget platforms 2021-02-05 00:39:27 +01:00
Nickolay Shmyrev cf62296a51 Update flags to hopefully fix the build 2021-02-02 14:43:12 +01:00
Nickolay Shmyrev 387b132814 Fix model version in Makefile. Thanks to Peter Kronenberg. 2021-01-26 23:19:34 +01:00
Nickolay Shmyrev de83de8624 Implement decoding on iOS with a microphone 2021-01-24 21:59:21 +01:00
Nickolay Shmyrev fe91b5a717 Preprocess header on the fly 2021-01-10 21:11:35 +01:00
Nickolay Shmyrev a052506a5d Add cffi example 2021-01-10 20:53:43 +01:00
Nickolay Shmyrev 6f2d6d0d69 Proper microphone recognizer with the queue 2021-01-09 23:16:35 +01:00
Nickolay Shmyrev a8ae6025bd Add a bit more optimization 2021-01-09 16:16:32 +01:00
Nickolay Shmyrev 1b8332a609 Raise to 0.3.17 2021-01-09 02:29:56 +01:00
Nickolay Shmyrev fe16ec7e57 Set lowest arch for linux 2021-01-09 01:47:23 +01:00
Nickolay Shmyrev c5ce5e46bd Add c++17 2021-01-09 01:46:13 +01:00
Nickolay Shmyrev 99d66670bc Update Android build 2021-01-08 13:30:28 +01:00
Nickolay Shmyrev 072b42cac6 Use our own dockcross 2021-01-08 00:56:18 +01:00
Nickolay Shmyrev acadb5b4c2 Add optimization 2021-01-07 23:41:13 +01:00
Nickolay Shmyrev 2e1de6c3af No need for python 3.5 anymore 2021-01-07 23:20:54 +01:00
Nickolay Shmyrev 67de30908b Use openblas_clapack 2021-01-07 22:37:56 +01:00
Nickolay Shmyrev 9d398eff0e Remove armv6, too slow anyway. Build with new dockcross. 2021-01-06 16:26:23 +01:00
Nickolay Shmyrev 02b7312a00 Build with openblas-clapack to avoid fortran 2021-01-06 01:11:03 +01:00
Nickolay Shmyrev 08c35e84f3 Update demo with spk vector check 2020-12-23 22:21:12 +01:00
Nickolay Shmyrev b92a5c1fc7 Update wheels to openfst 1.8.0 2020-12-22 23:27:01 +01:00
Nickolay Shmyrev 8997a587c5 Fix warnings in preparation for openfst 1.8.0 2020-12-22 21:16:20 +01:00
Nickolay Shmyrev dc3d03d742 Make sure we have result field in json 2020-11-29 19:19:50 +01:00
Nickolay Shmyrev 84df40715c Add Filipino 2020-11-19 14:53:46 +01:00
Nickolay Shmyrev b639fb501a Package US model on bintray 2020-11-04 22:08:03 +01:00
Nickolay Shmyrev 746ff47757 Split long lines in subtitles 2020-11-03 15:13:16 +01:00
Nickolay Shmyrev 2d62db8118 Update link in readme 2020-10-31 10:03:25 +01:00
Nickolay Shmyrev 7a2adcd9ba Add nuget wraps 2020-10-26 15:57:40 +01:00
Nickolay Shmyrev 9ccf3ef0e8 Introduce CMVN in feature pipeline 2020-10-22 23:56:36 +02:00
Nickolay V. Shmyrev 0edab6d558 Merge pull request #259 from ThThoma/add-valid-word-check
add isWordRecognizable()
2020-10-22 15:53:04 +03:00
Athanasios Thoma 4b344f0cd8 rename 2020-10-22 14:09:50 +03:00
Athanasios Thoma 17ddc4d5ba add isWordRecognizable() 2020-10-21 10:00:39 +03:00
Nickolay Shmyrev 3e33860c47 Update to latest 0.3.15 changes 2020-10-20 23:50:39 +03:00
77 changed files with 1435 additions and 915 deletions
+20 -16
View File
@@ -10,7 +10,7 @@
# Gradle files
.gradle/
build/
android/build/
gradlew
gradlew.bat
gradle
@@ -27,12 +27,8 @@ 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/build
python/vosk/*.so
python/test/db
python/test/hyp
python/test/model
@@ -48,16 +44,24 @@ java/model-spk/
java/model/
# CSharp
csharp/gen
csharp/*.exe
csharp/*.c
csharp/model/
csharp/test.wav
*.dll
*.so
*.nupkg
csharp/demo/model
csharp/demo/test.wav
csharp/demo/bin
csharp/demo/obj
# Node
nodejs/vosk_wrap.cc
nodejs/example/model
nodejs/example/test.wav
nodejs/demo/model
nodejs/demo/model-spk
nodejs/demo/test.wav
nodejs/node_modules
nodejs/package-lock.json
nodejs/build
# C
c/test_vosk
c/test_vosk_speaker
c/oprofile_data
c/model
c/test.wav
+1 -2
View File
@@ -7,11 +7,10 @@ matrix:
services:
- docker
env: DOCKER_IMAGE=alphacep/kaldi-manylinux:latest
PLAT=manylinux2010_x86_64
install:
- docker pull $DOCKER_IMAGE
script:
- docker run --rm -e PLAT=$PLAT -v `pwd`:/io $DOCKER_IMAGE $PRE_CMD /io/travis/build-wheels.sh
- docker run --rm -v `pwd`:/io $DOCKER_IMAGE $PRE_CMD /io/travis/build-wheels.sh
- ls wheelhouse/
+2 -2
View File
@@ -1,9 +1,9 @@
# About
Vosk is an offline open source speech recognition toolkit. It enables
speech recognition models for 16 languages and dialects - English, Indian
speech recognition models for 17 languages and dialects - English, Indian
English, German, French, Spanish, Portuguese, Chinese, Russian, Turkish,
Vietnamese, Italian, Dutch, Catalan, Arabic, Greek, Farsi.
Vietnamese, Italian, Dutch, Catalan, Arabic, Greek, Farsi, Filipino.
Vosk models are small (50 Mb) but provide continuous large vocabulary
transcription, zero-latency response with streaming API, reconfigurable
+2 -2
View File
@@ -32,7 +32,7 @@ set(API_SOURCES
"${PROJECT_SOURCE_DIR}/../src/vosk_api.h"
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DFST_NO_DYNAMIC_LINKING")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3 -DFST_NO_DYNAMIC_LINKING")
add_library( vosk_jni SHARED
build/generated-src/cpp/vosk_wrap.cc
@@ -60,7 +60,7 @@ target_link_libraries( vosk_jni
${KALDI_ROOT}/src/base/kaldi-base.a
${LIB_ROOT}/lib/libfst.a
${LIB_ROOT}/lib/libfstngram.a
${LIB_ROOT}/lib/libopenblas_${OPENBLAS_ARCH}-r0.3.7.a
${LIB_ROOT}/lib/libopenblas.a
${LIB_ROOT}/lib/libclapack.a
${LIB_ROOT}/lib/liblapack.a
${LIB_ROOT}/lib/libblas.a
+2 -21
View File
@@ -1,22 +1,3 @@
This is still work in progress, more to come
Vosk library for Android
## TODO
* Optimize graph construction, current one is below accuracy
* Load model from the AAR (mmap them in tflite style)
* Add decoding speed measurement
* Add wakeup word
* Add speakerid
* Integrate proper hardware optimized neural network library. Candidates are:
* https://github.com/XiaoMi/mace
* https://github.com/Tencent/ncnn
* https://developer.android.com/ndk/guides/neuralnetworks/ (since API level 27)
* https://github.com/google/XNNPACK
* Quantization for the models
See for details https://alphacephei.com/vosk/android
+3 -3
View File
@@ -39,7 +39,7 @@ 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/${OS_NAME}-x86_64/bin
OPENFST_VERSION=1.6.7
OPENFST_VERSION=1.8.0
mkdir -p $WORKDIR_ARM64/local/lib $WORKDIR_ARM32/local/lib $WORKDIR_X86_64/local/lib $WORKDIR_X86/local/lib
@@ -106,7 +106,7 @@ esac
# openblas first
cd $WORKDIR
git clone -b v0.3.7 --single-branch https://github.com/xianyi/OpenBLAS
git clone -b v0.3.13 --single-branch https://github.com/xianyi/OpenBLAS
make -C OpenBLAS TARGET=$BLAS_ARCH ONLY_CBLAS=1 AR=$AR CC=$CC HOSTCC=gcc ARM_SOFTFP_ABI=1 USE_THREAD=0 NUM_THREADS=1 -j4
make -C OpenBLAS install PREFIX=$WORKDIR/local
@@ -130,7 +130,7 @@ if [ "`uname`" == "Darwin" ]; then
fi
CXX=$CXX CXXFLAGS="$ARCHFLAGS -O3 -DFST_NO_DYNAMIC_LINKING" ./configure --use-cuda=no \
--mathlib=OPENBLAS --shared \
--mathlib=OPENBLAS_CLAPACK --shared \
--android-incdir=${ANDROID_TOOLCHAIN_PATH}/sysroot/usr/include \
--host=$HOST --openblas-root=${WORKDIR}/local \
--fst-root=${WORKDIR}/local --fst-version=${OPENFST_VERSION}
+1 -1
View File
@@ -14,7 +14,7 @@ plugins {
}
def archiveName = "vosk-android"
def libVersion = "0.3.15"
def libVersion = "0.3.17"
allprojects {
repositories {
+71
View File
@@ -0,0 +1,71 @@
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
}
}
plugins {
id "com.jfrog.bintray"
}
def archiveName = "vosk-model-en"
def libVersion = "0.3.17"
allprojects {
repositories {
google()
jcenter()
}
}
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
android {
compileSdkVersion 29
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 6
versionName = libVersion
archivesBaseName = archiveName
}
}
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
pkg {
repo = 'vosk'
name = 'vosk-model-en'
userOrg = "alphacep"
licenses = ['Apache2.0']
websiteUrl = 'https://github.com/alphacep/vosk-api'
issueTrackerUrl = 'https://github.com/alphacep/vosk-api/issues'
vcsUrl = 'https://github.com/alphacep/vosk-api'
version {
name = libVersion
vcsTag = libVersion
}
}
publications = ['aar']
}
publishing {
publications {
aar(MavenPublication) {
groupId 'com.alphacep'
artifactId archiveName
version libVersion
artifact("$buildDir/outputs/aar/$archiveName-release.aar")
}
}
}
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kaldi.model.en">
</manifest>
@@ -0,0 +1,7 @@
US English model for mobile Vosk applications
Copyright 2020 Alpha Cephei Inc
Accuracy: 10.38 (tedlium test) 9.85 (librispeech test-clean)
Speed: 0.11xRT (desktop)
Latency: 0.15s (right context)
@@ -0,0 +1 @@
0.3.16
+1
View File
@@ -0,0 +1 @@
include 'model-en'
+7 -41
View File
@@ -1,50 +1,16 @@
KALDI_ROOT=$(HOME)/travis/kaldi
VOSK_SOURCES= \
../src/kaldi_recognizer.cc \
../src/language_model.cc \
../src/model.cc \
../src/spk_model.cc \
../src/vosk_api.cc
CFLAGS=-g -O2 -DFST_NO_DYNAMIC_LINKING -I../src -I$(KALDI_ROOT)/src -I$(KALDI_ROOT)/tools/openfst/include
LIBS= \
$(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/OpenBLAS/libopenblas.a \
$(KALDI_ROOT)/tools/openfst/lib/libfst.a \
$(KALDI_ROOT)/tools/openfst/lib/libfstngram.a
CFLAGS=-I../src
LDFLAGS=-L../src -lvosk -ldl -lpthread -Wl,-rpath=../src
all: test_vosk test_vosk_speaker
test_vosk: test_vosk.o libvosk.a
g++ $^ -o $@ $(LIBS) -lgfortran -lpthread
test_vosk: test_vosk.o
g++ $^ -o $@ $(LDFLAGS)
test_vosk_speaker: test_vosk_speaker.o libvosk.a
g++ $^ -o $@ $(LIBS) -lgfortran -lpthread
libvosk.a: $(VOSK_SOURCES:.cc=.o)
ar rcs $@ $^
test_vosk_speaker: test_vosk_speaker.o
g++ $^ -o $@ $(LDFLAGS)
%.o: %.c
g++ $(CFLAGS) -c -o $@ $<
%.o: %.cc
g++ -std=c++11 $(CFLAGS) -c -o $@ $<
clean:
rm -f *.o *.a test_vosk
rm -f *.o *.a test_vosk test_vosk_speaker
+1
View File
@@ -24,5 +24,6 @@ int main() {
vosk_recognizer_free(recognizer);
vosk_model_free(model);
fclose(wavin);
return 0;
}
-62
View File
@@ -1,62 +0,0 @@
KALDI_ROOT ?= $(HOME)/kaldi
CFLAGS := -std=c++11 -g -O2 -DPIC -fPIC -Wno-unused-function
CPPFLAGS := -I$(KALDI_ROOT)/src -I$(KALDI_ROOT)/tools/openfst/include -I../src -DFST_NO_DYNAMIC_LINKING
KALDI_LIBS = \
${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
# On Linux
MATH_LIBS = ${KALDI_ROOT}/tools/OpenBLAS/libopenblas.a -lgfortran
# On OSX
# MATH_LIBS = -framework Accelerate
all: test.exe
test.exe: libkaldiwrap.so test.cs
mcs test.cs gen/*.cs
VOSK_SOURCES = \
vosk_wrap.c \
../src/kaldi_recognizer.cc \
../src/language_model.cc \
../src/model.cc \
../src/spk_model.cc \
../src/vosk_api.cc
VOSK_HEADERS = \
../src/kaldi_recognizer.h \
../src/language_model.h \
../src/model.h \
../src/vosk_api.h \
../src/spk_model.h
libkaldiwrap.so: $(VOSK_SOURCES) $(VOSK_HEADERS)
$(CXX) -fpermissive $(CFLAGS) $(CPPFLAGS) -shared -o $@ $(VOSK_SOURCES) $(KALDI_LIBS) $(MATH_LIBS)
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.c *.o gen/*.cs test.exe
+12
View File
@@ -0,0 +1,12 @@
This is a nuget-based wrapper for libvosk library
See demo folder for example how to use the library. You can simply run
"dotnet run" to run the demo. Make sure you unpacked the model and the
test file.
See the nuget folder for the sources of the wrapper. Run build.sh to
build nuget package.
Note we only support win64 and linux64 for now. No support for win32
since it is a little bit painful to load the libraries depending on
architecture. In theory we can add OSX some time or even Android.
+4 -4
View File
@@ -1,15 +1,15 @@
using System;
using System.IO;
using Kaldi;
using Vosk;
public class Test
{
public static void Main()
{
Vosk.SetLogLevel(0);
Vosk.Vosk.SetLogLevel(0);
Model model = new Model("model");
KaldiRecognizer rec = new KaldiRecognizer(model, 16000.0f);
VoskRecognizer rec = new VoskRecognizer(model, 16000.0f);
using(Stream source = File.OpenRead("test.wav")) {
byte[] buffer = new byte[4096];
@@ -24,7 +24,7 @@ public class Test
}
Console.WriteLine(rec.FinalResult());
rec = new KaldiRecognizer(model, 16000.0f);
rec = new VoskRecognizer(model, 16000.0f);
using(Stream source = File.OpenRead("test.wav")) {
byte[] buffer = new byte[4096];
+13
View File
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace>VoskDemo</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Vosk" Version="0.3.19" />
</ItemGroup>
</Project>
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<package>
<metadata>
<id>Vosk</id>
<version>0.3.19</version>
<authors>Alpha Cephei Inc</authors>
<owners>Alpha Cephei Inc</owners>
<license type="expression">Apache-2.0</license>
<projectUrl>https://alphacephei.com/vosk/</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Vosk is an offline open source speech recognition toolkit. It enables speech recognition models for 16 languages and dialects - English, Indian English, German, French, Spanish, Portuguese, Chinese, Russian, Turkish, Vietnamese, Italian, Dutch, Catalan, Arabic, Greek, Farsi.
Vosk models are small (50 Mb) but provide continuous large vocabulary transcription, zero-latency response with streaming API, reconfigurable vocabulary and speaker identification.
Speech recognition bindings implemented for various programming languages like Python, Java, Node.JS, C#, C++ and others.
Vosk supplies speech recognition for chatbots, smart home appliances, virtual assistants. It can also create subtitles for movies, transcription for lectures and interviews.
Vosk scales from small devices like Raspberry Pi or Android smartphone to big clusters.</description>
<releaseNotes>See for details https://github.com/alphacep/vosk-api/releases</releaseNotes>
<copyright>Copyright 2020 Alpha Cephei Inc</copyright>
<tags>speech recognition voice stt asr speech-to-text ai offline privacy</tags>
<dependencies>
<group targetFramework=".NETStandard2.0"/>
</dependencies>
</metadata>
<files>
<file src="**" exclude="src/*.cs;build.sh;**/.keep-me;*.nupkg" />
</files>
</package>
+2
View File
@@ -0,0 +1,2 @@
mcs -out:lib/netstandard2.0/Vosk.dll -target:library src/*.cs
nuget pack
+10
View File
@@ -0,0 +1,10 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)\lib\linux-x64\*.so" Condition="'$([MSBuild]::IsOsPlatform(Linux))'" />
<NativeLibs Include="$(MSBuildThisFileDirectory)\lib\win-x64\*.dll" Condition="'$([MSBuild]::IsOsPlatform(Windows))'" />
<None Include="@(NativeLibs)">
<Link>%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
+41
View File
@@ -0,0 +1,41 @@
namespace Vosk {
public class Model : global::System.IDisposable {
private global::System.Runtime.InteropServices.HandleRef handle;
internal Model(global::System.IntPtr cPtr) {
handle = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
}
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Model obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.handle;
}
~Model() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
global::System.GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
lock(this) {
if (handle.Handle != global::System.IntPtr.Zero) {
VoskPINVOKE.delete_Model(handle);
handle = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
}
}
public Model(string model_path) : this(VoskPINVOKE.new_Model(model_path)) {
}
public int vosk_model_find_word(string word) {
return VoskPINVOKE.Model_vosk_model_find_word(handle, word);
}
}
}
+37
View File
@@ -0,0 +1,37 @@
namespace Vosk {
public class SpkModel : global::System.IDisposable {
private global::System.Runtime.InteropServices.HandleRef handle;
internal SpkModel(global::System.IntPtr cPtr) {
handle = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
}
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(SpkModel obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.handle;
}
~SpkModel() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
global::System.GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
lock(this) {
if (handle.Handle != global::System.IntPtr.Zero) {
VoskPINVOKE.delete_SpkModel(handle);
handle = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
}
}
public SpkModel(string model_path) : this(VoskPINVOKE.new_SpkModel(model_path)) {
}
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace Vosk {
public class Vosk {
public static void SetLogLevel(int level) {
VoskPINVOKE.SetLogLevel(level);
}
}
}
+57
View File
@@ -0,0 +1,57 @@
namespace Vosk {
class VoskPINVOKE {
static VoskPINVOKE() {
}
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_model_new")]
public static extern global::System.IntPtr new_Model(string jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_model_free")]
public static extern void delete_Model(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_model_find_word")]
public static extern int Model_vosk_model_find_word(global::System.Runtime.InteropServices.HandleRef jarg1, string jarg2);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_spk_model_new")]
public static extern global::System.IntPtr new_SpkModel(string jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_spk_model_free")]
public static extern void delete_SpkModel(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_new")]
public static extern global::System.IntPtr new_VoskRecognizer(global::System.Runtime.InteropServices.HandleRef jarg1, float jarg2);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_new_spk")]
public static extern global::System.IntPtr new_VoskRecognizerSpk(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2, float jarg3);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_new_grm")]
public static extern global::System.IntPtr new_VoskRecognizerGrm(global::System.Runtime.InteropServices.HandleRef jarg1, float jarg2, string jarg3);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_free")]
public static extern void delete_VoskRecognizer(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_accept_waveform")]
public static extern bool VoskRecognizer_AcceptWaveform(global::System.Runtime.InteropServices.HandleRef jarg1, [global::System.Runtime.InteropServices.In, global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray)]byte[] jarg2, int jarg3);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_accept_waveform_s")]
public static extern bool VoskRecognizer_AcceptWaveformShort(global::System.Runtime.InteropServices.HandleRef jarg1, [global::System.Runtime.InteropServices.In, global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray)]short[] jarg2, int jarg3);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_accept_waveform_f")]
public static extern bool VoskRecognizer_AcceptWaveformFloat(global::System.Runtime.InteropServices.HandleRef jarg1, [global::System.Runtime.InteropServices.In, global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray)]float[] jarg2, int jarg3);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_result")]
public static extern global::System.IntPtr VoskRecognizer_Result(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_partial_result")]
public static extern global::System.IntPtr VoskRecognizer_PartialResult(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_recognizer_final_result")]
public static extern global::System.IntPtr VoskRecognizer_FinalResult(global::System.Runtime.InteropServices.HandleRef jarg1);
[global::System.Runtime.InteropServices.DllImport("libvosk", EntryPoint="vosk_set_log_level")]
public static extern void SetLogLevel(int jarg1);
}
}
+67
View File
@@ -0,0 +1,67 @@
namespace Vosk {
public class VoskRecognizer : global::System.IDisposable {
private global::System.Runtime.InteropServices.HandleRef handle;
internal VoskRecognizer(global::System.IntPtr cPtr) {
handle = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
}
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(VoskRecognizer obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.handle;
}
~VoskRecognizer() {
Dispose(false);
}
public void Dispose() {
Dispose(true);
global::System.GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
lock(this) {
if (handle.Handle != global::System.IntPtr.Zero) {
VoskPINVOKE.delete_VoskRecognizer(handle);
handle = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
}
}
public VoskRecognizer(Model model, float sample_rate) : this(VoskPINVOKE.new_VoskRecognizer(Model.getCPtr(model), sample_rate)) {
}
public VoskRecognizer(Model model, SpkModel spk_model, float sample_rate) : this(VoskPINVOKE.new_VoskRecognizerSpk(Model.getCPtr(model), SpkModel.getCPtr(spk_model), sample_rate)) {
}
public VoskRecognizer(Model model, float sample_rate, string grammar) : this(VoskPINVOKE.new_VoskRecognizerGrm(Model.getCPtr(model), sample_rate, grammar)) {
}
public bool AcceptWaveform(byte[] data, int len) {
return VoskPINVOKE.VoskRecognizer_AcceptWaveform(handle, data, len);
}
public bool AcceptWaveform(short[] sdata, int len) {
return VoskPINVOKE.VoskRecognizer_AcceptWaveformShort(handle, sdata, len);
}
public bool AcceptWaveform(float[] fdata, int len) {
return VoskPINVOKE.VoskRecognizer_AcceptWaveformFloat(handle, fdata, len);
}
public string Result() {
return global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_Result(handle));
}
public string PartialResult() {
return global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_PartialResult(handle));
}
public string FinalResult() {
return global::System.Runtime.InteropServices.Marshal.PtrToStringUTF8(VoskPINVOKE.VoskRecognizer_FinalResult(handle));
}
}
}
+14 -93
View File
@@ -16,56 +16,12 @@
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 */; };
92BACED125BE125A00B5CC93 /* vosk-model-small-en-us-0.15 in Resources */ = {isa = PBXBuildFile; fileRef = 928CC50C25BE124400490481 /* vosk-model-small-en-us-0.15 */; };
92D6B8D325BDFEAC007FF08D /* VoskModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D6B8D225BDFEAC007FF08D /* VoskModel.swift */; };
92D86BD6253F823F0040D53F /* vosk-model-spk-0.4 in Resources */ = {isa = PBXBuildFile; fileRef = 92D86BD4253F823F0040D53F /* vosk-model-spk-0.4 */; };
/* 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>"; };
@@ -78,22 +34,12 @@
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>"; };
928CC50C25BE124400490481 /* vosk-model-small-en-us-0.15 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "vosk-model-small-en-us-0.15"; path = "/Users/shmyrev/Documents/IOS/VoskApiTest/VoskApiTest/Vosk/vosk-model-small-en-us-0.15"; sourceTree = "<absolute>"; };
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>"; };
92D6B8D225BDFEAC007FF08D /* VoskModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoskModel.swift; sourceTree = "<group>"; };
92D86BD4253F823F0040D53F /* vosk-model-spk-0.4 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "vosk-model-spk-0.4"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -139,6 +85,7 @@
9237522A240C550B00DD6076 /* LaunchScreen.storyboard */,
9237522D240C550B00DD6076 /* Info.plist */,
92375233240C558900DD6076 /* Vosk.swift */,
92D6B8D225BDFEAC007FF08D /* VoskModel.swift */,
);
path = VoskApiTest;
sourceTree = "<group>";
@@ -146,7 +93,8 @@
92375239240C642000DD6076 /* Vosk */ = {
isa = PBXGroup;
children = (
92375247240C6E3D00DD6076 /* model-android */,
928CC50C25BE124400490481 /* vosk-model-small-en-us-0.15 */,
92D86BD4253F823F0040D53F /* vosk-model-spk-0.4 */,
92375256240C6E3D00DD6076 /* 10001-90210-01803.wav */,
92AA22AD244CDD1200DA464B /* vosk_api.h */,
9237523A240C642000DD6076 /* libkaldiwrap.a */,
@@ -164,34 +112,6 @@
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 */
@@ -202,8 +122,6 @@
9237521A240C550B00DD6076 /* Sources */,
9237521B240C550B00DD6076 /* Frameworks */,
9237521C240C550B00DD6076 /* Resources */,
92375265240C6ECF00DD6076 /* CopyFiles */,
9237526D240C6F0400DD6076 /* CopyFiles */,
);
buildRules = (
);
@@ -254,9 +172,11 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
92BACED125BE125A00B5CC93 /* vosk-model-small-en-us-0.15 in Resources */,
92375274240C6F1E00DD6076 /* 10001-90210-01803.wav in Resources */,
9237522C240C550B00DD6076 /* LaunchScreen.storyboard in Resources */,
92375229240C550B00DD6076 /* Assets.xcassets in Resources */,
92D86BD6253F823F0040D53F /* vosk-model-spk-0.4 in Resources */,
92375227240C550B00DD6076 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -270,6 +190,7 @@
files = (
92375224240C550B00DD6076 /* ViewController.swift in Sources */,
92375222240C550B00DD6076 /* AppDelegate.swift in Sources */,
92D6B8D325BDFEAC007FF08D /* VoskModel.swift in Sources */,
92375234240C558900DD6076 /* Vosk.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -412,7 +333,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
ENABLE_BITCODE = NO;
ENABLE_BITCODE = YES;
INFOPLIST_FILE = VoskApiTest/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
@@ -434,7 +355,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
ENABLE_BITCODE = NO;
ENABLE_BITCODE = YES;
INFOPLIST_FILE = VoskApiTest/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
@@ -2,6 +2,9 @@
<Workspace
version = "1.0">
<FileRef
location = "self:VoskApiTest.xcodeproj">
location = "group:/Users/shmyrev/Documents/IOS/VoskApiTest/VoskApiTest/Vosk/vosk-model-small-en-us-0.15">
</FileRef>
<FileRef
location = "self:">
</FileRef>
</Workspace>
+42 -13
View File
@@ -1,6 +1,6 @@
<?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">
<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="bdW-KL-Y8Z">
<device id="retina5_5" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
@@ -10,23 +10,52 @@
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<scene sceneID="nEc-89-Iqu">
<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"/>
<viewController id="bdW-KL-Y8Z" customClass="ViewController" customModule="VoskApiTest" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Hyr-Dz-4mU"/>
<viewControllerLayoutGuide type="bottom" id="w4A-5X-uBu"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="m5v-US-bvR">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IaT-no-U3i" userLabel="Microphone">
<rect key="frame" x="124" y="34" width="157" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Recognize Microphone"/>
<connections>
<action selector="runRecognizeMicrohpone:" destination="bdW-KL-Y8Z" eventType="touchUpInside" id="hGB-lz-N2B"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GC5-nT-FQR" userLabel="File">
<rect key="frame" x="90" y="84" width="221" height="41"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal" title="Recognize File"/>
<connections>
<action selector="runRecognizeFile:" destination="bdW-KL-Y8Z" eventType="touchUpInside" id="xp5-Yi-rnN"/>
</connections>
</button>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" text="Results here" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="w4X-cu-USq">
<rect key="frame" x="11" y="112" width="383" height="569"/>
<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>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</view>
<connections>
<outlet property="mainText" destination="CtX-mx-X98" id="oJy-5J-NKp"/>
<outlet property="mainText" destination="w4X-cu-USq" id="rZS-nz-Wql"/>
<outlet property="recognizeFile" destination="GC5-nT-FQR" id="dRe-tc-IA0"/>
<outlet property="recognizeMicrophone" destination="IaT-no-U3i" id="IuM-aa-pAP"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="nWA-4D-pA6" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="32.799999999999997" y="32.833583208395808"/>
<point key="canvasLocation" x="-17.39130434782609" y="-285.32608695652175"/>
</scene>
</scenes>
</document>
+95 -12
View File
@@ -3,30 +3,113 @@
// VoskApiTest
//
// Created by Niсkolay Shmyrev on 01.03.20.
// Copyright © 2020 Alpha Cephei. All rights reserved.
// Copyright © 2020-2021 Alpha Cephei. All rights reserved.
//
import UIKit
import AVFoundation
enum WorkMode {
case stopped
case microphone
case file
}
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..."
var mode: WorkMode!
@IBOutlet weak var recognizeFile: UIButton!
@IBOutlet weak var mainText: UITextView!
@IBOutlet weak var recognizeMicrophone: UIButton!
var audioEngine : AVAudioEngine!
var processingQueue: DispatchQueue!
var model : VoskModel!
func setMode(mode: WorkMode) {
switch mode {
case .stopped:
self.recognizeFile.isEnabled = true
self.recognizeMicrophone.isEnabled = true
self.recognizeMicrophone.setTitle("Recognize Microphone",for: .normal)
case .microphone:
self.recognizeFile.isEnabled = false
self.recognizeMicrophone.isEnabled = true
self.recognizeMicrophone.setTitle("Stop Microphone",for: .normal)
self.mainText.text = ""
case .file:
self.recognizeFile.isEnabled = false
self.recognizeMicrophone.isEnabled = false
self.mainText.text = "Processing file..."
}
self.mode = mode
}
func startAudioEngine() {
do {
// Create a new audio engine.
audioEngine = AVAudioEngine()
let inputNode = audioEngine.inputNode
let formatInput = inputNode.inputFormat(forBus: 0)
let formatPcm = AVAudioFormat.init(commonFormat: AVAudioCommonFormat.pcmFormatInt16, sampleRate: formatInput.sampleRate, channels: 1, interleaved: true)
let recognizer = Vosk(model: model, sampleRate: Float(formatInput.sampleRate))
inputNode.installTap(onBus: 0,
bufferSize: UInt32(formatInput.sampleRate / 10),
format: formatPcm) { buffer, time in
self.processingQueue.async {
let res = recognizer.recognizeData(buffer: buffer)
DispatchQueue.main.async {
self.mainText.text = res + "\n" + self.mainText.text
}
}
}
let vosk = Vosk()
let res = vosk.recognizeFile()
// Start the stream of audio data.
audioEngine.prepare()
try audioEngine.start()
} catch {
print("Unable to start AVAudioEngine: \(error.localizedDescription)")
}
}
func stopAudioEngine() {
audioEngine.stop()
}
@IBAction func runRecognizeMicrohpone(_ sender: Any) {
if (mode == .stopped) {
setMode(mode: .microphone)
startAudioEngine()
} else {
stopAudioEngine()
setMode(mode: .stopped)
}
}
@IBAction func runRecognizeFile(_ sender: Any) {
setMode(mode: .file)
processingQueue.async {
let recognizer = Vosk(model: self.model, sampleRate: 16000.0)
let res = recognizer.recognizeFile()
DispatchQueue.main.async {
self.mainText.text = res
self.setMode(mode: .stopped)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
setMode(mode: .stopped)
processingQueue = DispatchQueue(label: "recognizerQueue")
model = VoskModel()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
+33 -16
View File
@@ -3,35 +3,52 @@
// VoskApiTest
//
// Created by Niсkolay Shmyrev on 01.03.20.
// Copyright © 2020 Alpha Cephei. All rights reserved.
// Copyright © 2020-2021 Alpha Cephei. All rights reserved.
//
import Foundation
import AVFoundation
public final class Vosk {
var recognizer : OpaquePointer!
init(model: VoskModel, sampleRate: Float) {
recognizer = vosk_recognizer_new_spk(model.model, model.spkModel, sampleRate)
}
deinit {
vosk_recognizer_free(recognizer);
}
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);
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
}
func recognizeData(buffer : AVAudioPCMBuffer) -> String {
let dataLen = Int(buffer.frameLength * 2)
let channels = UnsafeBufferPointer(start: buffer.int16ChannelData, count: 1)
let endOfSpeech = channels[0].withMemoryRebound(to: Int8.self, capacity: dataLen) {
vosk_recognizer_accept_waveform(recognizer, $0, Int32(dataLen))
}
let res = endOfSpeech == 1 ?vosk_recognizer_result(recognizer) :vosk_recognizer_partial_result(recognizer)
return String(validatingUTF8: res!)!;
}
}
+4 -3
View File
@@ -88,10 +88,10 @@ VoskRecognizer *vosk_recognizer_new(VoskModel *model, float sample_rate);
VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, VoskSpkModel *spk_model, float sample_rate);
/** Creates the recognizer object with the grammar
/** Creates the recognizer object with the phrase list
*
* 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
* to recognize large vocabulary you can specify a list of phrases to recognize. This
* will improve recognizer speed and accuracy but might return [unk] if user said
* something different.
*
@@ -99,7 +99,8 @@ VoskRecognizer *vosk_recognizer_new_spk(VoskModel *model, VoskSpkModel *spk_mode
* 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]"
* @param grammar The string with the list of phrases to recognize as JSON array of strings,
* for example "["one two three four five", "[unk]"]".
*
* @returns recognizer object */
VoskRecognizer *vosk_recognizer_new_grm(VoskModel *model, float sample_rate, const char *grammar);
+36
View File
@@ -0,0 +1,36 @@
//
// Vosk.swift
// VoskApiTest
//
// Created by Niсkolay Shmyrev on 01.03.20.
// Copyright © 2020-2021 Alpha Cephei. All rights reserved.
//
import Foundation
public final class VoskModel {
var model : OpaquePointer!
var spkModel : OpaquePointer!
init() {
// Set to -1 to disable logs
vosk_set_log_level(0);
if let resourcePath = Bundle.main.resourcePath {
let modelPath = resourcePath + "/vosk-model-small-en-us-0.15"
let spkModelPath = resourcePath + "/vosk-model-spk-0.4"
model = vosk_model_new(modelPath)
spkModel = vosk_spk_model_new(spkModelPath)
}
}
deinit {
vosk_model_free(model)
vosk_spk_model_free(spkModel)
}
}
-67
View File
@@ -1,67 +0,0 @@
KALDI_ROOT ?= $(HOME)/kaldi
CFLAGS := -g -O2 -DPIC -fPIC -Wno-unused-function
CPPFLAGS := -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux -I$(KALDI_ROOT)/src -I$(KALDI_ROOT)/tools/openfst/include -I../src
KALDI_LIBS = \
${KALDI_ROOT}/src/online2/kaldi-online2.a \
${KALDI_ROOT}/src/decoder/kaldi-decoder.a \
${KALDI_ROOT}/src/ivector/kaldi-ivector.a \
${KALDI_ROOT}/src/gmm/kaldi-gmm.a \
${KALDI_ROOT}/src/nnet3/kaldi-nnet3.a \
${KALDI_ROOT}/src/tree/kaldi-tree.a \
${KALDI_ROOT}/src/feat/kaldi-feat.a \
${KALDI_ROOT}/src/lat/kaldi-lat.a \
${KALDI_ROOT}/src/lm/kaldi-lm.a \
${KALDI_ROOT}/src/hmm/kaldi-hmm.a \
${KALDI_ROOT}/src/transform/kaldi-transform.a \
${KALDI_ROOT}/src/cudamatrix/kaldi-cudamatrix.a \
${KALDI_ROOT}/src/matrix/kaldi-matrix.a \
${KALDI_ROOT}/src/fstext/kaldi-fstext.a \
${KALDI_ROOT}/src/util/kaldi-util.a \
${KALDI_ROOT}/src/base/kaldi-base.a \
${KALDI_ROOT}/tools/openfst/lib/libfst.a \
${KALDI_ROOT}/tools/openfst/lib/libfstngram.a \
${KALDI_ROOT}/tools/OpenBLAS/libopenblas.a \
-lgfortran
all: libvosk_jni.so
VOSK_SOURCES = \
vosk_wrap.cc \
../src/kaldi_recognizer.cc \
../src/kaldi_recognizer.h \
../src/language_model.cc \
../src/language_model.h \
../src/model.cc \
../src/model.h \
../src/spk_model.cc \
../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 -c++ -I../src \
-java -package org.kaldi \
-outdir org/kaldi -o $@ $<
clean:
$(RM) *.so *_wrap.cc *_wrap.o test/*.class
$(RM) -r org model-en
model:
wget https://alphacephei.com/kaldi/models/vosk-model-small-en-us-0.3.zip
unzip vosk-model-small-en-us-0.3.zip && rm vosk-model-small-en-us-0.3.zip
mv vosk-model-small-en-us-0.3 model
model-spk:
wget https://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
+3 -17
View File
@@ -1,19 +1,5 @@
Java API sample
Java Vosk API using jnr-ffi
Doesn't work on Windows or Mac yet, help to prepare the packaged jars is welcome.
Still needs classes to wrap C code
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
Run with simple gradle build. Unpack model and put libvosk library in current folder.
+12
View File
@@ -0,0 +1,12 @@
apply plugin: "application"
mainClassName = "test.DecoderTest"
applicationDefaultJvmArgs = ['-Djna.library.path=.']
repositories {
mavenCentral()
}
dependencies {
implementation group: 'net.java.dev.jna', name: 'jna', version: '4.5.0'
}
+49
View File
@@ -0,0 +1,49 @@
package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.*;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class DecoderTest {
public interface LibVosk extends Library {
static LibVosk INSTANCE = (LibVosk) Native.loadLibrary("vosk", LibVosk.class);
void vosk_set_log_level(int level);
Pointer vosk_model_new(String path);
void vosk_model_free(Pointer model);
Pointer vosk_recognizer_new(Pointer model, float sample_rate);
boolean vosk_recognizer_accept_waveform(Pointer recognizer, byte[] data, int len);
String vosk_recognizer_result(Pointer recognizer);
String vosk_recognizer_final_result(Pointer recognizer);
String vosk_recognizer_partial_result(Pointer recognizer);
void vosk_recognizer_free(Pointer recognizer);
}
public static void main(String[] args) throws IOException {
LibVosk.INSTANCE.vosk_set_log_level(0);
Pointer model = LibVosk.INSTANCE.vosk_model_new("model");
FileInputStream ais = new FileInputStream(new File("../python/example/test.wav"));
Pointer rec = LibVosk.INSTANCE.vosk_recognizer_new(model, 16000.0f);
int nbytes;
byte[] b = new byte[4096];
while ((nbytes = ais.read(b)) >= 0) {
if (LibVosk.INSTANCE.vosk_recognizer_accept_waveform(rec, b, nbytes)) {
System.out.println(LibVosk.INSTANCE.vosk_recognizer_result(rec));
} else {
System.out.println(LibVosk.INSTANCE.vosk_recognizer_partial_result(rec));
}
}
System.out.println(LibVosk.INSTANCE.vosk_recognizer_final_result(rec));
LibVosk.INSTANCE.vosk_recognizer_free(rec);
LibVosk.INSTANCE.vosk_model_free(model);
}
}
-37
View File
@@ -1,37 +0,0 @@
package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.*;
import org.kaldi.KaldiRecognizer;
import org.kaldi.Model;
import org.kaldi.SpkModel;
import org.kaldi.Vosk;
public class DecoderTest {
public static void main(String args[]) throws IOException {
Vosk.SetLogLevel(-10);
FileInputStream ais = new FileInputStream(new File("../python/example/test.wav"));
Model model = new Model("model");
SpkModel spkModel = new SpkModel("model-spk");
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)) {
System.out.println(rec.Result());
} else {
System.out.println(rec.PartialResult());
}
}
System.out.println(rec.FinalResult());
}
}
+3 -3
View File
@@ -1,3 +1,3 @@
build
node_modules
vosk_wrap.cc
demo/model
demo/model-spk
demo/test.wav
+27 -14
View File
@@ -1,20 +1,33 @@
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.
This is an FFI-NAPI wrapper for the Vosk library.
The build tested with node-0.10.15, node-0.12 is not yet supported by swig.
## Usage
Still, you need swig of newest version 4.0.1
It mostly follows Vosk interface, some methods are not yet fully implemented.
Build like this
To use it you need to compile libvosk library, see Python module build
instructions for details. You can find prebuilt library inside python
wheel.
```
npm install --kaldi_root=/home/user/kaldi
```
## About
Then test with
Vosk is an offline open source speech recognition toolkit. It enables
speech recognition models for 17 languages and dialects - English, Indian
English, German, French, Spanish, Portuguese, Chinese, Russian, Turkish,
Vietnamese, Italian, Dutch, Catalan, Arabic, Greek, Farsi, Filipino.
```
cd example
node test.js
```
Vosk models are small (50 Mb) but provide continuous large vocabulary
transcription, zero-latency response with streaming API, reconfigurable
vocabulary and speaker identification.
Vosk supplies speech recognition for chatbots, smart home appliances,
virtual assistants. It can also create subtitles for movies,
transcription for lectures and interviews.
Vosk scales from small devices like Raspberry Pi or Android smartphone to
big clusters.
# Documentation
For installation instructions, examples and documentation visit [Vosk
Website](https://alphacephei.com/vosk). See also our project on
[Github](https://github.com/alphacep/vosk-api).
-80
View File
@@ -1,80 +0,0 @@
{
'targets': [
{
'target_name': 'vosk',
'sources': [
'../src/kaldi_recognizer.cc',
'../src/model.cc',
'../src/language_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',
],
'conditions': [
['OS == "mac"', {
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'GCC_ENABLE_CPP_RTTI': 'YES',
'CLANG_CXX_LANGUAGE_STANDARD': 'c++11'
}
}]
],
'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',
],
},
}
]
}
+30
View File
@@ -0,0 +1,30 @@
var vosk = require('..')
const fs = require("fs");
const { Readable } = require("stream");
const wav = require("wav");
vosk.setLogLevel(0);
const model = new vosk.Model("model");
const rec = new vosk.Recognizer(model, 16000.0);
const wfStream = fs.createReadStream("test.wav", {'highWaterMark': 4096});
const wfReader = new wav.Reader();
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);
}
for await (const data of new Readable().wrap(wfReader)) {
const end_of_speech = rec.acceptWaveform(data);
if (end_of_speech) {
console.log(rec.result());
}
}
console.log(rec.finalResult(rec));
rec.free();
model.free();
});
wfStream.pipe(wfReader);
-90
View File
@@ -1,90 +0,0 @@
const wav = require('wav')
const fs = require('fs')
const {Readable} = require('stream')
const {Model, KaldiRecognizer, SpkModel} = require('..')
try {
fs.accessSync('model', fs.constants.R_OK)
} catch (err) {
console.error("Please download the model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model' in the current folder.")
process.exit(1)
}
try {
fs.accessSync('model-spk', fs.constants.R_OK)
} catch (err) {
console.error("Please download the speaker model from https://github.com/alphacep/kaldi-android-demo/releases and unpack as 'model-spk' in the current folder.")
process.exit(1)
}
const wfStream = fs.createReadStream('test.wav', { highWaterMark: 4096 })
const wfReader = new wav.Reader()
const model = new Model('model')
const spkModel = new SpkModel('model-spk')
const spk_sig = [-0.56648, 0.030579, 1.730239, 0.239899, -1.194183,
0.251954, 0.540388, -0.971872, -0.020963, 0.085036, 0.563973, -0.019682,
-0.597381, 1.094719, -0.566738, 0.29819, 0.171165, 0.370341, -0.033539,
-0.09757, 1.228286, 0.485949, 0.427826, 0.147762, -0.015112, 0.599513,
-2.040655, -0.490882, 0.440161, -0.072991, 0.835955, -0.496124, 0.952978,
0.85356, -1.096116, 0.107764, -0.385486, 1.410305, 0.609147, -0.457014,
-1.542864, 0.343669, 0.171913, -0.627281, -1.281781, -1.134276,
-0.639895, 1.190183, -0.700537, 1.063457, 0.206946, 0.342198, -1.165625,
1.475955, -0.089007, -2.555155, 0.551438, -0.212736, 1.025625, -1.631965,
-0.716256, -1.295995, 1.554956, -1.866009, -1.010782, -1.43231, 0.109027,
2.123925, 1.703283, -0.784997, 2.730568, 0.755113, 0.0617, 0.128955,
-0.054047, 1.359119, -0.611666, -1.105754, -0.631353, 0.052109, 0.729386,
-0.769876, 1.250235, -1.463298, 0.648176, -0.73239, -0.385239,
-1.661856, 0.602106, -0.45567, -1.438431, -0.836673, 0.033557, 0.373597,
-1.343341, -0.181095, 0.237287, -0.522005, -1.722836, 0.932333,
-0.092861, -0.219254, 0.476182, 1.033803, -1.633563, -0.874341, 1.039064,
-1.758573, -0.838422, -0.324336, -0.924634, 1.962594, 2.152814, 1.2521,
-0.46172, -1.50271, 1.685691, 0.403097, -0.819042, 0.866403, -0.591716,
-0.578645, -0.553839, 0.381861, -1.051647, -1.477578, 0.524005, 0.925245]
function dotp(x, y) {
function dotp_sum(a, b) {
return a + b
}
function dotp_times(a, i) {
return x[i] * y[i]
}
return x.map(dotp_times).reduce(dotp_sum, 0)
}
function cosineSimilarity(A, B) {
var similarity =
dotp(A, B) / (Math.sqrt(dotp(A, A)) * Math.sqrt(dotp(B, B)))
return similarity
}
function cosine_dist(x, y) {
return 1 - cosineSimilarity(x, y)
}
wfReader.on('format', async ({ audioFormat, sampleRate, channels }) => {
if (audioFormat != 1 || channels != 1) {
console.error('Audio file must be WAV format mono PCM.')
process.exit(1)
}
const rec = new KaldiRecognizer(model, spkModel, sampleRate)
for await (const data of new Readable().wrap(wfReader)) {
const endOfSpeech = await rec.AcceptWaveform(data)
if (endOfSpeech) {
res = await JSON.parse(rec.Result());
console.log(res)
console.log('X-vector:', JSON.stringify(res['spk']))
console.log('Speaker distance:', cosine_dist(spk_sig, res['spk']))
} else {
console.log(await rec.PartialResult())
}
}
res = await JSON.parse(rec.FinalResult());
console.log(res)
console.log('X-vector:', JSON.stringify(res['spk']))
console.log('Speaker distance:', cosine_dist(spk_sig, res['spk']))
})
wfStream.pipe(wfReader)
-38
View File
@@ -1,38 +0,0 @@
#!/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);
+76 -2
View File
@@ -1,3 +1,77 @@
const voskNativeModule = require('./build/Release/vosk.node');
'use strict'
module.exports = voskNativeModule;
const os = require('os');
const path = require('path');
const ffi = require('ffi-napi');
const ref = require('ref-napi');
const vosk_model = ref.types.void;
const vosk_model_ptr = ref.refType(vosk_model);
const vosk_spk_model = ref.types.void;
const vosk_spk_model_ptr = ref.refType(vosk_spk_model);
const vosk_recognizer = ref.types.void;
const vosk_recognizer_ptr = ref.refType(vosk_recognizer);
var soname;
if (os.platform == 'win32') {
soname = path.join(__dirname, "lib", "win-x86_64", "libvosk.dll")
} else {
soname = path.join(__dirname, "lib", "linux-x86_64", "libvosk.so")
}
const libvosk = ffi.Library(soname, {
'vosk_set_log_level': [ 'void', [ 'int' ] ],
'vosk_model_new': [ vosk_model_ptr, [ 'string' ] ],
'vosk_model_free': [ 'void', [ vosk_model_ptr ] ],
'vosk_recognizer_new': [ vosk_recognizer_ptr, [ vosk_model_ptr, 'float' ] ],
'vosk_recognizer_free': [ 'void', [ vosk_recognizer_ptr ] ],
'vosk_recognizer_accept_waveform': [ 'bool', [ vosk_recognizer_ptr, 'pointer', 'int' ] ],
'vosk_recognizer_result': ['string', [vosk_recognizer_ptr ] ],
'vosk_recognizer_final_result': ['string', [vosk_recognizer_ptr ] ],
});
function setLogLevel(level) {
libvosk.vosk_set_log_level(level);
}
function Model(model_path) {
this.handle = libvosk.vosk_model_new(model_path);
this.free = function() {
libvosk.vosk_model_free(this.handle);
}
this.getHandle = function() {
return this.handle;
}
}
function Recognizer(model, sample_rate) {
this.handle = libvosk.vosk_recognizer_new(model.getHandle(), sample_rate);
this.free = function() {
libvosk.vosk_recognizer_free(this.handle);
}
this.acceptWaveform = function(data) {
return libvosk.vosk_recognizer_accept_waveform(this.handle, data, data.length);
}
this.result = function() {
return libvosk.vosk_recognizer_result(this.handle);
}
this.partialResult = function() {
return libvosk.vosk_recognizer_partial_result(this.handle);
}
this.finalResult = function() {
return libvosk.vosk_recognizer_final_result(this.handle);
}
}
exports.setLogLevel = setLogLevel
exports.Model = Model
exports.Recognizer = Recognizer
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "vosk",
"version": "0.3.15",
"version": "0.3.21",
"description": "Node binding for continuous offline voice recoginition with Vosk library.",
"repository": {
"type": "git",
@@ -15,10 +15,11 @@
"author": "Alpha Cephei Inc.",
"license": "Apache-2.0",
"engines": {
"node": ">= 10.x.x"
"node": ">= 12.x.x"
},
"dependencies": {
"node-gyp": "^5.1.1",
"ffi-napi": "^3.1.0",
"ref-napi": "^3.0.0",
"wav": "^1.0.2"
}
}
+2 -2
View File
@@ -1,9 +1,9 @@
This is a Python module for Vosk.
Vosk is an offline open source speech recognition toolkit. It enables
speech recognition models for 16 languages and dialects - English, Indian
speech recognition models for 17 languages and dialects - English, Indian
English, German, French, Spanish, Portuguese, Chinese, Russian, Turkish,
Vietnamese, Italian, Dutch, Catalan, Arabic, Greek, Farsi.
Vietnamese, Italian, Dutch, Catalan, Arabic, Greek, Farsi, Filipino.
Vosk models are small (50 Mb) but provide continuous large vocabulary
transcription, zero-latency response with streaming API, reconfigurable
+80 -18
View File
@@ -1,28 +1,90 @@
#!/usr/bin/env python3
from vosk import Model, KaldiRecognizer
import argparse
import os
import queue
import sounddevice as sd
import vosk
import sys
if not os.path.exists("model"):
print ("Please download the model from https://alphacephei.com/vosk/models and unpack as 'model' in the current folder.")
exit (1)
q = queue.Queue()
import pyaudio
def int_or_str(text):
"""Helper function for argument parsing."""
try:
return int(text)
except ValueError:
return text
model = Model("model")
rec = KaldiRecognizer(model, 16000)
def callback(indata, frames, time, status):
"""This is called (from a separate thread) for each audio block."""
if status:
print(status, file=sys.stderr)
q.put(indata)
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=8000)
stream.start_stream()
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
'-l', '--list-devices', action='store_true',
help='show list of audio devices and exit')
args, remaining = parser.parse_known_args()
if args.list_devices:
print(sd.query_devices())
parser.exit(0)
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[parser])
parser.add_argument(
'-f', '--filename', type=str, metavar='FILENAME',
help='audio file to store recording to')
parser.add_argument(
'-m', '--model', type=str, metavar='MODEL_PATH',
help='Path to the model')
parser.add_argument(
'-d', '--device', type=int_or_str,
help='input device (numeric ID or substring)')
parser.add_argument(
'-r', '--samplerate', type=int, help='sampling rate')
args = parser.parse_args(remaining)
while True:
data = stream.read(4000)
if len(data) == 0:
break
if rec.AcceptWaveform(data):
print(rec.Result())
try:
if args.model is None:
args.model = "model"
if not os.path.exists(args.model):
print ("Please download a model for your language from https://alphacephei.com/vosk/models")
print ("and unpack as 'model' in the current folder.")
parser.exit(0)
if args.samplerate is None:
device_info = sd.query_devices(args.device, 'input')
# soundfile expects an int, sounddevice provides a float:
args.samplerate = int(device_info['default_samplerate'])
model = vosk.Model(args.model)
if args.filename:
dump_fn = open(args.filename, "wb")
else:
print(rec.PartialResult())
dump_fn = None
print(rec.FinalResult())
with sd.RawInputStream(samplerate=args.samplerate, blocksize = 8000, device=args.device, dtype='int16',
channels=1, callback=callback):
print('#' * 80)
print('Press Ctrl+C to stop the recording')
print('#' * 80)
rec = vosk.KaldiRecognizer(model, args.samplerate)
while True:
data = q.get()
data = bytes(data)
if rec.AcceptWaveform(data):
print(rec.Result())
else:
print(rec.PartialResult())
if dump_fn is not None:
dump_fn.write(data)
except KeyboardInterrupt:
print('\nDone')
parser.exit(0)
except Exception as e:
parser.exit(type(e).__name__ + ': ' + str(e))
+6 -4
View File
@@ -44,13 +44,15 @@ while True:
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']), "based on", res['spk_frames'], "frames")
if 'spk' in res:
print ("X-vector:", res['spk'])
print ("Speaker distance:", cosine_dist(spk_sig, res['spk']), "based on", res['spk_frames'], "frames")
print ("Note that second distance is not very reliable because utterance is too short. Utterances longer than 4 seconds give better xvector")
res = json.loads(rec.FinalResult())
print ("Text:", res['text'])
print ("X-vector:", res['spk'])
print ("Speaker distance:", cosine_dist(spk_sig, res['spk']), "based on", res['spk_frames'], "frames")
if 'spk' in res:
print ("X-vector:", res['spk'])
print ("Speaker distance:", cosine_dist(spk_sig, res['spk']), "based on", res['spk_frames'], "frames")
+12 -6
View File
@@ -25,6 +25,8 @@ process = subprocess.Popen(['ffmpeg', '-loglevel', 'quiet', '-i',
stdout=subprocess.PIPE)
WORDS_PER_LINE = 7
def transcribe():
results = []
subs = []
@@ -38,12 +40,16 @@ def transcribe():
for i, res in enumerate(results):
jres = json.loads(res)
s = srt.Subtitle(index=i,
content=jres['text'],
start=datetime.timedelta(seconds=jres['result'][0]['start']),
end=datetime.timedelta(seconds=jres['result'][-1]['end']))
subs.append(s)
if not 'result' in jres:
continue
words = jres['result']
for j in range(0, len(words), WORDS_PER_LINE):
line = words[j : j + WORDS_PER_LINE]
s = srt.Subtitle(index=len(subs),
content=" ".join([l['word'] for l in line]),
start=datetime.timedelta(seconds=line[0]['start']),
end=datetime.timedelta(seconds=line[-1]['end']))
subs.append(s)
return subs
print (srt.compose(transcribe()))
+43 -67
View File
@@ -1,79 +1,50 @@
import os
import sys
import setuptools
from setuptools import Extension
from setuptools.command.build_py import build_py as _build_py
import distutils.dir_util
import distutils.log
import shutil
import glob
import platform
class build_py(_build_py):
def run(self):
self.run_command("build_ext")
return super().run()
# Figure out environment for cross-compile
vosk_source = os.getenv("VOSK_SOURCE", os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
system = os.environ.get('VOSK_PLATFORM', platform.system())
architecture = os.environ.get('VOSK_ARCHITECTURE', platform.architecture()[0])
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")))
# Copy precompmilled libraries
for lib in glob.glob(os.path.join(vosk_source, "src/lib*.*")):
print ("Adding library", lib)
shutil.copy(lib, "vosk")
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)
# Create OS-dependent, but Python-independent wheels.
try:
from wheel.bdist_wheel import bdist_wheel
except ImportError:
cmdclass = {}
else:
class bdist_wheel_tag_name(bdist_wheel):
def get_tag(self):
abi = 'none'
if system == 'Darwin':
oses = 'macosx_10_6_x86_64'
elif system == 'Windows' and architecture == '32bit':
oses = 'win32'
elif system == 'Windows' and architecture == '64bit':
oses = 'win_amd64'
elif system == 'Linux' and architecture == '64bit':
oses = 'linux_x86_64'
elif system == 'Linux':
oses = 'linux_' + architecture
else:
raise TypeError("Unknown build environment")
return 'py3', abi, oses
cmdclass = {'bdist_wheel': bdist_wheel_tag_name}
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 == "1":
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', 'language_model.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",
version="0.3.15",
version="0.3.21",
author="Alpha Cephei Inc",
author_email="contact@alphacephei.com",
description="Offline open source speech recognition API based on Kaldi and Vosk",
@@ -81,8 +52,8 @@ setuptools.setup(
long_description_content_type="text/markdown",
url="https://github.com/alphacep/vosk-api",
packages=setuptools.find_packages(),
ext_modules=[vosk_ext],
cmdclass = {'build_py' : build_py},
package_data = {'vosk': ['*.so', '*.dll', '*.dyld']},
include_package_data=True,
classifiers=[
'Programming Language :: Python :: 3',
'License :: OSI Approved :: Apache Software License',
@@ -91,5 +62,10 @@ setuptools.setup(
'Operating System :: MacOS :: MacOS X',
'Topic :: Software Development :: Libraries :: Python Modules'
],
python_requires='>=3.5',
cmdclass=cmdclass,
python_requires='>=3',
zip_safe=False, # Since we load so file from the filesystem, we can not run from zip file
setup_requires=['cffi>=1.0'],
install_requires=['cffi>=1.0'],
cffi_modules=['vosk_builder.py:ffibuilder'],
)
+70 -1
View File
@@ -1,2 +1,71 @@
from .vosk import KaldiRecognizer, Model, SpkModel, SetLogLevel
import os
import sys
from .vosk_cffi import ffi as _ffi
def open_dll():
dlldir = os.path.abspath(os.path.dirname(__file__))
if sys.platform == 'win32':
# We want to load dependencies too
os.environ["PATH"] = dlldir + os.pathsep + os.environ['PATH']
if hasattr(os, 'add_dll_directory'):
os.add_dll_directory(dlldir)
return _ffi.dlopen("libvosk.dll")
elif sys.platform == 'linux':
return _ffi.dlopen(os.path.join(dlldir, "libvosk.so"))
elif sys.platform == 'darwin':
return _ffi.dlopen(os.path.join(dlldir, "libvosk.dyld"))
else:
raise TypeError("Unsupported platform")
_c = open_dll()
class Model(object):
def __init__(self, model_path):
self._handle = _c.vosk_model_new(model_path.encode('utf-8'))
def __del__(self):
_c.vosk_model_free(self._handle)
def vosk_model_find_word(self, word):
return _c.vosk_model_find_word(self._handle, word.encode('utf-8'))
class SpkModel(object):
def __init__(self, model_path):
self._handle = _c.vosk_spk_model_new(model_path.encode('utf-8'))
def __del__(self):
_c.vosk_spk_model_free(self._handle)
class KaldiRecognizer(object):
def __init__(self, *args):
if len(args) == 2:
self._handle = _c.vosk_recognizer_new(args[0]._handle, args[1])
elif len(args) == 3 and type(args[1]) is SpkModel:
self._handle = _c.vosk_recognizer_new_spk(args[0]._handle, args[1]._handle, args[2])
elif len(args) == 3 and type(args[2]) is str:
self._handle = _c.vosk_recognizer_new_grm(args[0]._handle, args[1], args[2].encode('utf-8'))
else:
raise TypeError("Unknown arguments")
def __del__(self):
_c.vosk_recognizer_free(self._handle)
def AcceptWaveform(self, data):
return _c.vosk_recognizer_accept_waveform(self._handle, data, len(data))
def Result(self):
return _ffi.string(_c.vosk_recognizer_result(self._handle)).decode('utf-8')
def PartialResult(self):
return _ffi.string(_c.vosk_recognizer_partial_result(self._handle)).decode('utf-8')
def FinalResult(self):
return _ffi.string(_c.vosk_recognizer_final_result(self._handle)).decode('utf-8')
def SetLogLevel(level):
return _c.vosk_set_log_level(level)
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env python3
import os
from cffi import FFI
vosk_root=os.environ.get("VOSK_SOURCE", "..")
cpp_command = "cpp " + vosk_root + "/src/vosk_api.h"
ffibuilder = FFI()
ffibuilder.set_source("vosk.vosk_cffi", None)
ffibuilder.cdef(os.popen(cpp_command).read())
if __name__ == '__main__':
ffibuilder.compile(verbose=True)
+47
View File
@@ -0,0 +1,47 @@
KALDI_ROOT?=$(HOME)/travis/kaldi
OPENFST_ROOT?=$(KALDI_ROOT)/tools/openfst
OPENBLAS_ROOT?=$(KALDI_ROOT)/tools/OpenBLAS/install
EXT?=so
CXX?=g++
VOSK_SOURCES= \
kaldi_recognizer.cc \
language_model.cc \
model.cc \
spk_model.cc \
vosk_api.cc
CFLAGS=-g -O2 -std=c++17 -fPIC -DFST_NO_DYNAMIC_LINKING -I. -I$(KALDI_ROOT)/src -I$(OPENFST_ROOT)/include -I$(OPENBLAS_ROOT)/include
LIBS= \
$(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 \
$(OPENBLAS_ROOT)/lib/libopenblas.a \
$(OPENBLAS_ROOT)/lib/liblapack.a \
$(OPENBLAS_ROOT)/lib/libblas.a \
$(OPENBLAS_ROOT)/lib/libf2c.a \
$(OPENFST_ROOT)/lib/libfst.a \
$(OPENFST_ROOT)/lib/libfstngram.a
all: libvosk.$(EXT)
libvosk.$(EXT): $(VOSK_SOURCES:.cc=.o)
$(CXX) --shared -s -o $@ $^ $(LIBS) -lm -latomic
%.o: %.cc
$(CXX) $(CFLAGS) -c -o $@ $<
clean:
rm -f *.o *.so *.dll
+27 -27
View File
@@ -44,7 +44,7 @@ namespace {
case '\t': output += "\\t"; break;
default : output += str[i]; break;
}
return std::move( output );
return output;
}
}
@@ -291,10 +291,10 @@ class JSON
/// Functions for getting primitives from the JSON object.
bool IsNull() const { return Type == Class::Null; }
string ToString() const { bool b; return std::move( ToString( b ) ); }
string ToString() const { bool b; return ToString(b); }
string ToString( bool &ok ) const {
ok = (Type == Class::String);
return ok ? std::move( json_escape( *Internal.String ) ): string("");
return ok ? json_escape( *Internal.String ) : string("");
}
double ToFloat() const { bool b; return ToFloat( b ); }
@@ -425,18 +425,18 @@ class JSON
};
JSON Array() {
return std::move( JSON::Make( JSON::Class::Array ) );
return JSON::Make( JSON::Class::Array );
}
template <typename... T>
JSON Array( T... args ) {
JSON arr = JSON::Make( JSON::Class::Array );
arr.append( args... );
return std::move( arr );
return arr;
}
JSON Object() {
return std::move( JSON::Make( JSON::Class::Object ) );
return JSON::Make( JSON::Class::Object );
}
std::ostream& operator<<( std::ostream &os, const JSON &json ) {
@@ -457,7 +457,7 @@ namespace {
++offset;
consume_ws( str, offset );
if( str[offset] == '}' ) {
++offset; return std::move( Object );
++offset; return Object;
}
while( true ) {
@@ -484,7 +484,7 @@ namespace {
}
}
return std::move( Object );
return Object;
}
JSON parse_array( const string &str, size_t &offset ) {
@@ -494,7 +494,7 @@ namespace {
++offset;
consume_ws( str, offset );
if( str[offset] == ']' ) {
++offset; return std::move( Array );
++offset; return Array;
}
while( true ) {
@@ -509,11 +509,11 @@ namespace {
}
else {
std::cerr << "ERROR: Array: Expected ',' or ']', found '" << str[offset] << "'\n";
return std::move( JSON::Make( JSON::Class::Array ) );
return JSON::Make( JSON::Class::Array );
}
}
return std::move( Array );
return Array;
}
JSON parse_string( const string &str, size_t &offset ) {
@@ -538,7 +538,7 @@ namespace {
val += c;
else {
std::cerr << "ERROR: String: Expected hex character in unicode escape, found '" << c << "'\n";
return std::move( JSON::Make( JSON::Class::String ) );
return JSON::Make( JSON::Class::String );
}
}
offset += 4;
@@ -551,7 +551,7 @@ namespace {
}
++offset;
String = val;
return std::move( String );
return String;
}
JSON parse_number( const string &str, size_t &offset ) {
@@ -580,7 +580,7 @@ namespace {
exp_str += c;
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
std::cerr << "ERROR: Number: Expected a number for exponent, found '" << c << "'\n";
return std::move( JSON::Make( JSON::Class::Null ) );
return JSON::Make( JSON::Class::Null );
}
else
break;
@@ -589,7 +589,7 @@ namespace {
}
else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) {
std::cerr << "ERROR: Number: unexpected character '" << c << "'\n";
return std::move( JSON::Make( JSON::Class::Null ) );
return JSON::Make( JSON::Class::Null );
}
--offset;
@@ -601,7 +601,7 @@ namespace {
else
Number = std::stol( val );
}
return std::move( Number );
return Number;
}
JSON parse_bool( const string &str, size_t &offset ) {
@@ -612,20 +612,20 @@ namespace {
Bool = false;
else {
std::cerr << "ERROR: Bool: Expected 'true' or 'false', found '" << str.substr( offset, 5 ) << "'\n";
return std::move( JSON::Make( JSON::Class::Null ) );
return JSON::Make( JSON::Class::Null );
}
offset += (Bool.ToBool() ? 4 : 5);
return std::move( Bool );
return Bool;
}
JSON parse_null( const string &str, size_t &offset ) {
JSON Null;
if( str.substr( offset, 4 ) != "null" ) {
std::cerr << "ERROR: Null: Expected 'null', found '" << str.substr( offset, 4 ) << "'\n";
return std::move( JSON::Make( JSON::Class::Null ) );
return JSON::Make( JSON::Class::Null );
}
offset += 4;
return std::move( Null );
return Null;
}
JSON parse_next( const string &str, size_t &offset ) {
@@ -633,14 +633,14 @@ namespace {
consume_ws( str, offset );
value = str[offset];
switch( value ) {
case '[' : return std::move( parse_array( str, offset ) );
case '{' : return std::move( parse_object( str, offset ) );
case '\"': return std::move( parse_string( str, offset ) );
case '[' : return parse_array( str, offset );
case '{' : return parse_object( str, offset );
case '\"': return parse_string( str, offset );
case 't' :
case 'f' : return std::move( parse_bool( str, offset ) );
case 'n' : return std::move( parse_null( str, offset ) );
case 'f' : return parse_bool( str, offset );
case 'n' : return parse_null( str, offset );
default : if( ( value <= '9' && value >= '0' ) || value == '-' )
return std::move( parse_number( str, offset ) );
return parse_number( str, offset );
}
std::cerr << "ERROR: Parse: Unknown starting character '" << value << "'\n";
return JSON();
@@ -649,7 +649,7 @@ namespace {
JSON JSON::Load( const string &str ) {
size_t offset = 0;
return std::move( parse_next( str, offset ) );
return parse_next( str, offset );
}
} // End Namespace json
+2 -2
View File
@@ -173,9 +173,9 @@ void KaldiRecognizer::InitRescoring()
{
if (model_->std_lm_fst_) {
fst::CacheOptions cache_opts(true, 50000);
fst::MapFstOptions mapfst_opts(cache_opts);
fst::ArcMapFstOptions 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);
lm_fst_ = new fst::ArcMapFst<fst::StdArc, kaldi::LatticeArc, fst::StdToLatticeMapper<kaldi::BaseFloat> >(*model_->std_lm_fst_, mapper, mapfst_opts);
} else {
lm_fst_ = NULL;
}
+1 -1
View File
@@ -72,7 +72,7 @@ class KaldiRecognizer {
SpkModel *spk_model_;
OnlineBaseFeature *spk_feature_;
fst::MapFst<fst::StdArc, kaldi::LatticeArc, fst::StdToLatticeMapper<kaldi::BaseFloat> > *lm_fst_;
fst::ArcMapFst<fst::StdArc, kaldi::LatticeArc, fst::StdToLatticeMapper<kaldi::BaseFloat> > *lm_fst_;
float sample_frequency_;
int32 frame_offset_;
+17
View File
@@ -161,6 +161,7 @@ void Model::ConfigureV1()
std_fst_rxfilename_ = model_path_str_ + "/rescore/G.fst";
final_ie_rxfilename_ = model_path_str_ + "/ivector/final.ie";
mfcc_conf_rxfilename_ = model_path_str_ + "/mfcc.conf";
global_cmvn_stats_rxfilename_ = model_path_str_ + "/global_cmvn.stats";
}
void Model::ConfigureV2()
@@ -183,6 +184,7 @@ void Model::ConfigureV2()
std_fst_rxfilename_ = model_path_str_ + "/rescore/G.fst";
final_ie_rxfilename_ = model_path_str_ + "/ivector/final.ie";
mfcc_conf_rxfilename_ = model_path_str_ + "/conf/mfcc.conf";
global_cmvn_stats_rxfilename_ = model_path_str_ + "/am/global_cmvn.stats";
}
void Model::ReadDataFiles()
@@ -233,6 +235,13 @@ void Model::ReadDataFiles()
feature_info_.use_ivectors = false;
}
if (stat(global_cmvn_stats_rxfilename_.c_str(), &buffer) == 0) {
KALDI_LOG << "Reading CMVN stats from " << global_cmvn_stats_rxfilename_;
feature_info_.use_cmvn = true;
ReadKaldiObject(global_cmvn_stats_rxfilename_, &feature_info_.global_cmvn_stats);
}
if (stat(hclg_fst_rxfilename_.c_str(), &buffer) == 0) {
KALDI_LOG << "Loading HCLG from " << hclg_fst_rxfilename_;
hclg_fst_ = fst::ReadFstKaldiGeneric(hclg_fst_rxfilename_);
@@ -295,6 +304,14 @@ void Model::Unref()
}
}
int Model::FindWord(const char *word)
{
if (!word_syms_)
return -1;
return word_syms_->Find(word);
}
Model::~Model() {
delete decodable_info_;
delete trans_model_;
+2
View File
@@ -42,6 +42,7 @@ public:
Model(const char *model_path);
void Ref();
void Unref();
int FindWord(const char *word);
protected:
~Model();
@@ -63,6 +64,7 @@ protected:
string std_fst_rxfilename_;
string final_ie_rxfilename_;
string mfcc_conf_rxfilename_;
string global_cmvn_stats_rxfilename_;
kaldi::OnlineEndpointConfig endpoint_config_;
kaldi::LatticeFasterDecoderConfig nnet3_decoding_config_;
+3
View File
@@ -75,6 +75,9 @@ typedef struct {} KaldiRecognizer;
~Model() {
vosk_model_free($self);
}
int vosk_model_find_word(const char* word) {
return vosk_model_find_word($self, word);
}
}
%extend SpkModel {
+5
View File
@@ -31,6 +31,11 @@ void vosk_model_free(VoskModel *model)
((Model *)model)->Unref();
}
int vosk_model_find_word(VoskModel *model, const char *word)
{
return (int) ((Model *)model)->FindWord(word);
}
VoskSpkModel *vosk_spk_model_new(const char *model_path)
{
return (VoskSpkModel *)new SpkModel(model_path);
+8
View File
@@ -55,6 +55,14 @@ VoskModel *vosk_model_new(const char *model_path);
void vosk_model_free(VoskModel *model);
/** Check if a word can be recognized by the model
* @param word: the word
* @returns the word symbol if @param word exists inside the model
* or -1 otherwise.
* Reminding that word symbol 0 is for <epsilon> */
int vosk_model_find_word(VoskModel *model, const char *word);
/** Loads speaker model data from the file and returns the model object
*
* @param model_path: the path of the model on the filesystem
+18 -76
View File
@@ -1,5 +1,5 @@
ARG DOCKCROSS_IMAGE=linux-armv7
FROM dockcross/${DOCKCROSS_IMAGE}
ARG DOCKCROSS_IMAGE=alphacep/dockcross-linux-armv7
FROM ${DOCKCROSS_IMAGE}
LABEL description="A docker image for building portable Python linux binary wheels and Kaldi on other architectures"
LABEL maintainer="contact@alphacephei.com"
@@ -13,92 +13,34 @@ RUN apt-get update && \
automake \
autoconf \
libtool \
cmake \
python3 \
python3-pip \
python3-wheel \
python3-setuptools \
python3-cffi \
&& rm -rf /var/lib/apt/lists/*
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 \
&& cd swig-4.0.1 \
&& CPP=/usr/bin/cpp CXX=/usr/bin/g++ CC=/usr/bin/gcc ./configure --prefix=/usr && make -j 10 && make install \
&& cd .. \
&& rm -rf swig-4.0.1.tar.gz swig-4.0.1
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 \
&& cd openssl-OpenSSL_1_0_2u \
&& CROSS_COMPILE= MACHINE="$(echo $CROSS_TRIPLE|cut -d - -f 1)" ./config --prefix=$CROSS_ROOT shared \
&& make -j $(nproc) \
&& make install \
&& rm -rf /opt/openssl-OpenSSL_1_0_2u /opt/OpenSSL_1_0_2u.tar.gz
RUN cd /opt \
&& wget -q https://github.com/python/cpython/archive/v3.7.6.tar.gz \
&& tar xf v3.7.6.tar.gz \
&& cp -r cpython-3.7.6 cpython-3.7.6-cross \
&& cd /opt/cpython-3.7.6 \
&& 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.7-cp3.7m" \
&& make -j $(nproc) \
&& make install \
&& /opt/python/cp3.7-cp3.7m/bin/pip3 install -U pip \
&& /opt/python/cp3.7-cp3.7m/bin/pip3 install -U wheel \
&& cd /opt/cpython-3.7.6-cross \
&& export PATH=/opt/python/cp3.7-cp3.7m/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.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 \
&& git clone -b lookahead-1.8.0 --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 -b old-gcc --single-branch https://github.com/alphacep/openfst openfst \
&& git clone -b v0.3.13 --single-branch https://github.com/xianyi/OpenBLAS \
&& git clone -b v3.2.1 --single-branch https://github.com/alphacep/clapack \
&& make -C OpenBLAS ONLY_CBLAS=1 TARGET="${OPENBLAS_ARCH}" HOSTCC=gcc USE_LOCKING=1 USE_THREAD=0 all \
&& make -C OpenBLAS PREFIX=$(pwd)/OpenBLAS/install install \
&& mkdir -p clapack/BUILD && cd clapack/BUILD && cmake .. && make -j 10 && find . -name "*.a" | xargs cp -t ../../OpenBLAS/install/lib \
&& cd /opt/kaldi/tools \
&& git clone --single-branch 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 \
&& CFLAGS="-g -O3" ./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 \
&& ./configure --mathlib=OPENBLAS_CLAPACK --shared --use-cuda=no \
&& make -j 10 online2 lm \
&& find /opt/kaldi -name "*.o" -exec rm {} \;
+16 -19
View File
@@ -4,33 +4,30 @@ LABEL description="A docker image for building portable Python linux binary whee
LABEL maintainer="contact@alphacephei.com"
RUN yum -y update && yum -y install \
wget \
openssl-devel \
pcre-devel \
devtoolset-8-libatomic-devel \
automake \
autoconf \
libtool \
cmake \
&& yum clean all
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 \
&& cd swig-4.0.1 \
&& ./configure --prefix=/usr && make -j 10 && make install \
&& cd .. \
&& rm -rf swig-4.0.1.tar.gz swig-4.0.1
RUN cd /opt \
&& git clone -b lookahead --single-branch https://github.com/alphacep/kaldi \
&& cd kaldi/tools \
&& git clone -b v0.3.7 --single-branch https://github.com/xianyi/OpenBLAS \
&& make PREFIX=$(pwd)/OpenBLAS/install DYNAMIC_ARCH=1 USE_LOCKING=1 USE_THREAD=0 -C OpenBLAS all install \
&& git clone https://github.com/alphacep/openfst openfst \
&& git clone -b lookahead-1.8.0 --single-branch https://github.com/alphacep/kaldi \
&& cd /opt/kaldi/tools \
&& git clone -b v0.3.13 --single-branch https://github.com/xianyi/OpenBLAS \
&& git clone -b v3.2.1 --single-branch https://github.com/alphacep/clapack \
&& make -C OpenBLAS ONLY_CBLAS=1 DYNAMIC_ARCH=1 TARGET=NEHALEM USE_LOCKING=1 USE_THREAD=0 all \
&& make -C OpenBLAS PREFIX=$(pwd)/OpenBLAS/install install \
&& mkdir -p clapack/BUILD && cd clapack/BUILD && cmake .. && make -j 10 && find . -name "*.a" | xargs cp -t ../../OpenBLAS/install/lib \
&& cd /opt/kaldi/tools \
&& git clone --single-branch 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 \
&& CFLAGS="-g -O3" ./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 rnnlm \
&& ./configure --mathlib=OPENBLAS_CLAPACK --shared --use-cuda=no \
&& sed -i 's:-msse -msse2:-msse -msse2:g' kaldi.mk \
&& sed -i 's: -O1 : -O3 :g' kaldi.mk \
&& make -j $(nproc) online2 lm rnnlm \
&& find /opt/kaldi -name "*.o" -exec rm {} \;
+65
View File
@@ -0,0 +1,65 @@
FROM debian:10.4
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
g++ \
bzip2 \
unzip \
make \
wget \
git \
python3 \
python3-pip \
python3-wheel \
python3-setuptools \
python3-cffi \
zlib1g-dev \
patch \
cmake \
xz-utils \
automake \
autoconf \
libtool \
pkg-config \
sudo \
g++-mingw-w64-i686 \
g++-mingw-w64-x86-64 \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir /opt/kaldi \
&& git clone https://github.com/alphacep/openfst \
&& cd openfst \
&& autoreconf -i \
&& CXX=x86_64-w64-mingw32-g++-posix CXXFLAGS="-O3 -ftree-vectorize -DFST_NO_DYNAMIC_LINKING" \
./configure --prefix=/opt/kaldi/local \
--enable-shared --enable-static --with-pic --disable-bin \
--enable-lookahead-fsts --enable-ngram-fsts --host=x86_64-w64-mingw32 \
&& make -j $(nproc) \
&& make install
RUN cd /opt/kaldi \
&& git clone -b v0.3.13 --single-branch https://github.com/xianyi/OpenBLAS \
&& cd OpenBLAS \
&& make HOSTCC=gcc BINARY=64 CC=x86_64-w64-mingw32-gcc ONLY_CBLAS=1 DYNAMIC_ARCH=1 TARGET=NEHALEM USE_LOCKING=1 USE_THREAD=0 -j $(nproc) \
&& make PREFIX=/opt/kaldi/local install
RUN cd /opt/kaldi \
&& git clone -b v3.2.1 --single-branch https://github.com/alphacep/clapack \
&& mkdir clapack/BUILD \
&& cd clapack/BUILD \
&& cmake -DCMAKE_C_COMPILER_TARGET=x86_64-w64-mingw32 -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc-posix -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_CROSSCOMPILING=True .. \
&& make -C F2CLIBS/libf2c \
&& make -C BLAS \
&& make -C SRC \
&& find . -name *.a -exec cp {} /opt/kaldi/local/lib \;
RUN cd /opt/kaldi \
&& git clone -b android-mix --single-branch https://github.com/alphacep/kaldi \
&& cd kaldi/src \
&& CXX=x86_64-w64-mingw32-g++-posix CXXFLAGS="-O3 -ftree-vectorize -DFST_NO_DYNAMIC_LINKING" ./configure --shared --mingw=yes --use-cuda=no \
--mathlib=OPENBLAS_CLAPACK \
--host=x86_64-w64-mingw32 --openblas-clapack-root=/opt/kaldi/local \
--fst-root=/opt/kaldi/local --fst-version=1.8.0 \
&& make depend -j \
&& make -j $(nproc) online2 lm
+64
View File
@@ -0,0 +1,64 @@
FROM debian:10.4
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
g++ \
bzip2 \
unzip \
make \
wget \
git \
python3 \
python3-pip \
python3-wheel \
python3-setuptools \
python3-cffi \
zlib1g-dev \
patch \
cmake \
automake \
autoconf \
libtool \
pkg-config \
sudo \
g++-mingw-w64-i686 \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir /opt/kaldi \
&& git clone https://github.com/alphacep/openfst \
&& cd openfst \
&& autoreconf -i \
&& CXX=i686-w64-mingw32-g++-posix CXXFLAGS="-msse2 -O3 -ftree-vectorize -DFST_NO_DYNAMIC_LINKING" \
./configure --prefix=/opt/kaldi/local \
--enable-shared --enable-static --with-pic \
--disable-bin --enable-lookahead-fsts --enable-ngram-fsts \
--host=i686-w64-mingw32 \
&& make -j $(nproc) \
&& make install
RUN cd /opt/kaldi \
&& git clone -b v0.3.13 --single-branch https://github.com/xianyi/OpenBLAS \
&& cd OpenBLAS \
&& make HOSTCC=gcc BINARY=32 CC=i686-w64-mingw32-gcc ONLY_CBLAS=1 DYNAMIC_ARCH=1 TARGET=NEHALEM USE_LOCKING=1 USE_THREAD=0 -j $(nproc) \
&& make PREFIX=/opt/kaldi/local install
RUN cd /opt/kaldi \
&& git clone -b v3.2.1 --single-branch https://github.com/alphacep/clapack \
&& mkdir clapack/BUILD \
&& cd clapack/BUILD \
&& cmake -DCMAKE_C_COMPILER_TARGET=i686-w64-mingw32 -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc-posix -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_CROSSCOMPILING=True .. \
&& make -C F2CLIBS/libf2c \
&& make -C BLAS \
&& make -C SRC \
&& find . -name *.a -exec cp {} /opt/kaldi/local/lib \;
RUN cd /opt/kaldi \
&& git clone -b android-mix --single-branch https://github.com/alphacep/kaldi \
&& cd kaldi/src \
&& CXX=i686-w64-mingw32-g++-posix CXXFLAGS="-O3 -ftree-vectorize -DFST_NO_DYNAMIC_LINKING" ./configure --shared --mingw=yes --use-cuda=no \
--mathlib=OPENBLAS_CLAPACK \
--host=i686-w64-mingw32 --openblas-clapack-root=/opt/kaldi/local \
--fst-root=/opt/kaldi/local --fst-version=1.8.0 \
&& make depend -j \
&& make -j $(nproc) online2 lm
+2 -4
View File
@@ -3,10 +3,8 @@
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" --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 build --build-arg="DOCKCROSS_IMAGE=alphacep/dockcross-linux-armv7" --build-arg="OPENBLAS_ARCH=ARMV7" --file Dockerfile.dockcross --tag alphacep/kaldi-dockcross-armv7:latest .
docker build --build-arg="DOCKCROSS_IMAGE=dockcross/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
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
set -e -x
docker build --file Dockerfile.win --tag alphacep/kaldi-win:latest .
docker run --rm -v `realpath ..`:/io alphacep/kaldi-win /io/travis/build-wheels-win.sh
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
set -e -x
docker build --file Dockerfile.win32 --tag alphacep/kaldi-win32:latest .
docker run --rm -v `realpath ..`:/io alphacep/kaldi-win32 /io/travis/build-wheels-win32.sh
+2 -4
View File
@@ -1,7 +1,5 @@
#!/bin/bash
set -e
set -x
set -e -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
docker run --rm -v `realpath ..`:/io alphacep/kaldi-manylinux /io/travis/build-wheels.sh
+20 -31
View File
@@ -1,37 +1,26 @@
#!/bin/bash
set -e -x
ORIG_PATH=$PATH
for pyver in 3.6 3.7 3.8; do
# Build so file
cd /opt
git clone https://github.com/alphacep/vosk-api
cd /opt/vosk-api/src
KALDI_ROOT=/opt/kaldi make -j $(nproc)
export KALDI_ROOT=/opt/kaldi
export PATH=/opt/python/cp${pyver}-cp${pyver}m/bin:$ORIG_PATH
export VOSK_SOURCE=/io/src
# Decide architecture name
export VOSK_SOURCE=/opt/vosk-api
case $CROSS_TRIPLE in
*armv7-*)
export VOSK_ARCHITECTURE=armv7l
;;
*aarch64-*)
export VOSK_ARCHITECTURE=aarch64
;;
esac
# Python 3.8 somehow changed syconfig file name
sysconfig_bit="m"
if [ $pyver == "3.8" ]; then
sysconfig_bit=""
fi
# Copy library to output folder
mkdir -p /io/wheelhouse/linux-$VOSK_ARCHITECTURE
cp /opt/vosk-api/src/*.so /io/wheelhouse/linux-$VOSK_ARCHITECTURE
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
# Build wheel
pip3 wheel /opt/vosk-api/python --no-deps -w /io/wheelhouse
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
set -e -x
# Build libvosk
cd /opt
git clone https://github.com/alphacep/vosk-api
cd vosk-api/src
CXX=x86_64-w64-mingw32-g++-posix EXT=dll KALDI_ROOT=/opt/kaldi/kaldi OPENFST_ROOT=/opt/kaldi/local OPENBLAS_ROOT=/opt/kaldi/local make -j $(nproc)
# Collect dependencies
cp /usr/lib/gcc/x86_64-w64-mingw32/*-posix/libstdc++-6.dll /opt/vosk-api/src
cp /usr/lib/gcc/x86_64-w64-mingw32/*-posix/libgcc_s_seh-1.dll /opt/vosk-api/src
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll /opt/vosk-api/src
# Copy dlls to output folder
mkdir -p /io/wheelhouse/win64
cp /opt/vosk-api/src/*.dll /io/wheelhouse/win64
# Build wheel and put to the output folder
export VOSK_SOURCE=/opt/vosk-api
export VOSK_PLATFORM=Windows
export VOSK_ARCHITECTURE=64bit
python3 -m pip -v wheel /opt/vosk-api/python --no-deps -w /io/wheelhouse
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
set -e -x
# Build libvosk
cd /opt
git clone https://github.com/alphacep/vosk-api
cd vosk-api/src
CXX=i686-w64-mingw32-g++-posix EXT=dll KALDI_ROOT=/opt/kaldi/kaldi OPENFST_ROOT=/opt/kaldi/local OPENBLAS_ROOT=/opt/kaldi/local make -j $(nproc)
# Copy dependencies
cp /usr/lib/gcc/i686-w64-mingw32/*-posix/libstdc++-6.dll /opt/vosk-api/src
cp /usr/lib/gcc/i686-w64-mingw32/*-posix/libgcc_s_sjlj-1.dll /opt/vosk-api/src
cp /usr/i686-w64-mingw32/lib/libwinpthread-1.dll /opt/vosk-api/src
# Copy dlls to output folder
mkdir -p /io/wheelhouse/win32
cp /opt/vosk-api/src/*.dll /io/wheelhouse/win32
# Build wheel and put to the output folder
export VOSK_SOURCE=/opt/vosk-api
export VOSK_PLATFORM=Windows
export VOSK_ARCHITECTURE=32bit
python3 -m pip -v wheel /opt/vosk-api/python --no-deps -w /io/wheelhouse
+16 -10
View File
@@ -1,17 +1,23 @@
#!/bin/bash
set -e -x
export KALDI_ROOT=/opt/kaldi
# Build libvosk
cd /opt
git clone https://github.com/alphacep/vosk-api
cd vosk-api/src
KALDI_ROOT=/opt/kaldi OPENFST_ROOT=/opt/kaldi/tools/openfst OPENBLAS_ROOT=/opt/kaldi/tools/OpenBLAS/install make -j $(nproc)
# Compile wheels
for pypath in /opt/python/cp3[56789]*; do
export VOSK_SOURCE=/io/src
mkdir -p /opt/wheelhouse
rm -rf /io/python/build
"${pypath}/bin/pip" -v wheel /io/python -w /opt/wheelhouse
done
# Copy dlls to output folder
mkdir -p /io/wheelhouse/linux
cp /opt/vosk-api/src/*.so /io/wheelhouse/linux
# Bundle external shared libraries into the wheels
# Build wheel and put to the output folder
mkdir -p /opt/wheelhouse
export VOSK_SOURCE=/opt/vosk-api
/opt/python/cp37*/bin/pip -v wheel /opt/vosk-api/python --no-deps -w /opt/wheelhouse
# Fix manylinux
for whl in /opt/wheelhouse/*.whl; do
auditwheel repair "$whl" --plat $PLAT -w /io/wheelhouse/
cp $whl /io/wheelhouse
auditwheel repair "$whl" --plat manylinux2010_x86_64 -w /io/wheelhouse
done