Xenova HF staff radames commited on
Commit
59da990
0 Parent(s):

Duplicate from radames/whisper.wasm

Browse files

Co-authored-by: Radamés Ajna <radames@users.noreply.huggingface.co>

.gitattributes ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tflite filter=lfs diff=lfs merge=lfs -text
29
+ *.tgz filter=lfs diff=lfs merge=lfs -text
30
+ *.wasm filter=lfs diff=lfs merge=lfs -text
31
+ *.xz filter=lfs diff=lfs merge=lfs -text
32
+ *.zip filter=lfs diff=lfs merge=lfs -text
33
+ *.zst filter=lfs diff=lfs merge=lfs -text
34
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ FROM nginxinc/nginx-unprivileged
2
+ COPY ./nginx.conf /etc/nginx/conf.d/default.conf
3
+ COPY . /usr/share/nginx/html
README.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Whisper.cpp WASM
3
+ emoji: 📉
4
+ colorFrom: red
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ app_port: 8080
9
+ duplicated_from: radames/whisper.wasm
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
13
+
14
+ Models on https://huggingface.co/datasets/ggerganov/whisper.cpp
ggml-tiny.en.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:921e4cf8686fdd993dcd081a5da5b6c365bfde1162e72b08d75ac75289920b1f
3
+ size 77704715
helpers.js ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Common Javascript functions used by the examples
2
+
3
+ function convertTypedArray(src, type) {
4
+ var buffer = new ArrayBuffer(src.byteLength);
5
+ var baseView = new src.constructor(buffer).set(src);
6
+ return new type(buffer);
7
+ }
8
+
9
+ var printTextarea = (function() {
10
+ var element = document.getElementById('output');
11
+ if (element) element.alue = ''; // clear browser cache
12
+ return function(text) {
13
+ if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
14
+ console.log(text);
15
+ if (element) {
16
+ element.value += text + "\n";
17
+ element.scrollTop = element.scrollHeight; // focus on bottom
18
+ }
19
+ };
20
+ })();
21
+
22
+ async function clearCache() {
23
+ if (confirm('Are you sure you want to clear the cache?\nAll the models will be downloaded again.')) {
24
+ indexedDB.deleteDatabase(dbName);
25
+ }
26
+ }
27
+
28
+ // fetch a remote file from remote URL using the Fetch API
29
+ async function fetchRemote(url, cbProgress, cbPrint) {
30
+ cbPrint('fetchRemote: downloading with fetch()...');
31
+
32
+ const response = await fetch(
33
+ url,
34
+ {
35
+ method: 'GET',
36
+ headers: {
37
+ 'Content-Type': 'application/octet-stream',
38
+ },
39
+ }
40
+ );
41
+
42
+ if (!response.ok) {
43
+ cbPrint('fetchRemote: failed to fetch ' + url);
44
+ return;
45
+ }
46
+
47
+ const contentLength = response.headers.get('content-length');
48
+ const total = parseInt(contentLength, 10);
49
+ const reader = response.body.getReader();
50
+
51
+ var chunks = [];
52
+ var receivedLength = 0;
53
+ var progressLast = -1;
54
+
55
+ while (true) {
56
+ const { done, value } = await reader.read();
57
+
58
+ if (done) {
59
+ break;
60
+ }
61
+
62
+ chunks.push(value);
63
+ receivedLength += value.length;
64
+
65
+ if (contentLength) {
66
+ cbProgress(receivedLength/total);
67
+
68
+ var progressCur = Math.round((receivedLength / total) * 10);
69
+ if (progressCur != progressLast) {
70
+ cbPrint('fetchRemote: fetching ' + 10*progressCur + '% ...');
71
+ progressLast = progressCur;
72
+ }
73
+ }
74
+ }
75
+
76
+ var position = 0;
77
+ var chunksAll = new Uint8Array(receivedLength);
78
+
79
+ for (var chunk of chunks) {
80
+ chunksAll.set(chunk, position);
81
+ position += chunk.length;
82
+ }
83
+
84
+ return chunksAll;
85
+ }
86
+
87
+ // load remote data
88
+ // - check if the data is already in the IndexedDB
89
+ // - if not, fetch it from the remote URL and store it in the IndexedDB
90
+ function loadRemote(url, dst, size_mb, cbProgress, cbReady, cbCancel, cbPrint) {
91
+ // query the storage quota and print it
92
+ navigator.storage.estimate().then(function (estimate) {
93
+ cbPrint('loadRemote: storage quota: ' + estimate.quota + ' bytes');
94
+ cbPrint('loadRemote: storage usage: ' + estimate.usage + ' bytes');
95
+ });
96
+
97
+ // check if the data is already in the IndexedDB
98
+ var rq = indexedDB.open(dbName, dbVersion);
99
+
100
+ rq.onupgradeneeded = function (event) {
101
+ var db = event.target.result;
102
+ if (db.version == 1) {
103
+ var os = db.createObjectStore('models', { autoIncrement: false });
104
+ cbPrint('loadRemote: created IndexedDB ' + db.name + ' version ' + db.version);
105
+ } else {
106
+ // clear the database
107
+ var os = event.currentTarget.transaction.objectStore('models');
108
+ os.clear();
109
+ cbPrint('loadRemote: cleared IndexedDB ' + db.name + ' version ' + db.version);
110
+ }
111
+ };
112
+
113
+ rq.onsuccess = function (event) {
114
+ var db = event.target.result;
115
+ var tx = db.transaction(['models'], 'readonly');
116
+ var os = tx.objectStore('models');
117
+ var rq = os.get(url);
118
+
119
+ rq.onsuccess = function (event) {
120
+ if (rq.result) {
121
+ cbPrint('loadRemote: "' + url + '" is already in the IndexedDB');
122
+ cbReady(dst, rq.result);
123
+ } else {
124
+ // data is not in the IndexedDB
125
+ cbPrint('loadRemote: "' + url + '" is not in the IndexedDB');
126
+
127
+ // alert and ask the user to confirm
128
+ if (!confirm(
129
+ 'You are about to download ' + size_mb + ' MB of data.\n' +
130
+ 'The model data will be cached in the browser for future use.\n\n' +
131
+ 'Press OK to continue.')) {
132
+ cbCancel();
133
+ return;
134
+ }
135
+
136
+ fetchRemote(url, cbProgress, cbPrint).then(function (data) {
137
+ if (data) {
138
+ // store the data in the IndexedDB
139
+ var rq = indexedDB.open(dbName, dbVersion);
140
+ rq.onsuccess = function (event) {
141
+ var db = event.target.result;
142
+ var tx = db.transaction(['models'], 'readwrite');
143
+ var os = tx.objectStore('models');
144
+ var rq = os.put(data, url);
145
+
146
+ rq.onsuccess = function (event) {
147
+ cbPrint('loadRemote: "' + url + '" stored in the IndexedDB');
148
+ cbReady(dst, data);
149
+ };
150
+
151
+ rq.onerror = function (event) {
152
+ cbPrint('loadRemote: failed to store "' + url + '" in the IndexedDB');
153
+ cbCancel();
154
+ };
155
+ };
156
+ }
157
+ });
158
+ }
159
+ };
160
+
161
+ rq.onerror = function (event) {
162
+ cbPrint('loadRemote: failed to get data from the IndexedDB');
163
+ cbCancel();
164
+ };
165
+ };
166
+
167
+ rq.onerror = function (event) {
168
+ cbPrint('loadRemote: failed to open IndexedDB');
169
+ cbCancel();
170
+ };
171
+
172
+ rq.onblocked = function (event) {
173
+ cbPrint('loadRemote: failed to open IndexedDB: blocked');
174
+ cbCancel();
175
+ };
176
+
177
+ rq.onabort = function (event) {
178
+ cbPrint('loadRemote: failed to open IndexedDB: abort');
179
+
180
+ };
181
+ }
182
+
index.html ADDED
@@ -0,0 +1,582 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en-us">
3
+
4
+ <head>
5
+ <title>whisper.cpp : WASM example</title>
6
+
7
+ <style>
8
+ body {
9
+ background-color: white;
10
+ }
11
+
12
+ #output {
13
+ width: 100%;
14
+ height: 100%;
15
+ margin: 0 auto;
16
+ margin-top: 10px;
17
+ border-left: 0px;
18
+ border-right: 0px;
19
+ padding-left: 0px;
20
+ padding-right: 0px;
21
+ display: block;
22
+ background-color: black;
23
+ color: white;
24
+ font-size: 10px;
25
+ font-family: 'Lucida Console', Monaco, monospace;
26
+ outline: none;
27
+ white-space: pre;
28
+ overflow-wrap: normal;
29
+ overflow-x: scroll;
30
+ }
31
+ </style>
32
+ </head>
33
+
34
+ <body>
35
+ <div id="main-container">
36
+ <div id="warning" style="display: none; padding: 1rem;">
37
+ <b style="color: red ; font-size: large;">Warning: your browser does not support SharedArrayBuffer please
38
+ try open the page in a new tab.
39
+ </b> <a href="https://radames-whisper-wasm.hf.space"
40
+ target="_blank">https://radames-whisper-wasm.hf.space</a>
41
+ </div>
42
+ <b>Minimal <a target="_blank" href="https://github.com/ggerganov/whisper.cpp">whisper.cpp</a> example running
43
+ fully in the browser</b>
44
+
45
+ <br><br>
46
+
47
+ Usage instructions:<br>
48
+ <ul>
49
+ <li>Load a ggml model file (you can obtain one from <a target="_blank"
50
+ href="https://ggml.ggerganov.com/">here</a>, recommended: <b>tiny</b> or <b>base</b>)</li>
51
+ <li>Select audio file to transcribe or record audio from the microphone (sample: <a target="_blank"
52
+ href="https://whisper.ggerganov.com/jfk.wav">jfk.wav</a>)</li>
53
+ <li>Click on the "Transcribe" button to start the transcription</li>
54
+ </ul>
55
+
56
+ Note that the computation is quite heavy and may take a few seconds to complete.<br>
57
+ The transcription results will be displayed in the text area below.<br><br>
58
+ <b>Important: your browser must support WASM SIMD instructions for this to work.</b>
59
+
60
+ <br><br>
61
+ <hr>
62
+
63
+ <div id="model">
64
+ Whisper model: <span id="model-whisper-status"></span>
65
+ <button id="fetch-whisper-tiny-en" onclick="loadWhisper('tiny.en')">tiny.en (75 MB)</button>
66
+ <button id="fetch-whisper-tiny" onclick="loadWhisper('tiny')">tiny (75 MB)</button>
67
+ <button id="fetch-whisper-base-en" onclick="loadWhisper('base.en')">base.en (142 MB)</button>
68
+ <button id="fetch-whisper-base" onclick="loadWhisper('base')">base (142 MB)</button>
69
+ <span id="fetch-whisper-progress"></span>
70
+
71
+ <input type="file" id="whisper-file" name="file" onchange="loadFile(event, 'whisper.bin')" />
72
+ </div>
73
+
74
+ <br>
75
+
76
+ <!-- radio button to select between file upload or microphone -->
77
+ <div id="input">
78
+ Input:
79
+ <input type="radio" id="file" name="input" value="file" checked="checked" onchange="changeInput('file')" />
80
+ File
81
+ <input type="radio" id="mic" name="input" value="mic" onchange="changeInput('mic')" /> Microphone
82
+ </div>
83
+
84
+ <br>
85
+
86
+ <div id="input_file">
87
+ Audio file:
88
+ <input type="file" id="file" name="file" onchange="loadAudio(event)" />
89
+ </div>
90
+
91
+ <div id="input_mic" style="display: none;">
92
+ Microphone:
93
+ <button id="start" onclick="startRecording()">Start</button>
94
+ <button id="stop" onclick="stopRecording()" disabled>Stop</button>
95
+
96
+ <!-- progress bar to show recording progress -->
97
+ <br><br>
98
+ <div id="progress" style="display: none;">
99
+ <div id="progress-bar" style="width: 0%; height: 10px; background-color: #4CAF50;"></div>
100
+ <div id="progress-text">0%</div>
101
+ </div>
102
+ </div>
103
+
104
+ <audio controls="controls" id="audio" loop hidden>
105
+ Your browser does not support the &lt;audio&gt; tag.
106
+ <source id="source" src="" type="audio/wav" />
107
+ </audio>
108
+
109
+ <hr><br>
110
+
111
+ <table>
112
+ <tr>
113
+ <td>
114
+ Language:
115
+ <select id="language" name="language">
116
+ <option value="en">English</option>
117
+ <option value="ar">Arabic</option>
118
+ <option value="hy">Armenian</option>
119
+ <option value="az">Azerbaijani</option>
120
+ <option value="eu">Basque</option>
121
+ <option value="be">Belarusian</option>
122
+ <option value="bn">Bengali</option>
123
+ <option value="bg">Bulgarian</option>
124
+ <option value="ca">Catalan</option>
125
+ <option value="zh">Chinese</option>
126
+ <option value="hr">Croatian</option>
127
+ <option value="cs">Czech</option>
128
+ <option value="da">Danish</option>
129
+ <option value="nl">Dutch</option>
130
+ <option value="en">English</option>
131
+ <option value="et">Estonian</option>
132
+ <option value="tl">Filipino</option>
133
+ <option value="fi">Finnish</option>
134
+ <option value="fr">French</option>
135
+ <option value="gl">Galician</option>
136
+ <option value="ka">Georgian</option>
137
+ <option value="de">German</option>
138
+ <option value="el">Greek</option>
139
+ <option value="gu">Gujarati</option>
140
+ <option value="iw">Hebrew</option>
141
+ <option value="hi">Hindi</option>
142
+ <option value="hu">Hungarian</option>
143
+ <option value="is">Icelandic</option>
144
+ <option value="id">Indonesian</option>
145
+ <option value="ga">Irish</option>
146
+ <option value="it">Italian</option>
147
+ <option value="ja">Japanese</option>
148
+ <option value="kn">Kannada</option>
149
+ <option value="ko">Korean</option>
150
+ <option value="la">Latin</option>
151
+ <option value="lv">Latvian</option>
152
+ <option value="lt">Lithuanian</option>
153
+ <option value="mk">Macedonian</option>
154
+ <option value="ms">Malay</option>
155
+ <option value="mt">Maltese</option>
156
+ <option value="no">Norwegian</option>
157
+ <option value="fa">Persian</option>
158
+ <option value="pl">Polish</option>
159
+ <option value="pt">Portuguese</option>
160
+ <option value="ro">Romanian</option>
161
+ <option value="ru">Russian</option>
162
+ <option value="sr">Serbian</option>
163
+ <option value="sk">Slovak</option>
164
+ <option value="sl">Slovenian</option>
165
+ <option value="es">Spanish</option>
166
+ <option value="sw">Swahili</option>
167
+ <option value="sv">Swedish</option>
168
+ <option value="ta">Tamil</option>
169
+ <option value="te">Telugu</option>
170
+ <option value="th">Thai</option>
171
+ <option value="tr">Turkish</option>
172
+ <option value="uk">Ukrainian</option>
173
+ <option value="ur">Urdu</option>
174
+ <option value="vi">Vietnamese</option>
175
+ <option value="cy">Welsh</option>
176
+ <option value="yi">Yiddish</option>
177
+ </select>
178
+ </td>
179
+ <td>
180
+ <button onclick="onProcess(false);">Transcribe</button>
181
+ </td>
182
+ <td>
183
+ <button onclick="onProcess(true);">Translate</button>
184
+ </td>
185
+ </tr>
186
+ </table>
187
+
188
+ <br>
189
+
190
+ <!-- textarea with height filling the rest of the page -->
191
+ <textarea id="output" rows="20"></textarea>
192
+
193
+ <br><br>
194
+
195
+ <div class="cell-version">
196
+ <span>
197
+ |
198
+ Build time: <span class="nav-link">Mon Jan 16 11:57:35 2023</span> |
199
+ Commit hash: <a class="nav-link" target="_blank"
200
+ href="https://github.com/ggerganov/whisper.cpp/commit/49b529ba">49b529ba</a> |
201
+ Commit subject: <span class="nav-link">whisper.android : add support for loading directly from asset in
202
+ C (#415)</span> |
203
+ <a class="nav-link" target="_blank"
204
+ href="https://github.com/ggerganov/whisper.cpp/tree/master/examples/whisper.wasm">Source Code</a> |
205
+ </span>
206
+ </div>
207
+ </div>
208
+
209
+ <script type="text/javascript" src="helpers.js"></script>
210
+ <script type='text/javascript'>
211
+ document.addEventListener("DOMContentLoaded", () => {
212
+ //check is shared array buffer is supported
213
+ if (!window.SharedArrayBuffer) {
214
+ document.querySelector("#warning").style.display = "block";
215
+ }
216
+ })
217
+ // TODO: convert audio buffer to WAV
218
+ function setAudio(audio) {
219
+ //if (audio) {
220
+ // // convert to 16-bit PCM
221
+ // var blob = new Blob([audio], { type: 'audio/wav' });
222
+ // var url = URL.createObjectURL(blob);
223
+ // document.getElementById('source').src = url;
224
+ // document.getElementById('audio').hidden = false;
225
+ // document.getElementById('audio').loop = false;
226
+ // document.getElementById('audio').load();
227
+ //} else {
228
+ // document.getElementById('audio').hidden = true;
229
+ //}
230
+ }
231
+
232
+ function changeInput(input) {
233
+ if (input == 'file') {
234
+ document.getElementById('input_file').style.display = 'block';
235
+ document.getElementById('input_mic').style.display = 'none';
236
+ document.getElementById('progress').style.display = 'none';
237
+ } else {
238
+ document.getElementById('input_file').style.display = 'none';
239
+ document.getElementById('input_mic').style.display = 'block';
240
+ document.getElementById('progress').style.display = 'block';
241
+ }
242
+ }
243
+
244
+ var Module = {
245
+ print: printTextarea,
246
+ printErr: printTextarea,
247
+ setStatus: function (text) {
248
+ printTextarea('js: ' + text);
249
+ },
250
+ monitorRunDependencies: function (left) {
251
+ }
252
+ };
253
+
254
+ // web audio context
255
+ var context = null;
256
+
257
+ // audio data
258
+ var audio = null;
259
+
260
+ // the whisper instance
261
+ var instance = null;
262
+ var model_whisper = '';
263
+
264
+ // helper function
265
+ function convertTypedArray(src, type) {
266
+ var buffer = new ArrayBuffer(src.byteLength);
267
+ var baseView = new src.constructor(buffer).set(src);
268
+ return new type(buffer);
269
+ }
270
+
271
+ //
272
+ // load model
273
+ //
274
+
275
+ let dbVersion = 1
276
+ let dbName = 'whisper.ggerganov.com';
277
+ let indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB
278
+
279
+ function storeFS(fname, buf) {
280
+ // write to WASM file using FS_createDataFile
281
+ // if the file exists, delete it
282
+ try {
283
+ Module.FS_unlink(fname);
284
+ } catch (e) {
285
+ // ignore
286
+ }
287
+
288
+ Module.FS_createDataFile("/", fname, buf, true, true);
289
+
290
+ model_whisper = fname;
291
+
292
+ document.getElementById('model-whisper-status').innerHTML = 'loaded "' + model_whisper + '"!';
293
+
294
+ printTextarea('storeFS: stored model: ' + fname + ' size: ' + buf.length);
295
+ }
296
+
297
+ function loadFile(event, fname) {
298
+ var file = event.target.files[0] || null;
299
+ if (file == null) {
300
+ return;
301
+ }
302
+
303
+ printTextarea("loadFile: loading model: " + file.name + ", size: " + file.size + " bytes");
304
+ printTextarea('loadFile: please wait ...');
305
+
306
+ var reader = new FileReader();
307
+ reader.onload = function (event) {
308
+ var buf = new Uint8Array(reader.result);
309
+ storeFS(fname, buf);
310
+ }
311
+ reader.readAsArrayBuffer(file);
312
+
313
+ document.getElementById('fetch-whisper-tiny-en').style.display = 'none';
314
+ document.getElementById('fetch-whisper-base-en').style.display = 'none';
315
+ document.getElementById('fetch-whisper-tiny').style.display = 'none';
316
+ document.getElementById('fetch-whisper-base').style.display = 'none';
317
+ document.getElementById('whisper-file').style.display = 'none';
318
+ document.getElementById('model-whisper-status').innerHTML = 'loaded model: ' + file.name;
319
+ }
320
+
321
+ function loadWhisper(model) {
322
+ let urls = {
323
+ 'tiny.en': 'models/ggml-tiny.en.bin',
324
+ 'tiny': 'models/ggml-tiny.bin',
325
+ 'base.en': 'models/ggml-base.en.bin',
326
+ 'base': 'models/ggml-base.bin',
327
+ };
328
+
329
+ let sizes = {
330
+ 'tiny.en': 75,
331
+ 'tiny': 75,
332
+ 'base.en': 142,
333
+ 'base': 142,
334
+ };
335
+
336
+ let url = urls[model];
337
+ let dst = 'whisper.bin';
338
+ let size_mb = sizes[model];
339
+
340
+ model_whisper = model;
341
+
342
+ document.getElementById('fetch-whisper-tiny-en').style.display = 'none';
343
+ document.getElementById('fetch-whisper-base-en').style.display = 'none';
344
+ document.getElementById('fetch-whisper-tiny').style.display = 'none';
345
+ document.getElementById('fetch-whisper-base').style.display = 'none';
346
+ document.getElementById('whisper-file').style.display = 'none';
347
+ document.getElementById('model-whisper-status').innerHTML = 'loading model: ' + model;
348
+
349
+ cbProgress = function (p) {
350
+ let el = document.getElementById('fetch-whisper-progress');
351
+ el.innerHTML = Math.round(100 * p) + '%';
352
+ };
353
+
354
+ cbCancel = function () {
355
+ var el;
356
+ el = document.getElementById('fetch-whisper-tiny-en'); if (el) el.style.display = 'inline-block';
357
+ el = document.getElementById('fetch-whisper-base-en'); if (el) el.style.display = 'inline-block';
358
+ el = document.getElementById('fetch-whisper-tiny'); if (el) el.style.display = 'inline-block';
359
+ el = document.getElementById('fetch-whisper-base'); if (el) el.style.display = 'inline-block';
360
+ el = document.getElementById('whisper-file'); if (el) el.style.display = 'inline-block';
361
+ el = document.getElementById('model-whisper-status'); if (el) el.innerHTML = '';
362
+ };
363
+
364
+ loadRemote(url, dst, size_mb, cbProgress, storeFS, cbCancel, printTextarea);
365
+ }
366
+
367
+ //
368
+ // audio file
369
+ //
370
+
371
+ const kMaxAudio_s = 120;
372
+ const kSampleRate = 16000;
373
+
374
+ window.AudioContext = window.AudioContext || window.webkitAudioContext;
375
+ window.OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;
376
+
377
+ function loadAudio(event) {
378
+ if (!context) {
379
+ context = new AudioContext({
380
+ sampleRate: kSampleRate,
381
+ channelCount: 1,
382
+ echoCancellation: false,
383
+ autoGainControl: true,
384
+ noiseSuppression: true,
385
+ });
386
+ }
387
+
388
+ var file = event.target.files[0] || null;
389
+ if (file == null) {
390
+ return;
391
+ }
392
+
393
+ printTextarea('js: loading audio: ' + file.name + ', size: ' + file.size + ' bytes');
394
+ printTextarea('js: please wait ...');
395
+
396
+ var reader = new FileReader();
397
+ reader.onload = function (event) {
398
+ var buf = new Uint8Array(reader.result);
399
+
400
+ context.decodeAudioData(buf.buffer, function (audioBuffer) {
401
+ var offlineContext = new OfflineAudioContext(audioBuffer.numberOfChannels, audioBuffer.length, audioBuffer.sampleRate);
402
+ var source = offlineContext.createBufferSource();
403
+ source.buffer = audioBuffer;
404
+ source.connect(offlineContext.destination);
405
+ source.start(0);
406
+
407
+ offlineContext.startRendering().then(function (renderedBuffer) {
408
+ audio = renderedBuffer.getChannelData(0);
409
+ printTextarea('js: audio loaded, size: ' + audio.length);
410
+
411
+ // truncate to first 30 seconds
412
+ if (audio.length > kMaxAudio_s * kSampleRate) {
413
+ audio = audio.slice(0, kMaxAudio_s * kSampleRate);
414
+ printTextarea('js: truncated audio to first ' + kMaxAudio_s + ' seconds');
415
+ }
416
+
417
+ setAudio(audio);
418
+ });
419
+ }, function (e) {
420
+ printTextarea('js: error decoding audio: ' + e);
421
+ audio = null;
422
+ setAudio(audio);
423
+ });
424
+ }
425
+ reader.readAsArrayBuffer(file);
426
+ }
427
+
428
+ //
429
+ // microphone
430
+ //
431
+
432
+ var mediaRecorder = null;
433
+ var doRecording = false;
434
+ var startTime = 0;
435
+
436
+ function stopRecording() {
437
+ doRecording = false;
438
+ }
439
+
440
+ // record up to kMaxAudio_s seconds of audio from the microphone
441
+ // check if doRecording is false every 1000 ms and stop recording if so
442
+ // update progress information
443
+ function startRecording() {
444
+ if (!context) {
445
+ context = new AudioContext({
446
+ sampleRate: kSampleRate,
447
+ channelCount: 1,
448
+ echoCancellation: false,
449
+ autoGainControl: true,
450
+ noiseSuppression: true,
451
+ });
452
+ }
453
+
454
+ document.getElementById('start').disabled = true;
455
+ document.getElementById('stop').disabled = false;
456
+
457
+ document.getElementById('progress-bar').style.width = '0%';
458
+ document.getElementById('progress-text').innerHTML = '0%';
459
+
460
+ doRecording = true;
461
+ startTime = Date.now();
462
+
463
+ var chunks = [];
464
+ var stream = null;
465
+
466
+ navigator.mediaDevices.getUserMedia({ audio: true, video: false })
467
+ .then(function (s) {
468
+ stream = s;
469
+ mediaRecorder = new MediaRecorder(stream);
470
+ mediaRecorder.ondataavailable = function (e) {
471
+ chunks.push(e.data);
472
+ };
473
+ mediaRecorder.onstop = function (e) {
474
+ var blob = new Blob(chunks, { 'type': 'audio/ogg; codecs=opus' });
475
+ chunks = [];
476
+
477
+ document.getElementById('start').disabled = false;
478
+ document.getElementById('stop').disabled = true;
479
+
480
+ var reader = new FileReader();
481
+ reader.onload = function (event) {
482
+ var buf = new Uint8Array(reader.result);
483
+
484
+ context.decodeAudioData(buf.buffer, function (audioBuffer) {
485
+ var offlineContext = new OfflineAudioContext(audioBuffer.numberOfChannels, audioBuffer.length, audioBuffer.sampleRate);
486
+ var source = offlineContext.createBufferSource();
487
+ source.buffer = audioBuffer;
488
+ source.connect(offlineContext.destination);
489
+ source.start(0);
490
+
491
+ offlineContext.startRendering().then(function (renderedBuffer) {
492
+ audio = renderedBuffer.getChannelData(0);
493
+ printTextarea('js: audio recorded, size: ' + audio.length);
494
+
495
+ // truncate to first 30 seconds
496
+ if (audio.length > kMaxAudio_s * kSampleRate) {
497
+ audio = audio.slice(0, kMaxAudio_s * kSampleRate);
498
+ printTextarea('js: truncated audio to first ' + kMaxAudio_s + ' seconds');
499
+ }
500
+ setAudio(audio);
501
+ });
502
+ }, function (e) {
503
+ printTextarea('js: error decoding audio: ' + e);
504
+ audio = null;
505
+ setAudio(audio);
506
+ });
507
+ }
508
+
509
+ reader.readAsArrayBuffer(blob);
510
+ };
511
+ mediaRecorder.start();
512
+ })
513
+ .catch(function (err) {
514
+ printTextarea('js: error getting audio stream: ' + err);
515
+ });
516
+
517
+ var interval = setInterval(function () {
518
+ if (!doRecording) {
519
+ clearInterval(interval);
520
+ mediaRecorder.stop();
521
+ stream.getTracks().forEach(function (track) {
522
+ track.stop();
523
+ });
524
+ }
525
+
526
+ document.getElementById('progress-bar').style.width = (100 * (Date.now() - startTime) / 1000 / kMaxAudio_s) + '%';
527
+ document.getElementById('progress-text').innerHTML = (100 * (Date.now() - startTime) / 1000 / kMaxAudio_s).toFixed(0) + '%';
528
+ }, 1000);
529
+
530
+ printTextarea('js: recording ...');
531
+
532
+ setTimeout(function () {
533
+ if (doRecording) {
534
+ printTextarea('js: recording stopped after ' + kMaxAudio_s + ' seconds');
535
+ stopRecording();
536
+ }
537
+ }, kMaxAudio_s * 1000);
538
+ }
539
+
540
+ //
541
+ // transcribe
542
+ //
543
+
544
+ function onProcess(translate) {
545
+ if (!instance) {
546
+ instance = Module.init('whisper.bin');
547
+
548
+ if (instance) {
549
+ printTextarea("js: whisper initialized, instance: " + instance);
550
+ document.getElementById('model').innerHTML = 'Model loaded: ' + model_whisper;
551
+ }
552
+ }
553
+
554
+ if (!instance) {
555
+ printTextarea("js: failed to initialize whisper");
556
+ return;
557
+ }
558
+
559
+ if (!audio) {
560
+ printTextarea("js: no audio data");
561
+ return;
562
+ }
563
+
564
+ if (instance) {
565
+ printTextarea('');
566
+ printTextarea('js: processing - this might take a while ...');
567
+ printTextarea('');
568
+
569
+ setTimeout(function () {
570
+ var ret = Module.full_default(instance, audio, document.getElementById('language').value, translate);
571
+ console.log('js: full_default returned: ' + ret);
572
+ if (ret) {
573
+ printTextarea("js: whisper returned: " + ret);
574
+ }
575
+ }, 100);
576
+ }
577
+ }
578
+ </script>
579
+ <script type="text/javascript" src="main.js"></script>
580
+ </body>
581
+
582
+ </html>
libmain.worker.js ADDED
@@ -0,0 +1 @@
 
 
1
+ "use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",data=>onmessage({data:data}));var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,"utf8")+"//# sourceURL="+f)},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;var pendingNotifiedProxyingQueues=[];function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=function(){postMessage({cmd:"callHandler",handler:handler,args:[...arguments]})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();pendingNotifiedProxyingQueues.forEach(queue=>{Module["executeNotifiedProxyingQueue"](queue)});pendingNotifiedProxyingQueues=[];initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processProxyingQueue"){if(initializedJS){Module["executeNotifiedProxyingQueue"](e.data.queue)}else{pendingNotifiedProxyingQueues.push(e.data.queue)}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage;
libwhisper.worker.js ADDED
@@ -0,0 +1 @@
 
 
1
+ "use strict";var Module={};var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require("worker_threads");var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",data=>onmessage({data:data}));var fs=require("fs");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,"utf8")+"//# sourceURL="+f)},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;var pendingNotifiedProxyingQueues=[];function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+"\n");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=function(){postMessage({cmd:"callHandler",handler:handler,args:[...arguments]})}}Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob=="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}whisper_factory(Module)}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();pendingNotifiedProxyingQueues.forEach(queue=>{Module["executeNotifiedProxyingQueue"](queue)});pendingNotifiedProxyingQueues=[];initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processProxyingQueue"){if(initializedJS){Module["executeNotifiedProxyingQueue"](e.data.queue)}else{pendingNotifiedProxyingQueues.push(e.data.queue)}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage;
main.js ADDED
The diff for this file is too large to render. See raw diff
 
models/.gitattributes ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ftz filter=lfs diff=lfs merge=lfs -text
6
+ *.gz filter=lfs diff=lfs merge=lfs -text
7
+ *.h5 filter=lfs diff=lfs merge=lfs -text
8
+ *.joblib filter=lfs diff=lfs merge=lfs -text
9
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
10
+ *.lz4 filter=lfs diff=lfs merge=lfs -text
11
+ *.model filter=lfs diff=lfs merge=lfs -text
12
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
13
+ *.npy filter=lfs diff=lfs merge=lfs -text
14
+ *.npz filter=lfs diff=lfs merge=lfs -text
15
+ *.onnx filter=lfs diff=lfs merge=lfs -text
16
+ *.ot filter=lfs diff=lfs merge=lfs -text
17
+ *.parquet filter=lfs diff=lfs merge=lfs -text
18
+ *.pb filter=lfs diff=lfs merge=lfs -text
19
+ *.pickle filter=lfs diff=lfs merge=lfs -text
20
+ *.pkl filter=lfs diff=lfs merge=lfs -text
21
+ *.pt filter=lfs diff=lfs merge=lfs -text
22
+ *.pth filter=lfs diff=lfs merge=lfs -text
23
+ *.rar filter=lfs diff=lfs merge=lfs -text
24
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
25
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
26
+ *.tflite filter=lfs diff=lfs merge=lfs -text
27
+ *.tgz filter=lfs diff=lfs merge=lfs -text
28
+ *.wasm filter=lfs diff=lfs merge=lfs -text
29
+ *.xz filter=lfs diff=lfs merge=lfs -text
30
+ *.zip filter=lfs diff=lfs merge=lfs -text
31
+ *.zst filter=lfs diff=lfs merge=lfs -text
32
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
33
+ # Audio files - uncompressed
34
+ *.pcm filter=lfs diff=lfs merge=lfs -text
35
+ *.sam filter=lfs diff=lfs merge=lfs -text
36
+ *.raw filter=lfs diff=lfs merge=lfs -text
37
+ # Audio files - compressed
38
+ *.aac filter=lfs diff=lfs merge=lfs -text
39
+ *.flac filter=lfs diff=lfs merge=lfs -text
40
+ *.mp3 filter=lfs diff=lfs merge=lfs -text
41
+ *.ogg filter=lfs diff=lfs merge=lfs -text
42
+ *.wav filter=lfs diff=lfs merge=lfs -text
43
+ # Image files - uncompressed
44
+ *.bmp filter=lfs diff=lfs merge=lfs -text
45
+ *.gif filter=lfs diff=lfs merge=lfs -text
46
+ *.png filter=lfs diff=lfs merge=lfs -text
47
+ *.tiff filter=lfs diff=lfs merge=lfs -text
48
+ # Image files - compressed
49
+ *.jpg filter=lfs diff=lfs merge=lfs -text
50
+ *.jpeg filter=lfs diff=lfs merge=lfs -text
51
+ *.webp filter=lfs diff=lfs merge=lfs -text
models/README.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ ---
4
+
5
+ # OpenAI's Whisper models converted to ggml format
6
+
7
+ [Available models](https://huggingface.co/datasets/ggerganov/whisper.cpp/tree/main)
8
+
9
+ | Model | Disk | Mem | SHA |
10
+ | --- | --- | --- | --- |
11
+ | tiny | 75 MB | ~390 MB | `bd577a113a864445d4c299885e0cb97d4ba92b5f` |
12
+ | tiny.en | 75 MB | ~390 MB | `c78c86eb1a8faa21b369bcd33207cc90d64ae9df` |
13
+ | base | 142 MB | ~500 MB | `465707469ff3a37a2b9b8d8f89f2f99de7299dac` |
14
+ | base.en | 142 MB | ~500 MB | `137c40403d78fd54d454da0f9bd998f78703390c` |
15
+ | small | 466 MB | ~1.0 GB | `55356645c2b361a969dfd0ef2c5a50d530afd8d5` |
16
+ | small.en | 466 MB | ~1.0 GB | `db8a495a91d927739e50b3fc1cc4c6b8f6c2d022` |
17
+ | medium | 1.5 GB | ~2.6 GB | `fd9727b6e1217c2f614f9b698455c4ffd82463b4` |
18
+ | medium.en | 1.5 GB | ~2.6 GB | `8c30f0e44ce9560643ebd10bbe50cd20eafd3723` |
19
+ | large-v1 | 2.9 GB | ~4.7 GB | `b1caaf735c4cc1429223d5a74f0f4d0b9b59a299` |
20
+ | large | 2.9 GB | ~4.7 GB | `0f4c8e34f21cf1a914c59d8b3ce882345ad349d6` |
21
+
22
+ For more information, visit:
23
+
24
+ https://github.com/ggerganov/whisper.cpp/tree/master/models
models/ggml-base.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:60ed5bc3dd14eea856493d334349b405782ddcaf0028d4b5df4088345fba2efe
3
+ size 147951465
models/ggml-base.en.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a03779c86df3323075f5e796cb2ce5029f00ec8869eee3fdfb897afe36c6d002
3
+ size 147964211
models/ggml-tiny.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:be07e048e1e599ad46341c8d2a135645097a538221678b7acdd1b1919c6e1b21
3
+ size 77691713
models/ggml-tiny.en.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:921e4cf8686fdd993dcd081a5da5b6c365bfde1162e72b08d75ac75289920b1f
3
+ size 77704715
nginx.conf ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ server {
2
+ listen 8080;
3
+ listen [::]:8080;
4
+ server_name localhost;
5
+
6
+ #access_log /var/log/nginx/host.access.log main;
7
+
8
+ location / {
9
+ root /usr/share/nginx/html;
10
+ index index.html index.htm;
11
+
12
+ add_header 'Cross-Origin-Embedder-Policy' 'require-corp';
13
+ add_header 'Cross-Origin-Opener-Policy' 'same-origin';
14
+ add_header 'Cross-Origin-Resource-Policy' 'cross-origin';
15
+
16
+ }
17
+ #error_page 404 /404.html;
18
+
19
+ }
style.css ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ padding: 2rem;
3
+ font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
+ }
5
+
6
+ h1 {
7
+ font-size: 16px;
8
+ margin-top: 0;
9
+ }
10
+
11
+ p {
12
+ color: rgb(107, 114, 128);
13
+ font-size: 15px;
14
+ margin-bottom: 10px;
15
+ margin-top: 5px;
16
+ }
17
+
18
+ .card {
19
+ max-width: 620px;
20
+ margin: 0 auto;
21
+ padding: 16px;
22
+ border: 1px solid lightgray;
23
+ border-radius: 16px;
24
+ }
25
+
26
+ .card p:last-child {
27
+ margin-bottom: 0;
28
+ }