npm : initial version ready

pull/260/head
Georgi Gerganov 3 years ago
parent fd9c9e9f8d
commit aa4dacb49a
No known key found for this signature in database
GPG Key ID: 449E073F9DC10735

@ -33,6 +33,7 @@ set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \
--bind \ --bind \
-s MODULARIZE=1 \ -s MODULARIZE=1 \
-s EXPORT_NAME=\"'whisper_factory'\" \ -s EXPORT_NAME=\"'whisper_factory'\" \
-s FORCE_FILESYSTEM=1 \
-s USE_PTHREADS=1 \ -s USE_PTHREADS=1 \
-s PTHREAD_POOL_SIZE=8 \ -s PTHREAD_POOL_SIZE=8 \
-s ALLOW_MEMORY_GROWTH=1 \ -s ALLOW_MEMORY_GROWTH=1 \

@ -2,12 +2,4 @@
Whisper speech recognition Whisper speech recognition
## Example Usage For sample usage check [tests/test-whisper.js](/tests/test-whisper.js)
```js
var factory = require('whisper')
factory().then(function(whisper) {
// TODO
});
```

@ -1,63 +1,48 @@
//
// This is the Javascript API of whisper.cpp
//
// Very crude at the moment.
// Feel free to contribute and make this better!
//
// See the tests/test-whisper.js for sample usage
//
#include "whisper.h" #include "whisper.h"
#include <emscripten.h> #include <emscripten.h>
#include <emscripten/bind.h> #include <emscripten/bind.h>
#include <vector>
#include <thread> #include <thread>
#include <vector>
std::thread g_worker; struct whisper_context * g_context;
std::vector<struct whisper_context *> g_contexts(4, nullptr);
EMSCRIPTEN_BINDINGS(whisper) { EMSCRIPTEN_BINDINGS(whisper) {
emscripten::function("init", emscripten::optional_override([](const std::string & path_model) { emscripten::function("init", emscripten::optional_override([](const std::string & path_model) {
if (g_worker.joinable()) { if (g_context == nullptr) {
g_worker.join(); g_context = whisper_init(path_model.c_str());
} if (g_context != nullptr) {
return true;
for (size_t i = 0; i < g_contexts.size(); ++i) {
if (g_contexts[i] == nullptr) {
g_contexts[i] = whisper_init(path_model.c_str());
if (g_contexts[i] != nullptr) {
return i + 1;
} else { } else {
return (size_t) 0; return false;
}
} }
} }
return (size_t) 0; return false;
})); }));
emscripten::function("free", emscripten::optional_override([](size_t index) { emscripten::function("free", emscripten::optional_override([]() {
if (g_worker.joinable()) { if (g_context) {
g_worker.join(); whisper_free(g_context);
} g_context = nullptr;
--index;
if (index < g_contexts.size()) {
whisper_free(g_contexts[index]);
g_contexts[index] = nullptr;
} }
})); }));
emscripten::function("full_default", emscripten::optional_override([](size_t index, const emscripten::val & audio, const std::string & lang, bool translate) { emscripten::function("full_default", emscripten::optional_override([](const emscripten::val & audio, const std::string & lang, bool translate) {
if (g_worker.joinable()) { if (g_context == nullptr) {
g_worker.join();
}
--index;
if (index >= g_contexts.size()) {
return -1; return -1;
} }
if (g_contexts[index] == nullptr) {
return -2;
}
struct whisper_full_params params = whisper_full_default_params(whisper_sampling_strategy::WHISPER_SAMPLING_GREEDY); struct whisper_full_params params = whisper_full_default_params(whisper_sampling_strategy::WHISPER_SAMPLING_GREEDY);
params.print_realtime = true; params.print_realtime = true;
@ -65,7 +50,7 @@ EMSCRIPTEN_BINDINGS(whisper) {
params.print_timestamps = true; params.print_timestamps = true;
params.print_special = false; params.print_special = false;
params.translate = translate; params.translate = translate;
params.language = whisper_is_multilingual(g_contexts[index]) ? lang.c_str() : "en"; params.language = whisper_is_multilingual(g_context) ? lang.c_str() : "en";
params.n_threads = std::min(8, (int) std::thread::hardware_concurrency()); params.n_threads = std::min(8, (int) std::thread::hardware_concurrency());
params.offset_ms = 0; params.offset_ms = 0;
@ -82,9 +67,11 @@ EMSCRIPTEN_BINDINGS(whisper) {
// print system information // print system information
{ {
printf("\n");
printf("system_info: n_threads = %d / %d | %s\n", printf("system_info: n_threads = %d / %d | %s\n",
params.n_threads, std::thread::hardware_concurrency(), whisper_print_system_info()); params.n_threads, std::thread::hardware_concurrency(), whisper_print_system_info());
printf("\n");
printf("%s: processing %d samples, %.1f sec, %d threads, %d processors, lang = %s, task = %s ...\n", printf("%s: processing %d samples, %.1f sec, %d threads, %d processors, lang = %s, task = %s ...\n",
__func__, int(pcmf32.size()), float(pcmf32.size())/WHISPER_SAMPLE_RATE, __func__, int(pcmf32.size()), float(pcmf32.size())/WHISPER_SAMPLE_RATE,
params.n_threads, 1, params.n_threads, 1,
@ -94,13 +81,11 @@ EMSCRIPTEN_BINDINGS(whisper) {
printf("\n"); printf("\n");
} }
// run the worker // run whisper
{ {
g_worker = std::thread([index, params, pcmf32 = std::move(pcmf32)]() { whisper_reset_timings(g_context);
whisper_reset_timings(g_contexts[index]); whisper_full(g_context, params, pcmf32.data(), pcmf32.size());
whisper_full(g_contexts[index], params, pcmf32.data(), pcmf32.size()); whisper_print_timings(g_context);
whisper_print_timings(g_contexts[index]);
});
} }
return 0; return 0;

File diff suppressed because one or more lines are too long

@ -1,5 +1,58 @@
var factory = require('../bindings/javascript/whisper.js') var factory = require('../bindings/javascript/whisper.js')
factory().then(function(whisper) { factory().then(function(whisper) {
// TODO var fs = require('fs');
// to avoid reading WAV files and depending on some 3rd-party package, we read
// 32-bit float PCM directly. to genereate it:
//
// $ ffmpeg -i samples/jfk.wav -f f32le -acodec pcm_f32le samples/jfk.pcmf32
//
let fname_wav = "../samples/jfk.pcmf32";
let fname_model = "../models/ggml-base.en.bin";
// init whisper
{
// read binary data from file
var model_data = fs.readFileSync(fname_model);
if (model_data == null) {
console.log("whisper: failed to read model file");
process.exit(1);
}
// write binary data to WASM memory
whisper.FS_createDataFile("/", "whisper.bin", model_data, true, true);
// init the model
var ret = whisper.init("whisper.bin");
if (ret == false) {
console.log('whisper: failed to init');
process.exit(1);
}
}
// transcribe wav file
{
// read raw binary data
var pcm_data = fs.readFileSync(fname_wav);
if (pcm_data == null) {
console.log("whisper: failed to read wav file");
process.exit(1);
}
// convert to 32-bit float array
var pcm = new Float32Array(pcm_data.buffer);
// transcribe
var ret = whisper.full_default(pcm, "en", false);
if (ret != 0) {
console.log("whisper: failed to transcribe");
process.exit(1);
}
}
// free memory
{
whisper.free();
}
}); });

Loading…
Cancel
Save