Remove libarchive, implement untar manually. Use vosk-browser models
This commit is contained in:
@@ -1,49 +1,27 @@
|
||||
#include "genericModel.h"
|
||||
|
||||
genericModel::genericModel(int index, bool normalMdl, std::string storepath, std::string id) : normalMdl{normalMdl}, index{index}, storepath{std::move(storepath)}, id{std::move(id)}, entry{archive_entry_new()} {}
|
||||
genericModel::genericModel(int index, bool normalMdl, std::string storepath, std::string id) : normalMdl{normalMdl}, index{index}, storepath{std::move(storepath)}, id{std::move(id)} {}
|
||||
void genericModel::extractAndLoad(int tarStart, int tarSize) {
|
||||
static fs::path path{};
|
||||
static int fd{};
|
||||
void* tar{reinterpret_cast<void*>(tarStart)};
|
||||
func = [this, tar, tarSize](){
|
||||
archive* src {archive_read_new()};
|
||||
archive_read_support_format_tar(src);
|
||||
archive_read_open_memory(src, tar, tarSize);
|
||||
if(archive_errno(src) != 0) {
|
||||
free(tar);
|
||||
fireEv(index, "Unable to open tar in WASM memory");
|
||||
return;
|
||||
}
|
||||
while(1) {
|
||||
int headerRes {archive_read_next_header2(src, entry)};
|
||||
if(headerRes == ARCHIVE_EOF) break;
|
||||
if(headerRes < ARCHIVE_OK) {
|
||||
free(tar);
|
||||
fireEv(index, archive_error_string(src));
|
||||
return;
|
||||
}
|
||||
path = archive_entry_pathname(entry);
|
||||
path = storepath + path.string().substr(path.string().find("/"));
|
||||
if(!path.has_extension()) {
|
||||
fs::create_directory(path);
|
||||
continue;
|
||||
}
|
||||
fd = open(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0777);
|
||||
if(fd == -1) {
|
||||
free(tar);
|
||||
fireEv(index, "Unable to create model files");
|
||||
return;
|
||||
}
|
||||
archive_read_data_into_fd(src, fd);
|
||||
close(fd);
|
||||
if(archive_errno(src) != 0) {
|
||||
free(tar);
|
||||
fireEv(index, "Cannot write into model files");
|
||||
return;
|
||||
}
|
||||
}
|
||||
func = [this, tar = reinterpret_cast<unsigned char*>(tarStart), tarSize]() {
|
||||
int res{untar(tar, tarSize, storepath)};
|
||||
free(tar);
|
||||
archive_read_free(src);
|
||||
switch(res) {
|
||||
case 1:
|
||||
fireEv(index, "Untar: Incorrect tar format, must be USTAR");
|
||||
return;
|
||||
case 2:
|
||||
fireEv(index, "Untar: Not a directory or regular file");
|
||||
return;
|
||||
case 3:
|
||||
fireEv(index, "Untar: Unable to open file for write");
|
||||
return;
|
||||
case 4:
|
||||
fireEv(index, "Untar: Unable to write file");
|
||||
return;
|
||||
case 5:
|
||||
fireEv(index, "Untar: Unable to close file after write");
|
||||
return;
|
||||
};
|
||||
if(normalMdl) mdl = vosk_model_new(storepath.c_str());
|
||||
else mdl = vosk_spk_model_new(storepath.c_str());
|
||||
if(normalMdl ? std::get<VoskModel*>(mdl) != nullptr : std::get<VoskSpkModel*>(mdl) != nullptr) fireEv(index, "0");
|
||||
@@ -61,7 +39,6 @@ int genericModel::findWord(std::string word) {
|
||||
return vosk_model_find_word(std::get<VoskModel*>(mdl), word.c_str());
|
||||
}
|
||||
genericModel::~genericModel() {
|
||||
archive_entry_free(entry);
|
||||
if(normalMdl) vosk_model_free(std::get<VoskModel*>(mdl));
|
||||
else vosk_spk_model_free(std::get<VoskSpkModel*>(mdl));
|
||||
}
|
||||
@@ -1,15 +1,7 @@
|
||||
#pragma once
|
||||
#include "link.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <variant>
|
||||
#include <fcntl.h>
|
||||
#include "util.h"
|
||||
|
||||
#include <vosk_api.h>
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
extern void free(void*);
|
||||
struct genericModel {
|
||||
@@ -21,7 +13,6 @@ struct genericModel {
|
||||
std::string id;
|
||||
std::variant<VoskModel*, VoskSpkModel*> mdl;
|
||||
std::function<void()> func;
|
||||
archive_entry* entry;
|
||||
void extractAndLoad(int tarStart, int tarSize);
|
||||
int findWord(std::string word);
|
||||
genericModel(int index, bool normalMdl, std::string storepath, std::string id);
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "link.h"
|
||||
|
||||
void fireEv(int index, const char* content, const char* type) {
|
||||
MAIN_THREAD_EM_ASM({
|
||||
objs[$0].dispatchEvent(new CustomEvent($2 === 0 ? "0" : UTF8ToString($2), { "detail" : UTF8ToString($1) }));
|
||||
}, index, content, type);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
#include <thread>
|
||||
|
||||
#include <emscripten/em_asm.h>
|
||||
|
||||
void fireEv(int index, const char* content, const char* type = nullptr);
|
||||
18
src/make
18
src/make
@@ -28,25 +28,15 @@ if [ $EMSDK = ../emsdk ] && [ ! -d $EMSDK ]; then
|
||||
./emsdk activate 3.1.59
|
||||
fi
|
||||
. $(realpath $EMSDK)/emsdk_env.sh &&
|
||||
export PATH=:$PATH:$(realpath $EMSDK)/upstream/bin
|
||||
export PATH=:$PATH:$(realpath $EMSDK)/upstream/bin &&
|
||||
|
||||
cd ..
|
||||
cd .. &&
|
||||
SRC=$(realpath src)
|
||||
KALDI=$(realpath kaldi)
|
||||
VOSK=$(realpath vosk)
|
||||
OPENFST=$(realpath openfst)
|
||||
LIBARCHIVE=$(realpath libarchive)
|
||||
CLAPACK_WASM=$(realpath clapack-wasm)
|
||||
|
||||
if [ ! -d $LIBARCHIVE ]; then
|
||||
rm -rf /tmp/libarchive &&
|
||||
git clone -b v3.7.4 --depth=1 https://github.com/libarchive/libarchive /tmp/libarchive &&
|
||||
cd /tmp/libarchive &&
|
||||
build/autogen.sh &&
|
||||
CFLAGS="-O3 -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals" LDFLAGS="-O3 -flto" emconfigure ./configure --prefix=$LIBARCHIVE --without-lz4 --without-lzma --without-zlib --without-bz2lib --without-xml2 --without-expat --without-cng --without-openssl --without-libb2 --without-zstd --disable-bsdunzip --disable-xattr --disable-acl --disable-bsdcpio --disable-bsdcat --disable-rpath --disable-maintainer-mode --disable-dependency-tracking --enable-static --disable-shared &&
|
||||
emmake make -j$JOBS install
|
||||
fi
|
||||
|
||||
if [ ! -d $OPENFST ]; then
|
||||
rm -rf /tmp/openfst &&
|
||||
git clone --depth=1 https://github.com/alphacep/openfst /tmp/openfst &&
|
||||
@@ -82,13 +72,13 @@ if [ ! -d $VOSK ]; then
|
||||
fi
|
||||
|
||||
cd $SRC &&
|
||||
em++ link.cc genericModel.cc recognizer.cc bindings.cc -O3 -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L$OPENFST/lib -l:libfst.a -l:libfstngram.a -L$CLAPACK_WASM -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js wrapper.js -o ../Vosklet.js &&
|
||||
em++ util.cc genericModel.cc recognizer.cc bindings.cc -O3 -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$MAX_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -sENVIRONMENT=web,worker -I. -I"$VOSK"/src -L$KALDI/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L"$OPENFST"/lib -l:libfst.a -l:libfstngram.a -L"$CLAPACK_WASM" -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L$VOSK/src -l:vosk.a -lembind -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js wrapper.js -o ../Vosklet.js &&
|
||||
cd .. &&
|
||||
rm -f Vosklet.worker.js
|
||||
|
||||
cp Vosklet.js examples/Vosklet.js &&
|
||||
|
||||
# Can't serve files from raw.githubusercontent with Content-Encoding: gzip header so the browser won't decompress automatically. Change to manually decompressing instead.
|
||||
# Can't serve files from raw.githubusercontent with Content-Encoding: gzip header so the browser won't decompress automatically. Manually decompressing instead.
|
||||
sed -i 's/res.body/new Response(res.body.pipeThrough(new DecompressionStream("gzip"))).body/' examples/Vosklet.js &&
|
||||
|
||||
rm -rf /tmp/libarchive
|
||||
|
||||
47
src/util.cc
Normal file
47
src/util.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "util.h"
|
||||
|
||||
void fireEv(int index, const char* content, const char* type) {
|
||||
MAIN_THREAD_EM_ASM({
|
||||
objs[$0].dispatchEvent(new CustomEvent($2 === 0 ? "0" : UTF8ToString($2), { "detail" : UTF8ToString($1) }));
|
||||
}, index, content, type);
|
||||
}
|
||||
int untar(unsigned char* tar, int tarSize, const std::string& storepath) {
|
||||
if(memcmp(tar + 257, "ustar", 5)) return 1;
|
||||
unsigned char* ptr = tar;
|
||||
size_t size{0};
|
||||
std::string path{};
|
||||
path.reserve(100); // Max length
|
||||
unsigned char* end = tar + tarSize;
|
||||
while(ptr <= end) {
|
||||
if(ptr[156] != '5' && ptr[156] != 0 &&
|
||||
ptr[156] != '0') {
|
||||
return 2;
|
||||
}
|
||||
path.clear();
|
||||
path += reinterpret_cast<char*>(ptr + 345);
|
||||
path += reinterpret_cast<char*>(ptr);
|
||||
ptr += 124;
|
||||
for(int i{0}; i < 11; i++) {
|
||||
size *= 8;
|
||||
size += *ptr - 48;
|
||||
ptr++;
|
||||
}
|
||||
ptr += 377;
|
||||
size_t firstSlash = path.find_first_of("/");
|
||||
if(firstSlash == std::string::npos) {
|
||||
if(size != 0) ptr += size + 512 - size % 512;
|
||||
continue;
|
||||
}
|
||||
path = storepath + path.substr(firstSlash);
|
||||
if(size == 0) fs::create_directory(path);
|
||||
else {
|
||||
int fd {open(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0777)};
|
||||
if(fd == -1) return 3;
|
||||
int res = write(fd, ptr, size);
|
||||
if(res == -1) return 4;
|
||||
if(close(fd) == -1) return 5;
|
||||
ptr += size + 512 - size % 512;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
15
src/util.h
Normal file
15
src/util.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include <thread>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <variant>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <emscripten/em_asm.h>
|
||||
#include <emscripten/console.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
void fireEv(int index, const char* content, const char* type = nullptr);
|
||||
int untar(unsigned char* tar, int tarSize, const std::string& storepath);
|
||||
Reference in New Issue
Block a user