@sridhar-mani/whisper-web-transcriber 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.bundled.js +16 -7
- package/dist/index.bundled.min.js +1 -1
- package/dist/index.esm.js +16 -7
- package/dist/index.js +16 -7
- package/dist/index.min.js +1 -1
- package/package.json +1 -1
package/dist/index.bundled.js
CHANGED
|
@@ -141,7 +141,7 @@ Current Status:
|
|
|
141
141
|
// Continue anyway, it might work with direct loading
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
-
return new Promise((resolve, reject) => {
|
|
144
|
+
return new Promise(async (resolve, reject) => {
|
|
145
145
|
// Configure Module before the script loads
|
|
146
146
|
window.Module = {
|
|
147
147
|
locateFile: (path) => {
|
|
@@ -193,12 +193,21 @@ Current Status:
|
|
|
193
193
|
document.head.appendChild(script);
|
|
194
194
|
}
|
|
195
195
|
else {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
196
|
+
try {
|
|
197
|
+
const basePath = this.getScriptBasePath();
|
|
198
|
+
const response = await fetch(basePath + 'libstream.js');
|
|
199
|
+
const code = await response.text();
|
|
200
|
+
// Force the correct MIME type via Blob
|
|
201
|
+
const blob = new Blob([code], { type: 'text/javascript' });
|
|
202
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
203
|
+
const script = document.createElement('script');
|
|
204
|
+
script.src = blobUrl; // Load from memory, bypassing extension MIME headers
|
|
205
|
+
script.onerror = () => reject(new Error('Failed to load WASM module'));
|
|
206
|
+
document.head.appendChild(script);
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
reject(new Error('Failed to fetch/blobify libstream.js: ' + error));
|
|
210
|
+
}
|
|
202
211
|
}
|
|
203
212
|
});
|
|
204
213
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).WhisperTranscriber={})}(this,(function(e){"use strict";class i{constructor(e={}){this.instance=null,this.mediaRecorder=null,this.audioContext=null,this.isRecording=!1,this.audio=null,this.audio0=null,this.Module=null,this.modelLoaded=!1,this.initPromise=null,this.config={modelUrl:e.modelUrl||i.MODEL_URLS[e.modelSize||"base-en-q5_1"],modelSize:e.modelSize||"base-en-q5_1",sampleRate:e.sampleRate||16e3,audioIntervalMs:e.audioIntervalMs||5e3,onTranscription:e.onTranscription||(()=>{}),onProgress:e.onProgress||(()=>{}),onStatus:e.onStatus||(()=>{}),debug:e.debug||!1},this.registerServiceWorkerIfNeeded()}log(e){this.config.debug&&console.log("[WhisperTranscriber]",e)}async registerServiceWorkerIfNeeded(){window.crossOriginIsolated||window.COI_SERVICEWORKER_CODE&&console.warn("[WhisperTranscriber] SharedArrayBuffer is not available. To enable it, you need to serve your site with COOP/COEP headers or use a service worker.\nYou can get the service worker code by calling: transcriber.getServiceWorkerCode()")}getServiceWorkerCode(){return window.COI_SERVICEWORKER_CODE?window.COI_SERVICEWORKER_CODE:null}getCrossOriginIsolationInstructions(){const e=this.getServiceWorkerCode();return window.crossOriginIsolated?"Cross-Origin Isolation is already enabled! No action needed.":`\nCross-Origin Isolation Setup Required\n=====================================\n\nWhisperTranscriber requires SharedArrayBuffer, which needs Cross-Origin Isolation.\n\nOption 1: Server Headers (Recommended)\n--------------------------------------\nConfigure your server to send these headers:\n Cross-Origin-Embedder-Policy: require-corp\n Cross-Origin-Opener-Policy: same-origin\n\nOption 2: Service Worker\n------------------------\n1. Save the following code as 'coi-serviceworker.js' in your website root:\n\n${e?"--- START SERVICE WORKER CODE ---\n"+e+"\n--- END SERVICE WORKER CODE ---":"[Service worker code not available]"}\n\n2. Register the service worker by adding this to your HTML:\n <script src="/coi-serviceworker.js"><\/script>\n\n3. Reload the page after registration.\n\nCurrent Status:\n- crossOriginIsolated: ${window.crossOriginIsolated}\n- SharedArrayBuffer available: ${"undefined"!=typeof SharedArrayBuffer}\n `.trim()}getScriptBasePath(){var e;try{const i=null===(e=window.chrome)||void 0===e?void 0:e.runtime;if(i&&"function"==typeof i.getURL)return i.getURL("whisper-assets/")}catch(e){}return"/src/"}async createWorkerFromURL(e){const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);return new Worker(r)}async loadWasmModule(){if(window.LIBSTREAM_WORKER_CODE){this.log("Using inlined worker code");const e=new Blob([window.LIBSTREAM_WORKER_CODE],{type:"application/javascript"}),i=URL.createObjectURL(e);window.__whisperWorkerBlobUrl=i,this.log("Worker blob URL created from inlined code")}else{const e=this.getScriptBasePath()+"libstream.worker.js";try{const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);window.__whisperWorkerBlobUrl=r,this.log("Worker script loaded and blob URL created")}catch(e){this.log("Failed to pre-fetch worker: "+e)}}return new Promise(((e,i)=>{if(window.Module={locateFile:e=>"libstream.worker.js"===e&&window.__whisperWorkerBlobUrl?window.__whisperWorkerBlobUrl:this.getScriptBasePath()+e,onRuntimeInitialized:()=>{this.log("WASM runtime initialized"),setTimeout((()=>{const t=window.Module;t?(this.Module=t,t.init||(t.init=t.cwrap("init","number",["string"])),t.set_audio||(t.set_audio=t.cwrap("set_audio","",["number","array"])),t.get_transcribed||(t.get_transcribed=t.cwrap("get_transcribed","string",[])),t.set_status||(t.set_status=t.cwrap("set_status","",["string"])),this.log("WASM module loaded and functions initialized"),e()):i(new Error("Module not available after runtime initialized"))}),100)}},window.LIBSTREAM_CODE){this.log("Using inlined libstream code");const e=new Blob([window.LIBSTREAM_CODE],{type:"application/javascript"}),t=URL.createObjectURL(e),o=document.createElement("script");o.src=t,o.onerror=()=>i(new Error("Failed to load WASM module")),document.head.appendChild(o)}else{const e=
|
|
1
|
+
!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).WhisperTranscriber={})}(this,(function(e){"use strict";class i{constructor(e={}){this.instance=null,this.mediaRecorder=null,this.audioContext=null,this.isRecording=!1,this.audio=null,this.audio0=null,this.Module=null,this.modelLoaded=!1,this.initPromise=null,this.config={modelUrl:e.modelUrl||i.MODEL_URLS[e.modelSize||"base-en-q5_1"],modelSize:e.modelSize||"base-en-q5_1",sampleRate:e.sampleRate||16e3,audioIntervalMs:e.audioIntervalMs||5e3,onTranscription:e.onTranscription||(()=>{}),onProgress:e.onProgress||(()=>{}),onStatus:e.onStatus||(()=>{}),debug:e.debug||!1},this.registerServiceWorkerIfNeeded()}log(e){this.config.debug&&console.log("[WhisperTranscriber]",e)}async registerServiceWorkerIfNeeded(){window.crossOriginIsolated||window.COI_SERVICEWORKER_CODE&&console.warn("[WhisperTranscriber] SharedArrayBuffer is not available. To enable it, you need to serve your site with COOP/COEP headers or use a service worker.\nYou can get the service worker code by calling: transcriber.getServiceWorkerCode()")}getServiceWorkerCode(){return window.COI_SERVICEWORKER_CODE?window.COI_SERVICEWORKER_CODE:null}getCrossOriginIsolationInstructions(){const e=this.getServiceWorkerCode();return window.crossOriginIsolated?"Cross-Origin Isolation is already enabled! No action needed.":`\nCross-Origin Isolation Setup Required\n=====================================\n\nWhisperTranscriber requires SharedArrayBuffer, which needs Cross-Origin Isolation.\n\nOption 1: Server Headers (Recommended)\n--------------------------------------\nConfigure your server to send these headers:\n Cross-Origin-Embedder-Policy: require-corp\n Cross-Origin-Opener-Policy: same-origin\n\nOption 2: Service Worker\n------------------------\n1. Save the following code as 'coi-serviceworker.js' in your website root:\n\n${e?"--- START SERVICE WORKER CODE ---\n"+e+"\n--- END SERVICE WORKER CODE ---":"[Service worker code not available]"}\n\n2. Register the service worker by adding this to your HTML:\n <script src="/coi-serviceworker.js"><\/script>\n\n3. Reload the page after registration.\n\nCurrent Status:\n- crossOriginIsolated: ${window.crossOriginIsolated}\n- SharedArrayBuffer available: ${"undefined"!=typeof SharedArrayBuffer}\n `.trim()}getScriptBasePath(){var e;try{const i=null===(e=window.chrome)||void 0===e?void 0:e.runtime;if(i&&"function"==typeof i.getURL)return i.getURL("whisper-assets/")}catch(e){}return"/src/"}async createWorkerFromURL(e){const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);return new Worker(r)}async loadWasmModule(){if(window.LIBSTREAM_WORKER_CODE){this.log("Using inlined worker code");const e=new Blob([window.LIBSTREAM_WORKER_CODE],{type:"application/javascript"}),i=URL.createObjectURL(e);window.__whisperWorkerBlobUrl=i,this.log("Worker blob URL created from inlined code")}else{const e=this.getScriptBasePath()+"libstream.worker.js";try{const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);window.__whisperWorkerBlobUrl=r,this.log("Worker script loaded and blob URL created")}catch(e){this.log("Failed to pre-fetch worker: "+e)}}return new Promise((async(e,i)=>{if(window.Module={locateFile:e=>"libstream.worker.js"===e&&window.__whisperWorkerBlobUrl?window.__whisperWorkerBlobUrl:this.getScriptBasePath()+e,onRuntimeInitialized:()=>{this.log("WASM runtime initialized"),setTimeout((()=>{const t=window.Module;t?(this.Module=t,t.init||(t.init=t.cwrap("init","number",["string"])),t.set_audio||(t.set_audio=t.cwrap("set_audio","",["number","array"])),t.get_transcribed||(t.get_transcribed=t.cwrap("get_transcribed","string",[])),t.set_status||(t.set_status=t.cwrap("set_status","",["string"])),this.log("WASM module loaded and functions initialized"),e()):i(new Error("Module not available after runtime initialized"))}),100)}},window.LIBSTREAM_CODE){this.log("Using inlined libstream code");const e=new Blob([window.LIBSTREAM_CODE],{type:"application/javascript"}),t=URL.createObjectURL(e),o=document.createElement("script");o.src=t,o.onerror=()=>i(new Error("Failed to load WASM module")),document.head.appendChild(o)}else try{const e=this.getScriptBasePath(),t=await fetch(e+"libstream.js"),o=await t.text(),r=new Blob([o],{type:"text/javascript"}),n=URL.createObjectURL(r),s=document.createElement("script");s.src=n,s.onerror=()=>i(new Error("Failed to load WASM module")),document.head.appendChild(s)}catch(e){i(new Error("Failed to fetch/blobify libstream.js: "+e))}}))}async loadHelpers(){if(window.HELPERS_CODE){this.log("Using inlined helpers code");const e=new Blob([window.HELPERS_CODE],{type:"application/javascript"}),i=URL.createObjectURL(e),t=document.createElement("script");return t.src=i,new Promise(((e,i)=>{t.onload=()=>e(),t.onerror=()=>i(new Error("Failed to load helpers")),document.head.appendChild(t)}))}{const e=document.createElement("script");return e.src=this.getScriptBasePath()+"helpers.js",new Promise(((i,t)=>{e.onload=()=>i(),e.onerror=()=>t(new Error("Failed to load helpers")),document.head.appendChild(e)}))}}async loadCOIServiceWorker(){if("undefined"!=typeof SharedArrayBuffer)return void this.log("SharedArrayBuffer already available");const e=this.getScriptBasePath(),i=document.createElement("script");return i.src=e+"coi-serviceworker.js",new Promise((e=>{i.onload=()=>{this.log("COI service worker loaded"),e()},i.onerror=()=>{this.log("Failed to load COI service worker - SharedArrayBuffer may not be available"),e()},document.head.appendChild(i)}))}async initialize(){return this.initPromise||(this.initPromise=(async()=>{try{await this.loadCOIServiceWorker(),window.dbVersion=1,window.dbName="whisper.transcriber.models",await this.loadHelpers(),this.log("Helpers loaded"),await this.loadWasmModule(),this.log("WASM module initialized"),this.config.onStatus("Ready to load model")}catch(e){throw this.log("Failed to initialize: "+e),e}})()),this.initPromise}async loadModel(){if(!this.modelLoaded)return await this.initialize(),new Promise(((e,t)=>{const o=this.config.modelUrl,r=i.MODEL_SIZES[this.config.modelSize];this.config.onStatus("Loading model...");window.loadRemote(o,"whisper.bin",r,(e=>{this.config.onProgress(Math.round(100*e))}),((i,t)=>{try{this.Module.FS_unlink(i)}catch(e){}this.Module.FS_createDataFile("/",i,t,!0,!0),this.log(`Model stored: ${i}, size: ${t.length}`),this.modelLoaded=!0,this.config.onStatus("Model loaded successfully"),e()}),(()=>{this.config.onStatus("Model loading cancelled"),t(new Error("Model loading cancelled"))}),(e=>{this.log(e)}))}));this.log("Model already loaded")}async startRecording(){if(!this.modelLoaded)throw new Error("Model not loaded. Call loadModel() first.");if(this.isRecording)return void this.log("Already recording");if(!this.instance){const e=this.Module.init||this.Module.cwrap("init","number",["string"]);if(this.instance=e("whisper.bin"),!this.instance)throw new Error("Failed to initialize Whisper");this.log("Whisper instance initialized")}this.audioContext=new AudioContext({sampleRate:this.config.sampleRate,channelCount:1,echoCancellation:!1,autoGainControl:!0,noiseSuppression:!0});(this.Module.set_status||this.Module.cwrap("set_status","",["string"]))(""),this.isRecording=!0,this.config.onStatus("Recording...");const e=[];try{const i=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1});this.mediaRecorder=new MediaRecorder(i),this.mediaRecorder.ondataavailable=i=>{e.push(i.data);const t=new Blob(e,{type:"audio/ogg; codecs=opus"}),o=new FileReader;o.onload=e=>{const i=new Uint8Array(e.target.result);this.audioContext&&this.audioContext.decodeAudioData(i.buffer,(e=>{const i=new OfflineAudioContext(e.numberOfChannels,e.length,e.sampleRate),t=i.createBufferSource();t.buffer=e,t.connect(i.destination),t.start(0),i.startRendering().then((e=>{this.audio=e.getChannelData(0);const i=new Float32Array(null==this.audio0?this.audio.length:this.audio0.length+this.audio.length);if(null!=this.audio0&&i.set(this.audio0,0),i.set(this.audio,null==this.audio0?0:this.audio0.length),this.instance){(this.Module.set_audio||this.Module.cwrap("set_audio","",["number","array"]))(this.instance,i)}}))}))},o.readAsArrayBuffer(t)},this.mediaRecorder.onstop=()=>{this.isRecording&&setTimeout((()=>this.startRecording()),0)},this.mediaRecorder.start(this.config.audioIntervalMs),this.startTranscriptionPolling()}catch(e){throw this.isRecording=!1,this.config.onStatus("Error: "+e.message),e}}startTranscriptionPolling(){const e=setInterval((()=>{if(!this.isRecording)return void clearInterval(e);const i=(this.Module.get_transcribed||this.Module.cwrap("get_transcribed","string",[]))();null!=i&&i.length>1&&this.config.onTranscription(i)}),100)}stopRecording(){if(!this.isRecording)return void this.log("Not recording");(this.Module.set_status||this.Module.cwrap("set_status","",["string"]))("paused"),this.isRecording=!1,this.audio0=null,this.audio=null,this.mediaRecorder&&(this.mediaRecorder.stop(),this.mediaRecorder=null),this.audioContext&&(this.audioContext.close(),this.audioContext=null),this.config.onStatus("Stopped")}destroy(){this.stopRecording(),this.instance=null,this.Module=null,this.modelLoaded=!1}}i.MODEL_URLS={"tiny.en":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en.bin","base.en":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin","tiny-en-q5_1":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en-q5_1.bin","base-en-q5_1":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en-q5_1.bin"},i.MODEL_SIZES={"tiny.en":75,"base.en":142,"tiny-en-q5_1":31,"base-en-q5_1":57},e.WhisperTranscriber=i}));
|
package/dist/index.esm.js
CHANGED
|
@@ -135,7 +135,7 @@ Current Status:
|
|
|
135
135
|
// Continue anyway, it might work with direct loading
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
return new Promise((resolve, reject) => {
|
|
138
|
+
return new Promise(async (resolve, reject) => {
|
|
139
139
|
// Configure Module before the script loads
|
|
140
140
|
window.Module = {
|
|
141
141
|
locateFile: (path) => {
|
|
@@ -187,12 +187,21 @@ Current Status:
|
|
|
187
187
|
document.head.appendChild(script);
|
|
188
188
|
}
|
|
189
189
|
else {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
190
|
+
try {
|
|
191
|
+
const basePath = this.getScriptBasePath();
|
|
192
|
+
const response = await fetch(basePath + 'libstream.js');
|
|
193
|
+
const code = await response.text();
|
|
194
|
+
// Force the correct MIME type via Blob
|
|
195
|
+
const blob = new Blob([code], { type: 'text/javascript' });
|
|
196
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
197
|
+
const script = document.createElement('script');
|
|
198
|
+
script.src = blobUrl; // Load from memory, bypassing extension MIME headers
|
|
199
|
+
script.onerror = () => reject(new Error('Failed to load WASM module'));
|
|
200
|
+
document.head.appendChild(script);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
reject(new Error('Failed to fetch/blobify libstream.js: ' + error));
|
|
204
|
+
}
|
|
196
205
|
}
|
|
197
206
|
});
|
|
198
207
|
}
|
package/dist/index.js
CHANGED
|
@@ -141,7 +141,7 @@ Current Status:
|
|
|
141
141
|
// Continue anyway, it might work with direct loading
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
-
return new Promise((resolve, reject) => {
|
|
144
|
+
return new Promise(async (resolve, reject) => {
|
|
145
145
|
// Configure Module before the script loads
|
|
146
146
|
window.Module = {
|
|
147
147
|
locateFile: (path) => {
|
|
@@ -193,12 +193,21 @@ Current Status:
|
|
|
193
193
|
document.head.appendChild(script);
|
|
194
194
|
}
|
|
195
195
|
else {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
196
|
+
try {
|
|
197
|
+
const basePath = this.getScriptBasePath();
|
|
198
|
+
const response = await fetch(basePath + 'libstream.js');
|
|
199
|
+
const code = await response.text();
|
|
200
|
+
// Force the correct MIME type via Blob
|
|
201
|
+
const blob = new Blob([code], { type: 'text/javascript' });
|
|
202
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
203
|
+
const script = document.createElement('script');
|
|
204
|
+
script.src = blobUrl; // Load from memory, bypassing extension MIME headers
|
|
205
|
+
script.onerror = () => reject(new Error('Failed to load WASM module'));
|
|
206
|
+
document.head.appendChild(script);
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
reject(new Error('Failed to fetch/blobify libstream.js: ' + error));
|
|
210
|
+
}
|
|
202
211
|
}
|
|
203
212
|
});
|
|
204
213
|
}
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).WhisperTranscriber={})}(this,(function(e){"use strict";class i{constructor(e={}){this.instance=null,this.mediaRecorder=null,this.audioContext=null,this.isRecording=!1,this.audio=null,this.audio0=null,this.Module=null,this.modelLoaded=!1,this.initPromise=null,this.config={modelUrl:e.modelUrl||i.MODEL_URLS[e.modelSize||"base-en-q5_1"],modelSize:e.modelSize||"base-en-q5_1",sampleRate:e.sampleRate||16e3,audioIntervalMs:e.audioIntervalMs||5e3,onTranscription:e.onTranscription||(()=>{}),onProgress:e.onProgress||(()=>{}),onStatus:e.onStatus||(()=>{}),debug:e.debug||!1},this.registerServiceWorkerIfNeeded()}log(e){this.config.debug&&console.log("[WhisperTranscriber]",e)}async registerServiceWorkerIfNeeded(){window.crossOriginIsolated||window.COI_SERVICEWORKER_CODE&&console.warn("[WhisperTranscriber] SharedArrayBuffer is not available. To enable it, you need to serve your site with COOP/COEP headers or use a service worker.\nYou can get the service worker code by calling: transcriber.getServiceWorkerCode()")}getServiceWorkerCode(){return window.COI_SERVICEWORKER_CODE?window.COI_SERVICEWORKER_CODE:null}getCrossOriginIsolationInstructions(){const e=this.getServiceWorkerCode();return window.crossOriginIsolated?"Cross-Origin Isolation is already enabled! No action needed.":`\nCross-Origin Isolation Setup Required\n=====================================\n\nWhisperTranscriber requires SharedArrayBuffer, which needs Cross-Origin Isolation.\n\nOption 1: Server Headers (Recommended)\n--------------------------------------\nConfigure your server to send these headers:\n Cross-Origin-Embedder-Policy: require-corp\n Cross-Origin-Opener-Policy: same-origin\n\nOption 2: Service Worker\n------------------------\n1. Save the following code as 'coi-serviceworker.js' in your website root:\n\n${e?"--- START SERVICE WORKER CODE ---\n"+e+"\n--- END SERVICE WORKER CODE ---":"[Service worker code not available]"}\n\n2. Register the service worker by adding this to your HTML:\n <script src="/coi-serviceworker.js"><\/script>\n\n3. Reload the page after registration.\n\nCurrent Status:\n- crossOriginIsolated: ${window.crossOriginIsolated}\n- SharedArrayBuffer available: ${"undefined"!=typeof SharedArrayBuffer}\n `.trim()}getScriptBasePath(){var e;try{const i=null===(e=window.chrome)||void 0===e?void 0:e.runtime;if(i&&"function"==typeof i.getURL)return i.getURL("whisper-assets/")}catch(e){}return"/src/"}async createWorkerFromURL(e){const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);return new Worker(r)}async loadWasmModule(){if(window.LIBSTREAM_WORKER_CODE){this.log("Using inlined worker code");const e=new Blob([window.LIBSTREAM_WORKER_CODE],{type:"application/javascript"}),i=URL.createObjectURL(e);window.__whisperWorkerBlobUrl=i,this.log("Worker blob URL created from inlined code")}else{const e=this.getScriptBasePath()+"libstream.worker.js";try{const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);window.__whisperWorkerBlobUrl=r,this.log("Worker script loaded and blob URL created")}catch(e){this.log("Failed to pre-fetch worker: "+e)}}return new Promise(((e,i)=>{if(window.Module={locateFile:e=>"libstream.worker.js"===e&&window.__whisperWorkerBlobUrl?window.__whisperWorkerBlobUrl:this.getScriptBasePath()+e,onRuntimeInitialized:()=>{this.log("WASM runtime initialized"),setTimeout((()=>{const t=window.Module;t?(this.Module=t,t.init||(t.init=t.cwrap("init","number",["string"])),t.set_audio||(t.set_audio=t.cwrap("set_audio","",["number","array"])),t.get_transcribed||(t.get_transcribed=t.cwrap("get_transcribed","string",[])),t.set_status||(t.set_status=t.cwrap("set_status","",["string"])),this.log("WASM module loaded and functions initialized"),e()):i(new Error("Module not available after runtime initialized"))}),100)}},window.LIBSTREAM_CODE){this.log("Using inlined libstream code");const e=new Blob([window.LIBSTREAM_CODE],{type:"application/javascript"}),t=URL.createObjectURL(e),o=document.createElement("script");o.src=t,o.onerror=()=>i(new Error("Failed to load WASM module")),document.head.appendChild(o)}else{const e=
|
|
1
|
+
!function(e,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i((e="undefined"!=typeof globalThis?globalThis:e||self).WhisperTranscriber={})}(this,(function(e){"use strict";class i{constructor(e={}){this.instance=null,this.mediaRecorder=null,this.audioContext=null,this.isRecording=!1,this.audio=null,this.audio0=null,this.Module=null,this.modelLoaded=!1,this.initPromise=null,this.config={modelUrl:e.modelUrl||i.MODEL_URLS[e.modelSize||"base-en-q5_1"],modelSize:e.modelSize||"base-en-q5_1",sampleRate:e.sampleRate||16e3,audioIntervalMs:e.audioIntervalMs||5e3,onTranscription:e.onTranscription||(()=>{}),onProgress:e.onProgress||(()=>{}),onStatus:e.onStatus||(()=>{}),debug:e.debug||!1},this.registerServiceWorkerIfNeeded()}log(e){this.config.debug&&console.log("[WhisperTranscriber]",e)}async registerServiceWorkerIfNeeded(){window.crossOriginIsolated||window.COI_SERVICEWORKER_CODE&&console.warn("[WhisperTranscriber] SharedArrayBuffer is not available. To enable it, you need to serve your site with COOP/COEP headers or use a service worker.\nYou can get the service worker code by calling: transcriber.getServiceWorkerCode()")}getServiceWorkerCode(){return window.COI_SERVICEWORKER_CODE?window.COI_SERVICEWORKER_CODE:null}getCrossOriginIsolationInstructions(){const e=this.getServiceWorkerCode();return window.crossOriginIsolated?"Cross-Origin Isolation is already enabled! No action needed.":`\nCross-Origin Isolation Setup Required\n=====================================\n\nWhisperTranscriber requires SharedArrayBuffer, which needs Cross-Origin Isolation.\n\nOption 1: Server Headers (Recommended)\n--------------------------------------\nConfigure your server to send these headers:\n Cross-Origin-Embedder-Policy: require-corp\n Cross-Origin-Opener-Policy: same-origin\n\nOption 2: Service Worker\n------------------------\n1. Save the following code as 'coi-serviceworker.js' in your website root:\n\n${e?"--- START SERVICE WORKER CODE ---\n"+e+"\n--- END SERVICE WORKER CODE ---":"[Service worker code not available]"}\n\n2. Register the service worker by adding this to your HTML:\n <script src="/coi-serviceworker.js"><\/script>\n\n3. Reload the page after registration.\n\nCurrent Status:\n- crossOriginIsolated: ${window.crossOriginIsolated}\n- SharedArrayBuffer available: ${"undefined"!=typeof SharedArrayBuffer}\n `.trim()}getScriptBasePath(){var e;try{const i=null===(e=window.chrome)||void 0===e?void 0:e.runtime;if(i&&"function"==typeof i.getURL)return i.getURL("whisper-assets/")}catch(e){}return"/src/"}async createWorkerFromURL(e){const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);return new Worker(r)}async loadWasmModule(){if(window.LIBSTREAM_WORKER_CODE){this.log("Using inlined worker code");const e=new Blob([window.LIBSTREAM_WORKER_CODE],{type:"application/javascript"}),i=URL.createObjectURL(e);window.__whisperWorkerBlobUrl=i,this.log("Worker blob URL created from inlined code")}else{const e=this.getScriptBasePath()+"libstream.worker.js";try{const i=await fetch(e),t=await i.text(),o=new Blob([t],{type:"application/javascript"}),r=URL.createObjectURL(o);window.__whisperWorkerBlobUrl=r,this.log("Worker script loaded and blob URL created")}catch(e){this.log("Failed to pre-fetch worker: "+e)}}return new Promise((async(e,i)=>{if(window.Module={locateFile:e=>"libstream.worker.js"===e&&window.__whisperWorkerBlobUrl?window.__whisperWorkerBlobUrl:this.getScriptBasePath()+e,onRuntimeInitialized:()=>{this.log("WASM runtime initialized"),setTimeout((()=>{const t=window.Module;t?(this.Module=t,t.init||(t.init=t.cwrap("init","number",["string"])),t.set_audio||(t.set_audio=t.cwrap("set_audio","",["number","array"])),t.get_transcribed||(t.get_transcribed=t.cwrap("get_transcribed","string",[])),t.set_status||(t.set_status=t.cwrap("set_status","",["string"])),this.log("WASM module loaded and functions initialized"),e()):i(new Error("Module not available after runtime initialized"))}),100)}},window.LIBSTREAM_CODE){this.log("Using inlined libstream code");const e=new Blob([window.LIBSTREAM_CODE],{type:"application/javascript"}),t=URL.createObjectURL(e),o=document.createElement("script");o.src=t,o.onerror=()=>i(new Error("Failed to load WASM module")),document.head.appendChild(o)}else try{const e=this.getScriptBasePath(),t=await fetch(e+"libstream.js"),o=await t.text(),r=new Blob([o],{type:"text/javascript"}),n=URL.createObjectURL(r),s=document.createElement("script");s.src=n,s.onerror=()=>i(new Error("Failed to load WASM module")),document.head.appendChild(s)}catch(e){i(new Error("Failed to fetch/blobify libstream.js: "+e))}}))}async loadHelpers(){if(window.HELPERS_CODE){this.log("Using inlined helpers code");const e=new Blob([window.HELPERS_CODE],{type:"application/javascript"}),i=URL.createObjectURL(e),t=document.createElement("script");return t.src=i,new Promise(((e,i)=>{t.onload=()=>e(),t.onerror=()=>i(new Error("Failed to load helpers")),document.head.appendChild(t)}))}{const e=document.createElement("script");return e.src=this.getScriptBasePath()+"helpers.js",new Promise(((i,t)=>{e.onload=()=>i(),e.onerror=()=>t(new Error("Failed to load helpers")),document.head.appendChild(e)}))}}async loadCOIServiceWorker(){if("undefined"!=typeof SharedArrayBuffer)return void this.log("SharedArrayBuffer already available");const e=this.getScriptBasePath(),i=document.createElement("script");return i.src=e+"coi-serviceworker.js",new Promise((e=>{i.onload=()=>{this.log("COI service worker loaded"),e()},i.onerror=()=>{this.log("Failed to load COI service worker - SharedArrayBuffer may not be available"),e()},document.head.appendChild(i)}))}async initialize(){return this.initPromise||(this.initPromise=(async()=>{try{await this.loadCOIServiceWorker(),window.dbVersion=1,window.dbName="whisper.transcriber.models",await this.loadHelpers(),this.log("Helpers loaded"),await this.loadWasmModule(),this.log("WASM module initialized"),this.config.onStatus("Ready to load model")}catch(e){throw this.log("Failed to initialize: "+e),e}})()),this.initPromise}async loadModel(){if(!this.modelLoaded)return await this.initialize(),new Promise(((e,t)=>{const o=this.config.modelUrl,r=i.MODEL_SIZES[this.config.modelSize];this.config.onStatus("Loading model...");window.loadRemote(o,"whisper.bin",r,(e=>{this.config.onProgress(Math.round(100*e))}),((i,t)=>{try{this.Module.FS_unlink(i)}catch(e){}this.Module.FS_createDataFile("/",i,t,!0,!0),this.log(`Model stored: ${i}, size: ${t.length}`),this.modelLoaded=!0,this.config.onStatus("Model loaded successfully"),e()}),(()=>{this.config.onStatus("Model loading cancelled"),t(new Error("Model loading cancelled"))}),(e=>{this.log(e)}))}));this.log("Model already loaded")}async startRecording(){if(!this.modelLoaded)throw new Error("Model not loaded. Call loadModel() first.");if(this.isRecording)return void this.log("Already recording");if(!this.instance){const e=this.Module.init||this.Module.cwrap("init","number",["string"]);if(this.instance=e("whisper.bin"),!this.instance)throw new Error("Failed to initialize Whisper");this.log("Whisper instance initialized")}this.audioContext=new AudioContext({sampleRate:this.config.sampleRate,channelCount:1,echoCancellation:!1,autoGainControl:!0,noiseSuppression:!0});(this.Module.set_status||this.Module.cwrap("set_status","",["string"]))(""),this.isRecording=!0,this.config.onStatus("Recording...");const e=[];try{const i=await navigator.mediaDevices.getUserMedia({audio:!0,video:!1});this.mediaRecorder=new MediaRecorder(i),this.mediaRecorder.ondataavailable=i=>{e.push(i.data);const t=new Blob(e,{type:"audio/ogg; codecs=opus"}),o=new FileReader;o.onload=e=>{const i=new Uint8Array(e.target.result);this.audioContext&&this.audioContext.decodeAudioData(i.buffer,(e=>{const i=new OfflineAudioContext(e.numberOfChannels,e.length,e.sampleRate),t=i.createBufferSource();t.buffer=e,t.connect(i.destination),t.start(0),i.startRendering().then((e=>{this.audio=e.getChannelData(0);const i=new Float32Array(null==this.audio0?this.audio.length:this.audio0.length+this.audio.length);if(null!=this.audio0&&i.set(this.audio0,0),i.set(this.audio,null==this.audio0?0:this.audio0.length),this.instance){(this.Module.set_audio||this.Module.cwrap("set_audio","",["number","array"]))(this.instance,i)}}))}))},o.readAsArrayBuffer(t)},this.mediaRecorder.onstop=()=>{this.isRecording&&setTimeout((()=>this.startRecording()),0)},this.mediaRecorder.start(this.config.audioIntervalMs),this.startTranscriptionPolling()}catch(e){throw this.isRecording=!1,this.config.onStatus("Error: "+e.message),e}}startTranscriptionPolling(){const e=setInterval((()=>{if(!this.isRecording)return void clearInterval(e);const i=(this.Module.get_transcribed||this.Module.cwrap("get_transcribed","string",[]))();null!=i&&i.length>1&&this.config.onTranscription(i)}),100)}stopRecording(){if(!this.isRecording)return void this.log("Not recording");(this.Module.set_status||this.Module.cwrap("set_status","",["string"]))("paused"),this.isRecording=!1,this.audio0=null,this.audio=null,this.mediaRecorder&&(this.mediaRecorder.stop(),this.mediaRecorder=null),this.audioContext&&(this.audioContext.close(),this.audioContext=null),this.config.onStatus("Stopped")}destroy(){this.stopRecording(),this.instance=null,this.Module=null,this.modelLoaded=!1}}i.MODEL_URLS={"tiny.en":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en.bin","base.en":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin","tiny-en-q5_1":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en-q5_1.bin","base-en-q5_1":"https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en-q5_1.bin"},i.MODEL_SIZES={"tiny.en":75,"base.en":142,"tiny-en-q5_1":31,"base-en-q5_1":57},e.WhisperTranscriber=i}));
|
package/package.json
CHANGED