Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d917af21ab | |||
| 948c8c7cfd | |||
| dec8e1acf3 | |||
| 3c020526ce | |||
| b0da19b07f | |||
| 70bcd9b018 | |||
| d2604b609d | |||
| e960e0cacf | |||
| 77b114d434 | |||
| 2860092cef | |||
| c6119c4835 | |||
| 415d1927e0 | |||
| 3d1e21d242 | |||
| 7a75e1c3f4 | |||
| c3430e448a | |||
| ae49ea60d2 | |||
| 02dc0ce0c8 | |||
| 15697a18e8 | |||
| 481881e59d | |||
| 11a25b26a7 | |||
| bf87358f6c | |||
| 04a8242230 | |||
| ceb96c301c | |||
| 307df8fdc0 | |||
| c44875a2dd | |||
| 31f11990ca | |||
| b79b85856d | |||
| 6e861c6a19 | |||
| cf62296a51 | |||
| 387b132814 | |||
| de83de8624 | |||
| fe91b5a717 | |||
| a052506a5d | |||
| 6f2d6d0d69 | |||
| a8ae6025bd | |||
| 1b8332a609 | |||
| fe16ec7e57 | |||
| c5ce5e46bd | |||
| 99d66670bc | |||
| 072b42cac6 | |||
| acadb5b4c2 | |||
| 2e1de6c3af | |||
| 67de30908b | |||
| 9d398eff0e | |||
| 02b7312a00 | |||
| 08c35e84f3 | |||
| b92a5c1fc7 | |||
| 8997a587c5 | |||
| dc3d03d742 | |||
| 84df40715c | |||
| b639fb501a | |||
| 746ff47757 | |||
| 2d62db8118 | |||
| 7a2adcd9ba | |||
| 9ccf3ef0e8 | |||
| 0edab6d558 | |||
| 4b344f0cd8 | |||
| 17ddc4d5ba | |||
| 3e33860c47 |
+20
-16
@@ -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
@@ -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/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -14,7 +14,7 @@ plugins {
|
||||
}
|
||||
|
||||
def archiveName = "vosk-android"
|
||||
def libVersion = "0.3.15"
|
||||
def libVersion = "0.3.17"
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
include 'model-en'
|
||||
+7
-41
@@ -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
|
||||
|
||||
@@ -24,5 +24,6 @@ int main() {
|
||||
|
||||
vosk_recognizer_free(recognizer);
|
||||
vosk_model_free(model);
|
||||
fclose(wavin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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];
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
mcs -out:lib/netstandard2.0/Vosk.dll -target:library src/*.cs
|
||||
nuget pack
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Vosk {
|
||||
|
||||
public class Vosk {
|
||||
public static void SetLogLevel(int level) {
|
||||
VoskPINVOKE.SetLogLevel(level);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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!)!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -1,3 +1,3 @@
|
||||
build
|
||||
node_modules
|
||||
vosk_wrap.cc
|
||||
demo/model
|
||||
demo/model-spk
|
||||
demo/test.wav
|
||||
|
||||
+27
-14
@@ -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).
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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 {} \;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Executable
+5
@@ -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
|
||||
Executable
+5
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
+23
@@ -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
|
||||
Executable
+23
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user