whispermix 1.4.8 → 1.4.12
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/demo/local.js +3 -1
- package/index.js +41 -7
- package/package.json +56 -52
- package/pnpm-workspace.yaml +5 -0
package/demo/local.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import WhisperMix from '../index.js';
|
|
2
2
|
|
|
3
3
|
const whisperLocal = new WhisperMix({
|
|
4
|
-
model: 'xenova/whisper-large-v3'
|
|
4
|
+
model: 'xenova/whisper-large-v3',
|
|
5
|
+
showProgress: true,
|
|
6
|
+
language: 'spanish',
|
|
5
7
|
});
|
|
6
8
|
|
|
7
9
|
const r = await whisperLocal.fromFile('conversation.wav');
|
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { getAudioDurationInSeconds } from 'get-audio-duration';
|
|
|
6
6
|
import os from 'os'; // For temporary directory
|
|
7
7
|
|
|
8
8
|
// Static imports for local dependencies
|
|
9
|
-
import { pipeline } from '@
|
|
9
|
+
import { pipeline, env } from '@huggingface/transformers';
|
|
10
10
|
import audioDecode from 'audio-decode';
|
|
11
11
|
|
|
12
12
|
class WhisperMix {
|
|
@@ -35,10 +35,12 @@ class WhisperMix {
|
|
|
35
35
|
'xenova/whisper-large-v3': {
|
|
36
36
|
local: true,
|
|
37
37
|
modelName: 'Xenova/whisper-large-v3',
|
|
38
|
+
dtype: 'q8',
|
|
38
39
|
},
|
|
39
40
|
'xenova/whisper-base': {
|
|
40
41
|
local: true,
|
|
41
42
|
modelName: 'Xenova/whisper-base',
|
|
43
|
+
dtype: 'q8',
|
|
42
44
|
},
|
|
43
45
|
};
|
|
44
46
|
|
|
@@ -52,6 +54,9 @@ class WhisperMix {
|
|
|
52
54
|
this.apiUrl = this.config.url;
|
|
53
55
|
this.isLocal = this.config.local || false;
|
|
54
56
|
this.modelName = this.config.modelName;
|
|
57
|
+
this.dtype = this.dtype || this.config.dtype;
|
|
58
|
+
this.showProgress = this.showProgress || false;
|
|
59
|
+
this.transcriber = null;
|
|
55
60
|
|
|
56
61
|
this.limiter = new Bottleneck(this.bottleneck);
|
|
57
62
|
}
|
|
@@ -150,6 +155,9 @@ class WhisperMix {
|
|
|
150
155
|
const formData = new FormData();
|
|
151
156
|
formData.append('file', blob, 'audio.mp3');
|
|
152
157
|
formData.append('model', this.modelName);
|
|
158
|
+
if (this.language) {
|
|
159
|
+
formData.append('language', this.language);
|
|
160
|
+
}
|
|
153
161
|
|
|
154
162
|
const response = await fetch(this.apiUrl, {
|
|
155
163
|
method: 'POST',
|
|
@@ -201,20 +209,46 @@ class WhisperMix {
|
|
|
201
209
|
audioData = resampledData;
|
|
202
210
|
}
|
|
203
211
|
|
|
204
|
-
//
|
|
205
|
-
const transcriber = await
|
|
212
|
+
// Reuse a single pipeline instance so repeated calls don't re-download/re-initialize.
|
|
213
|
+
const transcriber = await this._getLocalTranscriber();
|
|
206
214
|
|
|
207
215
|
// Pass the processed audio data
|
|
208
|
-
const
|
|
209
|
-
language: this.language,
|
|
216
|
+
const transcriberOptions = {
|
|
210
217
|
task: 'transcribe',
|
|
211
|
-
}
|
|
218
|
+
};
|
|
219
|
+
if (this.language !== undefined) {
|
|
220
|
+
transcriberOptions.language = this.language;
|
|
221
|
+
}
|
|
222
|
+
const result = await transcriber(audioData, transcriberOptions);
|
|
212
223
|
|
|
213
224
|
return result.text.trim();
|
|
214
225
|
} catch (error) {
|
|
215
|
-
throw new Error(`Local transcription failed: ${error.message}
|
|
226
|
+
throw new Error(`Local transcription failed: ${error.message}. If this happened after an interrupted download, remove the model cache at ${env.cacheDir}${this.modelName}/ and try again.`);
|
|
216
227
|
}
|
|
217
228
|
}
|
|
229
|
+
|
|
230
|
+
async _getLocalTranscriber() {
|
|
231
|
+
if (!this.transcriber) {
|
|
232
|
+
const options = {};
|
|
233
|
+
if (this.dtype) {
|
|
234
|
+
options.dtype = this.dtype;
|
|
235
|
+
}
|
|
236
|
+
if (this.showProgress) {
|
|
237
|
+
options.progress_callback = (event) => {
|
|
238
|
+
if (!event || !event.status) return;
|
|
239
|
+
if (event.file && typeof event.progress === 'number') {
|
|
240
|
+
console.log(`[WhisperMix] ${event.status} ${event.file} ${event.progress.toFixed(1)}%`);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
console.log(`[WhisperMix] ${event.status}`);
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
this.transcriber = pipeline('automatic-speech-recognition', this.modelName, options);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return this.transcriber;
|
|
251
|
+
}
|
|
218
252
|
}
|
|
219
253
|
|
|
220
254
|
// Support both CommonJS and ES modules
|
package/package.json
CHANGED
|
@@ -1,53 +1,57 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
2
|
+
"name": "whispermix",
|
|
3
|
+
"description": "🎙️ WhisperMix is a versatile module for transcribing audio using OpenAI’s Whisper or Groq’s Whisper v3 model.",
|
|
4
|
+
"version": "1.4.12",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"whisper",
|
|
8
|
+
"openai",
|
|
9
|
+
"groq",
|
|
10
|
+
"transcription",
|
|
11
|
+
"speech-to-text",
|
|
12
|
+
"audio",
|
|
13
|
+
"voice",
|
|
14
|
+
"ai",
|
|
15
|
+
"machine-learning",
|
|
16
|
+
"nlp",
|
|
17
|
+
"natural-language-processing",
|
|
18
|
+
"audio-processing",
|
|
19
|
+
"voice-recognition",
|
|
20
|
+
"speech-recognition",
|
|
21
|
+
"api-wrapper",
|
|
22
|
+
"whisper-large-v3",
|
|
23
|
+
"whisper-1",
|
|
24
|
+
"streaming",
|
|
25
|
+
"file-processing",
|
|
26
|
+
"multilingual",
|
|
27
|
+
"bottleneck",
|
|
28
|
+
"chunk",
|
|
29
|
+
"clasen",
|
|
30
|
+
"local",
|
|
31
|
+
"xenova"
|
|
32
|
+
],
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/clasen/WhisperMix.git"
|
|
36
|
+
},
|
|
37
|
+
"main": "index.js",
|
|
38
|
+
"author": "Martin Clasen",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/clasen/WhisperMix/issues"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@huggingface/transformers": "^4.2.0",
|
|
45
|
+
"audio-decode": "^2.2.3",
|
|
46
|
+
"bottleneck": "^2.19.5",
|
|
47
|
+
"fluent-ffmpeg": "^2.1.3",
|
|
48
|
+
"get-audio-duration": "^4.0.1"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"node-addon-api": "^8.7.0",
|
|
52
|
+
"node-gyp": "^12.3.0"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
56
|
+
}
|
|
57
|
+
}
|