Nodejs Addon blocking main thread. Implemented Napi::AsyncWorker (#642)
* fixed blocking code on node addon * modify the example to run async * format * added logic to see the whisper output * added logic to see the whisper output * removed extra function for more clean example
This commit is contained in:
parent
1d749919e3
commit
21165580a1
@ -292,51 +292,64 @@ int run(whisper_params ¶ms, std::vector<std::vector<std::string>> &result) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Napi::Object whisper(const Napi::CallbackInfo& info) {
|
class Worker : public Napi::AsyncWorker {
|
||||||
Napi::Env env = info.Env();
|
public:
|
||||||
if (info.Length() <= 0 || !info[0].IsObject()) {
|
Worker(Napi::Function& callback, whisper_params params)
|
||||||
Napi::TypeError::New(env, "object expected").ThrowAsJavaScriptException();
|
: Napi::AsyncWorker(callback), params(params) {}
|
||||||
}
|
|
||||||
whisper_params params;
|
|
||||||
std::vector<std::vector<std::string>> result;
|
|
||||||
|
|
||||||
Napi::Object whisper_params = info[0].As<Napi::Object>();
|
void Execute() override {
|
||||||
std::string language = whisper_params.Get("language").As<Napi::String>();
|
|
||||||
std::string model = whisper_params.Get("model").As<Napi::String>();
|
|
||||||
std::string input = whisper_params.Get("fname_inp").As<Napi::String>();
|
|
||||||
|
|
||||||
params.language = language;
|
|
||||||
params.model = model;
|
|
||||||
params.fname_inp.emplace_back(input);
|
|
||||||
|
|
||||||
// run model
|
|
||||||
run(params, result);
|
run(params, result);
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, "RESULT:\n");
|
void OnOK() override {
|
||||||
for (auto sentence:result) {
|
Napi::HandleScope scope(Env());
|
||||||
fprintf(stderr, "t0: %s, t1: %s, content: %s \n",
|
Napi::Object res = Napi::Array::New(Env(), result.size());
|
||||||
sentence[0].c_str(), sentence[1].c_str(), sentence[2].c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Napi::Object res = Napi::Array::New(env, result.size());
|
|
||||||
for (uint64_t i = 0; i < result.size(); ++i) {
|
for (uint64_t i = 0; i < result.size(); ++i) {
|
||||||
Napi::Object tmp = Napi::Array::New(env, 3);
|
Napi::Object tmp = Napi::Array::New(Env(), 3);
|
||||||
for (uint64_t j = 0; j < 3; ++j) {
|
for (uint64_t j = 0; j < 3; ++j) {
|
||||||
tmp[j] = Napi::String::New(env, result[i][j]);
|
tmp[j] = Napi::String::New(Env(), result[i][j]);
|
||||||
}
|
}
|
||||||
res[i] = tmp;
|
res[i] = tmp;
|
||||||
}
|
}
|
||||||
|
Callback().Call({Env().Null(), res});
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
private:
|
||||||
|
whisper_params params;
|
||||||
|
std::vector<std::vector<std::string>> result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Napi::Value whisper(const Napi::CallbackInfo& info) {
|
||||||
|
Napi::Env env = info.Env();
|
||||||
|
if (info.Length() <= 0 || !info[0].IsObject()) {
|
||||||
|
Napi::TypeError::New(env, "object expected").ThrowAsJavaScriptException();
|
||||||
|
}
|
||||||
|
whisper_params params;
|
||||||
|
|
||||||
|
Napi::Object whisper_params = info[0].As<Napi::Object>();
|
||||||
|
std::string language = whisper_params.Get("language").As<Napi::String>();
|
||||||
|
std::string model = whisper_params.Get("model").As<Napi::String>();
|
||||||
|
std::string input = whisper_params.Get("fname_inp").As<Napi::String>();
|
||||||
|
|
||||||
|
params.language = language;
|
||||||
|
params.model = model;
|
||||||
|
params.fname_inp.emplace_back(input);
|
||||||
|
|
||||||
|
Napi::Function callback = info[1].As<Napi::Function>();
|
||||||
|
Worker* worker = new Worker(callback, params);
|
||||||
|
worker->Queue();
|
||||||
|
return env.Undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||||
exports.Set(
|
exports.Set(
|
||||||
Napi::String::New(env, "whisper"),
|
Napi::String::New(env, "whisper"),
|
||||||
Napi::Function::New(env, whisper)
|
Napi::Function::New(env, whisper)
|
||||||
);
|
);
|
||||||
return exports;
|
return exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_API_MODULE(whisper, Init);
|
NODE_API_MODULE(whisper, Init);
|
||||||
|
@ -1,27 +1,36 @@
|
|||||||
const path = require('path');
|
const path = require("path");
|
||||||
const { whisper } = require(path.join(__dirname, '../../build/Release/whisper-addon'));
|
const { whisper } = require(path.join(
|
||||||
|
__dirname,
|
||||||
|
"../../build/Release/whisper-addon"
|
||||||
|
));
|
||||||
|
const { promisify } = require("util");
|
||||||
|
|
||||||
|
const whisperAsync = promisify(whisper);
|
||||||
|
|
||||||
const whisperParams = {
|
const whisperParams = {
|
||||||
language: 'en',
|
language: "en",
|
||||||
model: path.join(__dirname, '../../models/ggml-base.en.bin'),
|
model: path.join(__dirname, "../../models/ggml-base.en.bin"),
|
||||||
fname_inp: '',
|
fname_inp: "../../samples/jfk.wav",
|
||||||
};
|
};
|
||||||
|
|
||||||
const arguments = process.argv.slice(2);
|
const arguments = process.argv.slice(2);
|
||||||
const params = Object.fromEntries(
|
const params = Object.fromEntries(
|
||||||
arguments.reduce((pre, item) => {
|
arguments.reduce((pre, item) => {
|
||||||
if (item.startsWith("--")) {
|
if (item.startsWith("--")) {
|
||||||
return [...pre, item.slice(2).split("=")];
|
return [...pre, item.slice(2).split("=")];
|
||||||
}
|
}
|
||||||
return pre;
|
return pre;
|
||||||
}, []),
|
}, [])
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const key in params) {
|
for (const key in params) {
|
||||||
if (whisperParams.hasOwnProperty(key)) {
|
if (whisperParams.hasOwnProperty(key)) {
|
||||||
whisperParams[key] = params[key];
|
whisperParams[key] = params[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('whisperParams =', whisperParams);
|
console.log("whisperParams =", whisperParams);
|
||||||
console.log(whisper(whisperParams));
|
|
||||||
|
whisperAsync(whisperParams).then((result) => {
|
||||||
|
console.log(`Result from whisper: ${result}`);
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user