whisper.wasm : add more q4_0 models + add nthreads selector

4-bit
Georgi Gerganov 2 years ago
parent 3916503e11
commit 6e776543f3
No known key found for this signature in database
GPG Key ID: 449E073F9DC10735

@ -145,7 +145,15 @@ function loadRemote(url, dst, size_mb, cbProgress, cbReady, cbCancel, cbPrint) {
var db = event.target.result; var db = event.target.result;
var tx = db.transaction(['models'], 'readwrite'); var tx = db.transaction(['models'], 'readwrite');
var os = tx.objectStore('models'); var os = tx.objectStore('models');
var rq = null;
try {
var rq = os.put(data, url); var rq = os.put(data, url);
} catch (e) {
cbPrint('loadRemote: failed to store "' + url + '" in the IndexedDB: \n' + e);
cbCancel();
return;
}
rq.onsuccess = function (event) { rq.onsuccess = function (event) {
cbPrint('loadRemote: "' + url + '" stored in the IndexedDB'); cbPrint('loadRemote: "' + url + '" stored in the IndexedDB');
@ -180,7 +188,6 @@ function loadRemote(url, dst, size_mb, cbProgress, cbReady, cbCancel, cbPrint) {
rq.onabort = function (event) { rq.onabort = function (event) {
cbPrint('loadRemote: failed to open IndexedDB: abort'); cbPrint('loadRemote: failed to open IndexedDB: abort');
cbCancel();
}; };
} }

@ -31,7 +31,7 @@ endif()
set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \ set_target_properties(${TARGET} PROPERTIES LINK_FLAGS " \
--bind \ --bind \
-s USE_PTHREADS=1 \ -s USE_PTHREADS=1 \
-s PTHREAD_POOL_SIZE=8 \ -s PTHREAD_POOL_SIZE_STRICT=0 \
-s INITIAL_MEMORY=2000MB \ -s INITIAL_MEMORY=2000MB \
-s TOTAL_MEMORY=2000MB \ -s TOTAL_MEMORY=2000MB \
-s FORCE_FILESYSTEM=1 \ -s FORCE_FILESYSTEM=1 \

@ -10,6 +10,12 @@ std::thread g_worker;
std::vector<struct whisper_context *> g_contexts(4, nullptr); std::vector<struct whisper_context *> g_contexts(4, nullptr);
static inline int mpow2(int n) {
int p = 1;
while (p <= n) p *= 2;
return p/2;
}
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_worker.joinable()) {
@ -43,7 +49,7 @@ EMSCRIPTEN_BINDINGS(whisper) {
} }
})); }));
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([](size_t index, const emscripten::val & audio, const std::string & lang, int nthreads, bool translate) {
if (g_worker.joinable()) { if (g_worker.joinable()) {
g_worker.join(); g_worker.join();
} }
@ -66,7 +72,7 @@ EMSCRIPTEN_BINDINGS(whisper) {
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_contexts[index]) ? lang.c_str() : "en";
params.n_threads = std::min(8, (int) std::thread::hardware_concurrency()); params.n_threads = std::min(nthreads, std::min(16, mpow2(std::thread::hardware_concurrency())));
params.offset_ms = 0; params.offset_ms = 0;
std::vector<float> pcmf32; std::vector<float> pcmf32;

@ -43,7 +43,7 @@
<b>Important:</b> <b>Important:</b>
<ul> <ul>
<li>your browser must support WASM SIMD instructions for this to work</li> <li>your browser must support WASM SIMD instructions for this to work</li>
<li>quantized models are still in experimental stage</li> <li>quantized models are still in experimental stage (<a href="https://github.com/ggerganov/ggml/pull/27">more info</a>)</li>
<li>Firefox cannot load files larger than 256 MB - use Chrome instead</li> <li>Firefox cannot load files larger than 256 MB - use Chrome instead</li>
</ul> </ul>
@ -174,6 +174,12 @@
<option value="yi">Yiddish</option> <option value="yi">Yiddish</option>
</select> </select>
</td> </td>
<!-- Slider to select number of threads between 1 and 16 -->
<td>
Threads:
<input type="range" id="threads" name="threads" min="1" max="16" value="8" onchange="changeThreads(this.value)" />
<span id="threads-value">8</span>
</td>
<td> <td>
<button onclick="onProcess(false);">Transcribe</button> <button onclick="onProcess(false);">Transcribe</button>
</td> </td>
@ -281,6 +287,8 @@
document.getElementById('model-whisper-status').innerHTML = 'loaded "' + model_whisper + '"!'; document.getElementById('model-whisper-status').innerHTML = 'loaded "' + model_whisper + '"!';
printTextarea('storeFS: stored model: ' + fname + ' size: ' + buf.length); printTextarea('storeFS: stored model: ' + fname + ' size: ' + buf.length);
document.getElementById('model').innerHTML = 'Model fetched: ' + model_whisper;
} }
function loadFile(event, fname) { function loadFile(event, fname) {
@ -384,6 +392,7 @@
cbCancel = function() { cbCancel = function() {
var el; var el;
el = document.getElementById('fetch-whisper-tiny-en' ); if (el) el.style.display = 'inline-block'; el = document.getElementById('fetch-whisper-tiny-en' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-base-en' ); if (el) el.style.display = 'inline-block'; el = document.getElementById('fetch-whisper-base-en' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-small-en'); if (el) el.style.display = 'inline-block'; el = document.getElementById('fetch-whisper-small-en'); if (el) el.style.display = 'inline-block';
@ -391,6 +400,12 @@
el = document.getElementById('fetch-whisper-base' ); if (el) el.style.display = 'inline-block'; el = document.getElementById('fetch-whisper-base' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-small' ); if (el) el.style.display = 'inline-block'; el = document.getElementById('fetch-whisper-small' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-base-en-q4_0' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-base-q4_0' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-small-en-q4_0' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-small-q4_0' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-medium-en-q4_0'); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-medium-q4_0' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('fetch-whisper-large-q4_0' ); if (el) el.style.display = 'inline-block'; el = document.getElementById('fetch-whisper-large-q4_0' ); if (el) el.style.display = 'inline-block';
el = document.getElementById('whisper-file' ); if (el) el.style.display = 'inline-block'; el = document.getElementById('whisper-file' ); if (el) el.style.display = 'inline-block';
@ -405,6 +420,7 @@
// //
const kMaxAudio_s = 30*60; const kMaxAudio_s = 30*60;
const kMaxRecording_s = 2*60;
const kSampleRate = 16000; const kSampleRate = 16000;
window.AudioContext = window.AudioContext || window.webkitAudioContext; window.AudioContext = window.AudioContext || window.webkitAudioContext;
@ -473,7 +489,7 @@
doRecording = false; doRecording = false;
} }
// record up to kMaxAudio_s seconds of audio from the microphone // record up to kMaxRecording_s seconds of audio from the microphone
// check if doRecording is false every 1000 ms and stop recording if so // check if doRecording is false every 1000 ms and stop recording if so
// update progress information // update progress information
function startRecording() { function startRecording() {
@ -529,9 +545,9 @@
printTextarea('js: audio recorded, size: ' + audio.length); printTextarea('js: audio recorded, size: ' + audio.length);
// truncate to first 30 seconds // truncate to first 30 seconds
if (audio.length > kMaxAudio_s*kSampleRate) { if (audio.length > kMaxRecording_s*kSampleRate) {
audio = audio.slice(0, kMaxAudio_s*kSampleRate); audio = audio.slice(0, kMaxRecording_s*kSampleRate);
printTextarea('js: truncated audio to first ' + kMaxAudio_s + ' seconds'); printTextarea('js: truncated audio to first ' + kMaxRecording_s + ' seconds');
} }
setAudio(audio); setAudio(audio);
}); });
@ -559,24 +575,31 @@
}); });
} }
document.getElementById('progress-bar').style.width = (100*(Date.now() - startTime)/1000/kMaxAudio_s) + '%'; document.getElementById('progress-bar').style.width = (100*(Date.now() - startTime)/1000/kMaxRecording_s) + '%';
document.getElementById('progress-text').innerHTML = (100*(Date.now() - startTime)/1000/kMaxAudio_s).toFixed(0) + '%'; document.getElementById('progress-text').innerHTML = (100*(Date.now() - startTime)/1000/kMaxRecording_s).toFixed(0) + '%';
}, 1000); }, 1000);
printTextarea('js: recording ...'); printTextarea('js: recording ...');
setTimeout(function() { setTimeout(function() {
if (doRecording) { if (doRecording) {
printTextarea('js: recording stopped after ' + kMaxAudio_s + ' seconds'); printTextarea('js: recording stopped after ' + kMaxRecording_s + ' seconds');
stopRecording(); stopRecording();
} }
}, kMaxAudio_s*1000); }, kMaxRecording_s*1000);
} }
// //
// transcribe // transcribe
// //
var nthreads = 8;
function changeThreads(value) {
nthreads = value;
document.getElementById('threads-value').innerHTML = nthreads;
}
function onProcess(translate) { function onProcess(translate) {
if (!instance) { if (!instance) {
instance = Module.init('whisper.bin'); instance = Module.init('whisper.bin');
@ -603,7 +626,7 @@
printTextarea(''); printTextarea('');
setTimeout(function() { setTimeout(function() {
var ret = Module.full_default(instance, audio, document.getElementById('language').value, translate); var ret = Module.full_default(instance, audio, document.getElementById('language').value, nthreads, translate);
console.log('js: full_default returned: ' + ret); console.log('js: full_default returned: ' + ret);
if (ret) { if (ret) {
printTextarea("js: whisper returned: " + ret); printTextarea("js: whisper returned: " + ret);

Loading…
Cancel
Save