@wovin/tranz 0.1.11 → 0.1.15
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/README.md +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.min.js +38 -40
- package/dist/providers.min.js +37 -40
- package/dist/realtime.d.ts +6 -4
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.min.js +374 -21
- package/dist/utils/transcription/providers.d.ts +0 -10
- package/dist/utils/transcription/providers.d.ts.map +1 -1
- package/dist/utils/transcription/realtime.d.ts +48 -3
- package/dist/utils/transcription/realtime.d.ts.map +1 -1
- package/dist/utils/transcription/runtime.d.ts +15 -0
- package/dist/utils/transcription/runtime.d.ts.map +1 -0
- package/dist/utils/transcription/transcribe.d.ts +1 -1
- package/dist/utils/transcription/transcribe.d.ts.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ const transcriber = createMistralTranscriber({
|
|
|
49
49
|
const result = await transcriber.transcribe({
|
|
50
50
|
audioPath: './interview.mp3',
|
|
51
51
|
diarize: true,
|
|
52
|
-
timestamps: '
|
|
52
|
+
timestamps: 'segment'
|
|
53
53
|
})
|
|
54
54
|
|
|
55
55
|
console.log(result.text)
|
|
@@ -137,7 +137,7 @@ const result = await mistral.transcribe({
|
|
|
137
137
|
apiKey: process.env.MISTRAL_API_KEY,
|
|
138
138
|
model: 'voxtral-mini-latest',
|
|
139
139
|
diarize: true,
|
|
140
|
-
timestampGranularity: '
|
|
140
|
+
timestampGranularity: 'segment'
|
|
141
141
|
})
|
|
142
142
|
|
|
143
143
|
// Whisper provider (local)
|
|
@@ -264,7 +264,7 @@ Options for the `transcribe()` method:
|
|
|
264
264
|
- `language?: string` - Language code (e.g., 'en', 'fr') - disables word timestamps
|
|
265
265
|
- `model?: string` - Override default model
|
|
266
266
|
- `diarize?: boolean` - Enable speaker diarization (default: true)
|
|
267
|
-
- `timestamps?: 'word' | 'segment'` - Timestamp granularity (default: '
|
|
267
|
+
- `timestamps?: 'word' | 'segment'` - Timestamp granularity (default: 'segment' when diarize is true, disabled if language is set)
|
|
268
268
|
- `autoSplit?: boolean` - Auto-split long audio (default: true)
|
|
269
269
|
- `splitOutputDir?: string` - Directory for split segments (default: system temp)
|
|
270
270
|
- `logger?: TranscribeLogger` - Custom logger
|
package/dist/index.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ export { createProvider, MistralProvider, WhisperProvider, GreenPTProvider, VOXT
|
|
|
5
5
|
export { autoSplitAudio, analyzeSplitPoints, detectSilenceRegions, getAudioDuration, findOptimalSplitPoints, splitAudioAtPoints, DEFAULT_SPLIT_CONFIG, type SplitConfig, type SilenceRegion, type SplitPoint, type AudioSegment, type SplitAnalysis, } from './utils/audio/split.ts';
|
|
6
6
|
export { mergeTranscriptionResults, formatMergedText, type MergedTranscriptionResult, type WordData, } from './utils/audio/merge-results.ts';
|
|
7
7
|
export { formatTranscriptWithPauses } from './utils/transcription/format.ts';
|
|
8
|
+
export { detectAudioMimeType } from './utils/transcription/mime-detection.ts';
|
|
8
9
|
export { createMistralTranscriber, transcribe, type TranscribeOptions, type MistralTranscriberConfig, type MistralTranscriber, } from './utils/transcription/transcribe.ts';
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,GAC3B,MAAM,oCAAoC,CAAA;AAG3C,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAA;AAG/B,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,KAAK,yBAAyB,EAC9B,KAAK,QAAQ,GACd,MAAM,gCAAgC,CAAA;AAGvC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAG5E,OAAO,EACL,wBAAwB,EACxB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,GACxB,MAAM,qCAAqC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EACL,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,GAC3B,MAAM,oCAAoC,CAAA;AAG3C,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAA;AAG/B,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,KAAK,yBAAyB,EAC9B,KAAK,QAAQ,GACd,MAAM,gCAAgC,CAAA;AAGvC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAG5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAA;AAG7E,OAAO,EACL,wBAAwB,EACxB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,GACxB,MAAM,qCAAqC,CAAA"}
|
package/dist/index.min.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
1
5
|
// src/utils/transcription/providers.ts
|
|
2
6
|
import { spawn } from "child_process";
|
|
3
7
|
import * as fs from "fs";
|
|
@@ -57,26 +61,10 @@ function createProvider(providerName, config) {
|
|
|
57
61
|
throw new Error(`Unknown provider: ${providerName}`);
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
|
-
var
|
|
61
|
-
name = "whisper";
|
|
62
|
-
cacheDir;
|
|
63
|
-
static DEFAULTS = {
|
|
64
|
-
DIARIZE: false,
|
|
65
|
-
SILDUR: "1.3",
|
|
66
|
-
SILBUF: 0.2,
|
|
67
|
-
SILTHR: "-35dB",
|
|
68
|
-
MODEL_KEYS: {
|
|
69
|
-
tinyd: "ggml-small.en-tdrz.bin",
|
|
70
|
-
small: "ggml-small.bin",
|
|
71
|
-
medium: "ggml-medium.bin"
|
|
72
|
-
},
|
|
73
|
-
MODELS: {
|
|
74
|
-
tinyd: "https://huggingface.co/akashmjn/tinydiarize-whisper.cpp/resolve/main/ggml-small.en-tdrz.bin",
|
|
75
|
-
small: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin",
|
|
76
|
-
medium: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.bin"
|
|
77
|
-
}
|
|
78
|
-
};
|
|
64
|
+
var _WhisperProvider = class _WhisperProvider {
|
|
79
65
|
constructor(config) {
|
|
66
|
+
__publicField(this, "name", "whisper");
|
|
67
|
+
__publicField(this, "cacheDir");
|
|
80
68
|
this.cacheDir = config?.cacheDir || `${process.env.HOME}/.cache/whisper-models`;
|
|
81
69
|
}
|
|
82
70
|
async transcribe(params) {
|
|
@@ -187,36 +175,44 @@ var WhisperProvider = class _WhisperProvider {
|
|
|
187
175
|
return modelPath;
|
|
188
176
|
}
|
|
189
177
|
};
|
|
178
|
+
__publicField(_WhisperProvider, "DEFAULTS", {
|
|
179
|
+
DIARIZE: false,
|
|
180
|
+
SILDUR: "1.3",
|
|
181
|
+
SILBUF: 0.2,
|
|
182
|
+
SILTHR: "-35dB",
|
|
183
|
+
MODEL_KEYS: {
|
|
184
|
+
tinyd: "ggml-small.en-tdrz.bin",
|
|
185
|
+
small: "ggml-small.bin",
|
|
186
|
+
medium: "ggml-medium.bin"
|
|
187
|
+
},
|
|
188
|
+
MODELS: {
|
|
189
|
+
tinyd: "https://huggingface.co/akashmjn/tinydiarize-whisper.cpp/resolve/main/ggml-small.en-tdrz.bin",
|
|
190
|
+
small: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin",
|
|
191
|
+
medium: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.bin"
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
var WhisperProvider = _WhisperProvider;
|
|
190
195
|
var VOXTRAL_LIMITS = {
|
|
191
196
|
/** Maximum audio duration in seconds (3 hours for Voxtral Transcribe 2) */
|
|
192
197
|
maxAudioDurationSec: 3 * 60 * 60,
|
|
193
198
|
// 10800 seconds = 3 hours
|
|
194
|
-
/** Recommended max duration before splitting (for reliability) */
|
|
195
|
-
recommendedMaxDurationSec: 30 * 60,
|
|
196
|
-
// 30 minutes
|
|
197
199
|
/** Maximum context biasing words/phrases */
|
|
198
200
|
maxContextBiasingTerms: 100,
|
|
199
201
|
/** Maximum file size in bytes (1GB) */
|
|
200
202
|
maxFileSizeBytes: 1024 * 1024 * 1024
|
|
201
203
|
};
|
|
202
204
|
var MistralProvider = class {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
* Check if audio duration exceeds recommended limits
|
|
207
|
-
*/
|
|
208
|
-
static shouldSplit(durationSec) {
|
|
209
|
-
return durationSec > VOXTRAL_LIMITS.recommendedMaxDurationSec;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Get the recommended max segment duration for splitting
|
|
213
|
-
*/
|
|
214
|
-
static getRecommendedMaxSegment() {
|
|
215
|
-
return VOXTRAL_LIMITS.recommendedMaxDurationSec;
|
|
205
|
+
constructor() {
|
|
206
|
+
__publicField(this, "name", "mistral");
|
|
207
|
+
__publicField(this, "maxAudioDurationSec", VOXTRAL_LIMITS.maxAudioDurationSec);
|
|
216
208
|
}
|
|
217
209
|
async transcribe(params) {
|
|
218
210
|
if (params.language && params.timestampGranularity) {
|
|
219
|
-
|
|
211
|
+
throw new Error("Cannot use both language and timestampGranularity (Mistral API limitation)");
|
|
212
|
+
}
|
|
213
|
+
const diarize = params.diarize ?? true;
|
|
214
|
+
if (diarize && params.timestampGranularity === "word") {
|
|
215
|
+
throw new Error('When diarize is set to true, the timestamp granularity must be set to ["segment"], got ["word"]');
|
|
220
216
|
}
|
|
221
217
|
const formData = new FormData();
|
|
222
218
|
if (params.audioUrl) {
|
|
@@ -242,7 +238,6 @@ var MistralProvider = class {
|
|
|
242
238
|
if (params.language) {
|
|
243
239
|
formData.append("language", params.language);
|
|
244
240
|
}
|
|
245
|
-
const diarize = params.diarize ?? true;
|
|
246
241
|
if (diarize) {
|
|
247
242
|
formData.append("diarize", "true");
|
|
248
243
|
}
|
|
@@ -278,7 +273,9 @@ var MistralProvider = class {
|
|
|
278
273
|
}
|
|
279
274
|
};
|
|
280
275
|
var GreenPTProvider = class {
|
|
281
|
-
|
|
276
|
+
constructor() {
|
|
277
|
+
__publicField(this, "name", "greenpt");
|
|
278
|
+
}
|
|
282
279
|
async transcribe(params) {
|
|
283
280
|
if (!params.apiKey) {
|
|
284
281
|
return { text: "", error: "API key is required for GreenPT provider" };
|
|
@@ -866,7 +863,7 @@ function createMistralTranscriber(config) {
|
|
|
866
863
|
language,
|
|
867
864
|
model = defaultModel,
|
|
868
865
|
diarize = true,
|
|
869
|
-
timestamps = language ? void 0 : "
|
|
866
|
+
timestamps = language ? void 0 : "segment",
|
|
870
867
|
autoSplit,
|
|
871
868
|
splitOutputDir,
|
|
872
869
|
logger: customLogger,
|
|
@@ -874,7 +871,7 @@ function createMistralTranscriber(config) {
|
|
|
874
871
|
} = options;
|
|
875
872
|
const log = customLogger || defaultLogger;
|
|
876
873
|
if (verbose) log.debug = log.info;
|
|
877
|
-
const maxDuration = VOXTRAL_LIMITS.
|
|
874
|
+
const maxDuration = VOXTRAL_LIMITS.maxAudioDurationSec;
|
|
878
875
|
if (audioBuffer) {
|
|
879
876
|
log.info(`Transcribing from buffer (${(audioBuffer.length / 1024 / 1024).toFixed(2)} MB)`);
|
|
880
877
|
const result = await provider.transcribe({
|
|
@@ -1003,6 +1000,7 @@ export {
|
|
|
1003
1000
|
autoSplitAudio,
|
|
1004
1001
|
createMistralTranscriber,
|
|
1005
1002
|
createProvider,
|
|
1003
|
+
detectAudioMimeType,
|
|
1006
1004
|
detectSilenceRegions,
|
|
1007
1005
|
findOptimalSplitPoints,
|
|
1008
1006
|
formatMergedText,
|
package/dist/providers.min.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
1
5
|
// src/utils/transcription/providers.ts
|
|
2
6
|
import { spawn } from "child_process";
|
|
3
7
|
import * as fs from "fs";
|
|
@@ -57,26 +61,10 @@ function createProvider(providerName, config) {
|
|
|
57
61
|
throw new Error(`Unknown provider: ${providerName}`);
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
|
-
var
|
|
61
|
-
name = "whisper";
|
|
62
|
-
cacheDir;
|
|
63
|
-
static DEFAULTS = {
|
|
64
|
-
DIARIZE: false,
|
|
65
|
-
SILDUR: "1.3",
|
|
66
|
-
SILBUF: 0.2,
|
|
67
|
-
SILTHR: "-35dB",
|
|
68
|
-
MODEL_KEYS: {
|
|
69
|
-
tinyd: "ggml-small.en-tdrz.bin",
|
|
70
|
-
small: "ggml-small.bin",
|
|
71
|
-
medium: "ggml-medium.bin"
|
|
72
|
-
},
|
|
73
|
-
MODELS: {
|
|
74
|
-
tinyd: "https://huggingface.co/akashmjn/tinydiarize-whisper.cpp/resolve/main/ggml-small.en-tdrz.bin",
|
|
75
|
-
small: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin",
|
|
76
|
-
medium: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.bin"
|
|
77
|
-
}
|
|
78
|
-
};
|
|
64
|
+
var _WhisperProvider = class _WhisperProvider {
|
|
79
65
|
constructor(config) {
|
|
66
|
+
__publicField(this, "name", "whisper");
|
|
67
|
+
__publicField(this, "cacheDir");
|
|
80
68
|
this.cacheDir = config?.cacheDir || `${process.env.HOME}/.cache/whisper-models`;
|
|
81
69
|
}
|
|
82
70
|
async transcribe(params) {
|
|
@@ -187,36 +175,44 @@ var WhisperProvider = class _WhisperProvider {
|
|
|
187
175
|
return modelPath;
|
|
188
176
|
}
|
|
189
177
|
};
|
|
178
|
+
__publicField(_WhisperProvider, "DEFAULTS", {
|
|
179
|
+
DIARIZE: false,
|
|
180
|
+
SILDUR: "1.3",
|
|
181
|
+
SILBUF: 0.2,
|
|
182
|
+
SILTHR: "-35dB",
|
|
183
|
+
MODEL_KEYS: {
|
|
184
|
+
tinyd: "ggml-small.en-tdrz.bin",
|
|
185
|
+
small: "ggml-small.bin",
|
|
186
|
+
medium: "ggml-medium.bin"
|
|
187
|
+
},
|
|
188
|
+
MODELS: {
|
|
189
|
+
tinyd: "https://huggingface.co/akashmjn/tinydiarize-whisper.cpp/resolve/main/ggml-small.en-tdrz.bin",
|
|
190
|
+
small: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin",
|
|
191
|
+
medium: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.bin"
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
var WhisperProvider = _WhisperProvider;
|
|
190
195
|
var VOXTRAL_LIMITS = {
|
|
191
196
|
/** Maximum audio duration in seconds (3 hours for Voxtral Transcribe 2) */
|
|
192
197
|
maxAudioDurationSec: 3 * 60 * 60,
|
|
193
198
|
// 10800 seconds = 3 hours
|
|
194
|
-
/** Recommended max duration before splitting (for reliability) */
|
|
195
|
-
recommendedMaxDurationSec: 30 * 60,
|
|
196
|
-
// 30 minutes
|
|
197
199
|
/** Maximum context biasing words/phrases */
|
|
198
200
|
maxContextBiasingTerms: 100,
|
|
199
201
|
/** Maximum file size in bytes (1GB) */
|
|
200
202
|
maxFileSizeBytes: 1024 * 1024 * 1024
|
|
201
203
|
};
|
|
202
204
|
var MistralProvider = class {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
* Check if audio duration exceeds recommended limits
|
|
207
|
-
*/
|
|
208
|
-
static shouldSplit(durationSec) {
|
|
209
|
-
return durationSec > VOXTRAL_LIMITS.recommendedMaxDurationSec;
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Get the recommended max segment duration for splitting
|
|
213
|
-
*/
|
|
214
|
-
static getRecommendedMaxSegment() {
|
|
215
|
-
return VOXTRAL_LIMITS.recommendedMaxDurationSec;
|
|
205
|
+
constructor() {
|
|
206
|
+
__publicField(this, "name", "mistral");
|
|
207
|
+
__publicField(this, "maxAudioDurationSec", VOXTRAL_LIMITS.maxAudioDurationSec);
|
|
216
208
|
}
|
|
217
209
|
async transcribe(params) {
|
|
218
210
|
if (params.language && params.timestampGranularity) {
|
|
219
|
-
|
|
211
|
+
throw new Error("Cannot use both language and timestampGranularity (Mistral API limitation)");
|
|
212
|
+
}
|
|
213
|
+
const diarize = params.diarize ?? true;
|
|
214
|
+
if (diarize && params.timestampGranularity === "word") {
|
|
215
|
+
throw new Error('When diarize is set to true, the timestamp granularity must be set to ["segment"], got ["word"]');
|
|
220
216
|
}
|
|
221
217
|
const formData = new FormData();
|
|
222
218
|
if (params.audioUrl) {
|
|
@@ -242,7 +238,6 @@ var MistralProvider = class {
|
|
|
242
238
|
if (params.language) {
|
|
243
239
|
formData.append("language", params.language);
|
|
244
240
|
}
|
|
245
|
-
const diarize = params.diarize ?? true;
|
|
246
241
|
if (diarize) {
|
|
247
242
|
formData.append("diarize", "true");
|
|
248
243
|
}
|
|
@@ -278,7 +273,9 @@ var MistralProvider = class {
|
|
|
278
273
|
}
|
|
279
274
|
};
|
|
280
275
|
var GreenPTProvider = class {
|
|
281
|
-
|
|
276
|
+
constructor() {
|
|
277
|
+
__publicField(this, "name", "greenpt");
|
|
278
|
+
}
|
|
282
279
|
async transcribe(params) {
|
|
283
280
|
if (!params.apiKey) {
|
|
284
281
|
return { text: "", error: "API key is required for GreenPT provider" };
|
|
@@ -788,7 +785,7 @@ function createMistralTranscriber(config) {
|
|
|
788
785
|
language,
|
|
789
786
|
model = defaultModel,
|
|
790
787
|
diarize = true,
|
|
791
|
-
timestamps = language ? void 0 : "
|
|
788
|
+
timestamps = language ? void 0 : "segment",
|
|
792
789
|
autoSplit,
|
|
793
790
|
splitOutputDir,
|
|
794
791
|
logger: customLogger,
|
|
@@ -796,7 +793,7 @@ function createMistralTranscriber(config) {
|
|
|
796
793
|
} = options;
|
|
797
794
|
const log = customLogger || defaultLogger;
|
|
798
795
|
if (verbose) log.debug = log.info;
|
|
799
|
-
const maxDuration = VOXTRAL_LIMITS.
|
|
796
|
+
const maxDuration = VOXTRAL_LIMITS.maxAudioDurationSec;
|
|
800
797
|
if (audioBuffer) {
|
|
801
798
|
log.info(`Transcribing from buffer (${(audioBuffer.length / 1024 / 1024).toFixed(2)} MB)`);
|
|
802
799
|
const result = await provider.transcribe({
|
package/dist/realtime.d.ts
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* This module provides a simple, event-driven interface for streaming audio
|
|
5
5
|
* transcription using Mistral's realtime WebSocket API.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* **Node.js only** - Browser support is currently disabled due to WebSocket
|
|
8
|
+
* authentication limitations with Mistral API.
|
|
9
|
+
*
|
|
10
|
+
* @example Node.js
|
|
8
11
|
* ```typescript
|
|
9
12
|
* import {
|
|
10
13
|
* createRealtimeTranscriber,
|
|
@@ -15,7 +18,7 @@
|
|
|
15
18
|
* apiKey: process.env.MISTRAL_API_KEY,
|
|
16
19
|
* })
|
|
17
20
|
*
|
|
18
|
-
* const { stream, stop } = captureAudioFromMicrophone(16000)
|
|
21
|
+
* const { stream, stop } = await captureAudioFromMicrophone(16000)
|
|
19
22
|
*
|
|
20
23
|
* try {
|
|
21
24
|
* for await (const event of transcriber.transcribe(stream)) {
|
|
@@ -33,6 +36,5 @@
|
|
|
33
36
|
*
|
|
34
37
|
* @module @wovin/tranz/realtime
|
|
35
38
|
*/
|
|
36
|
-
export { createRealtimeTranscriber, captureAudioFromMicrophone, type RealtimeEvent, type RealtimeConfig, type RealtimeTranscriber, type TranscribeOptions, type AudioFormat, type AudioCaptureResult, type SessionCreatedEvent, type SessionUpdatedEvent, type TranscriptionTextDeltaEvent, type TranscriptionLanguageEvent, type TranscriptionSegmentEvent, type TranscriptionDoneEvent, type ErrorEvent, } from "./utils/transcription/realtime.js";
|
|
37
|
-
export { AudioEncoding } from "@mistralai/mistralai/extra/realtime";
|
|
39
|
+
export { createRealtimeTranscriber, captureAudioFromMicrophone, captureAudioFromBrowser, AudioEncoding, type RealtimeEvent, type RealtimeConfig, type RealtimeTranscriber, type TranscribeOptions, type AudioFormat, type AudioCaptureResult, type SessionCreatedEvent, type SessionUpdatedEvent, type TranscriptionTextDeltaEvent, type TranscriptionLanguageEvent, type TranscriptionSegmentEvent, type TranscriptionDoneEvent, type ErrorEvent, } from "./utils/transcription/realtime.js";
|
|
38
40
|
//# sourceMappingURL=realtime.d.ts.map
|
package/dist/realtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,uBAAuB,EACvB,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,UAAU,GAChB,MAAM,mCAAmC,CAAC"}
|
package/dist/realtime.min.js
CHANGED
|
@@ -1,32 +1,309 @@
|
|
|
1
|
+
// src/utils/transcription/runtime.ts
|
|
2
|
+
async function getWebSocketImpl() {
|
|
3
|
+
const isBrowser = typeof globalThis !== "undefined" && (typeof globalThis.document !== "undefined" || typeof globalThis.navigator !== "undefined");
|
|
4
|
+
if (isBrowser && typeof globalThis.WebSocket !== "undefined") {
|
|
5
|
+
return globalThis.WebSocket;
|
|
6
|
+
}
|
|
7
|
+
if (!isBrowser) {
|
|
8
|
+
try {
|
|
9
|
+
const WS = await import("ws");
|
|
10
|
+
return WS.default || WS;
|
|
11
|
+
} catch (err) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
"WebSocket not available. In Node.js, install 'ws' package: npm install ws"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
throw new Error(
|
|
18
|
+
"WebSocket not available in this environment"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
1
22
|
// src/utils/transcription/realtime.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
23
|
+
var AudioEncoding = /* @__PURE__ */ ((AudioEncoding2) => {
|
|
24
|
+
AudioEncoding2["PcmS16le"] = "pcm_s16le";
|
|
25
|
+
AudioEncoding2["PcmS16be"] = "pcm_s16be";
|
|
26
|
+
AudioEncoding2["PcmU16le"] = "pcm_u16le";
|
|
27
|
+
AudioEncoding2["PcmU16be"] = "pcm_u16be";
|
|
28
|
+
AudioEncoding2["PcmS24le"] = "pcm_s24le";
|
|
29
|
+
AudioEncoding2["PcmS24be"] = "pcm_s24be";
|
|
30
|
+
AudioEncoding2["PcmU24le"] = "pcm_u24le";
|
|
31
|
+
AudioEncoding2["PcmU24be"] = "pcm_u24be";
|
|
32
|
+
AudioEncoding2["PcmS32le"] = "pcm_s32le";
|
|
33
|
+
AudioEncoding2["PcmS32be"] = "pcm_s32be";
|
|
34
|
+
AudioEncoding2["PcmU32le"] = "pcm_u32le";
|
|
35
|
+
AudioEncoding2["PcmU32be"] = "pcm_u32be";
|
|
36
|
+
AudioEncoding2["PcmF32le"] = "pcm_f32le";
|
|
37
|
+
AudioEncoding2["PcmF32be"] = "pcm_f32be";
|
|
38
|
+
AudioEncoding2["PcmF64le"] = "pcm_f64le";
|
|
39
|
+
AudioEncoding2["PcmF64be"] = "pcm_f64be";
|
|
40
|
+
return AudioEncoding2;
|
|
41
|
+
})(AudioEncoding || {});
|
|
7
42
|
function createRealtimeTranscriber(config) {
|
|
43
|
+
const isBrowser = typeof window !== "undefined" && typeof document !== "undefined" && typeof navigator !== "undefined";
|
|
44
|
+
if (isBrowser) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"Realtime transcription is not yet supported in browsers. Browser WebSocket API does not support authentication headers required by Mistral API. Use this API in Node.js or server-side environments only. See: https://github.com/wovin/tranz/issues"
|
|
47
|
+
);
|
|
48
|
+
}
|
|
8
49
|
const model = config.model ?? "voxtral-mini-transcribe-realtime-2602";
|
|
9
50
|
const baseUrl = config.baseUrl ?? "wss://api.mistral.ai";
|
|
10
|
-
const client = new RealtimeTranscription({
|
|
11
|
-
apiKey: config.apiKey,
|
|
12
|
-
serverURL: baseUrl
|
|
13
|
-
});
|
|
14
51
|
return {
|
|
15
52
|
async *transcribe(audioStream, options) {
|
|
16
53
|
const audioFormat = {
|
|
17
|
-
encoding: options?.audioFormat?.encoding ??
|
|
54
|
+
encoding: options?.audioFormat?.encoding ?? "pcm_s16le" /* PcmS16le */,
|
|
18
55
|
sampleRate: options?.audioFormat?.sampleRate ?? 16e3
|
|
19
56
|
};
|
|
20
|
-
const
|
|
57
|
+
const connection = await createConnection(
|
|
58
|
+
config.apiKey,
|
|
59
|
+
baseUrl,
|
|
60
|
+
model,
|
|
21
61
|
audioFormat
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
62
|
+
);
|
|
63
|
+
try {
|
|
64
|
+
let stopRequested = false;
|
|
65
|
+
const sendAudioTask = (async () => {
|
|
66
|
+
try {
|
|
67
|
+
for await (const chunk of audioStream) {
|
|
68
|
+
if (stopRequested || connection.isClosed) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
await connection.sendAudio(chunk);
|
|
72
|
+
}
|
|
73
|
+
} finally {
|
|
74
|
+
await connection.endAudio();
|
|
75
|
+
}
|
|
76
|
+
})();
|
|
77
|
+
for await (const event of connection.events()) {
|
|
78
|
+
yield event;
|
|
79
|
+
if (event.type === "transcription.done" || event.type === "error") {
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
await sendAudioTask;
|
|
84
|
+
} finally {
|
|
85
|
+
await connection.close();
|
|
86
|
+
const maybeReturn = audioStream.return;
|
|
87
|
+
if (typeof maybeReturn === "function") {
|
|
88
|
+
await maybeReturn.call(audioStream);
|
|
89
|
+
}
|
|
25
90
|
}
|
|
26
91
|
}
|
|
27
92
|
};
|
|
28
93
|
}
|
|
29
|
-
function
|
|
94
|
+
async function createConnection(apiKey, baseUrl, model, audioFormat) {
|
|
95
|
+
const WebSocketImpl = await getWebSocketImpl();
|
|
96
|
+
const wsUrl = buildWebSocketUrl(baseUrl, model, apiKey);
|
|
97
|
+
const isNodeWs = typeof process !== "undefined" && process.versions?.node;
|
|
98
|
+
const ws = isNodeWs ? new WebSocketImpl(wsUrl, {
|
|
99
|
+
headers: {
|
|
100
|
+
Authorization: `Bearer ${apiKey}`
|
|
101
|
+
}
|
|
102
|
+
}) : new WebSocketImpl(wsUrl);
|
|
103
|
+
const session = await waitForSession(ws);
|
|
104
|
+
let closed = false;
|
|
105
|
+
const websocket = ws;
|
|
106
|
+
const connection = {
|
|
107
|
+
get isClosed() {
|
|
108
|
+
return closed || websocket.readyState === 2 || websocket.readyState === 3;
|
|
109
|
+
},
|
|
110
|
+
async *events() {
|
|
111
|
+
const queue = [];
|
|
112
|
+
let resolver = null;
|
|
113
|
+
let done = false;
|
|
114
|
+
const push = (item) => {
|
|
115
|
+
if (done) return;
|
|
116
|
+
if (resolver) {
|
|
117
|
+
const resolve = resolver;
|
|
118
|
+
resolver = null;
|
|
119
|
+
resolve(item);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
queue.push(item);
|
|
123
|
+
};
|
|
124
|
+
const handleMessage = (event) => {
|
|
125
|
+
push({ kind: "message", data: event.data });
|
|
126
|
+
};
|
|
127
|
+
const handleClose = () => {
|
|
128
|
+
closed = true;
|
|
129
|
+
push({ kind: "close" });
|
|
130
|
+
};
|
|
131
|
+
const handleError = (event) => {
|
|
132
|
+
push({
|
|
133
|
+
kind: "error",
|
|
134
|
+
error: new Error("WebSocket connection error")
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
websocket.addEventListener("message", handleMessage);
|
|
138
|
+
websocket.addEventListener("close", handleClose);
|
|
139
|
+
websocket.addEventListener("error", handleError);
|
|
140
|
+
try {
|
|
141
|
+
while (true) {
|
|
142
|
+
const item = queue.length > 0 ? queue.shift() : await new Promise((resolve) => {
|
|
143
|
+
resolver = resolve;
|
|
144
|
+
});
|
|
145
|
+
if (item.kind === "close") break;
|
|
146
|
+
if (item.kind === "error") {
|
|
147
|
+
const error = item.error ?? new Error("WebSocket connection error");
|
|
148
|
+
yield {
|
|
149
|
+
type: "error",
|
|
150
|
+
error: { message: error.message }
|
|
151
|
+
};
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const event = parseRealtimeEvent(item.data);
|
|
155
|
+
yield event;
|
|
156
|
+
}
|
|
157
|
+
} finally {
|
|
158
|
+
done = true;
|
|
159
|
+
websocket.removeEventListener("message", handleMessage);
|
|
160
|
+
websocket.removeEventListener("close", handleClose);
|
|
161
|
+
websocket.removeEventListener("error", handleError);
|
|
162
|
+
if (resolver !== null) {
|
|
163
|
+
const resolve = resolver;
|
|
164
|
+
resolver = null;
|
|
165
|
+
resolve({ kind: "close" });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
async sendAudio(chunk) {
|
|
170
|
+
if (connection.isClosed) {
|
|
171
|
+
throw new Error("Connection is closed");
|
|
172
|
+
}
|
|
173
|
+
const base64Audio = arrayBufferToBase64(chunk);
|
|
174
|
+
const message = {
|
|
175
|
+
type: "input_audio.append",
|
|
176
|
+
audio: base64Audio
|
|
177
|
+
};
|
|
178
|
+
await sendJson(websocket, message);
|
|
179
|
+
},
|
|
180
|
+
async endAudio() {
|
|
181
|
+
if (connection.isClosed) return;
|
|
182
|
+
await sendJson(websocket, { type: "input_audio.end" });
|
|
183
|
+
},
|
|
184
|
+
async close() {
|
|
185
|
+
if (closed) return;
|
|
186
|
+
closed = true;
|
|
187
|
+
if (websocket.readyState === 3) return;
|
|
188
|
+
await new Promise((resolve) => {
|
|
189
|
+
const finalize = () => {
|
|
190
|
+
websocket.removeEventListener("close", finalize);
|
|
191
|
+
resolve();
|
|
192
|
+
};
|
|
193
|
+
websocket.addEventListener("close", finalize);
|
|
194
|
+
websocket.close(1e3, "");
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
return connection;
|
|
199
|
+
}
|
|
200
|
+
function buildWebSocketUrl(baseUrl, model, apiKey) {
|
|
201
|
+
const url = new URL("v1/audio/transcriptions/realtime", baseUrl);
|
|
202
|
+
url.searchParams.set("model", model);
|
|
203
|
+
return url.toString();
|
|
204
|
+
}
|
|
205
|
+
async function waitForSession(ws) {
|
|
206
|
+
return new Promise((resolve, reject) => {
|
|
207
|
+
const timeout = setTimeout(() => {
|
|
208
|
+
cleanup();
|
|
209
|
+
ws.close();
|
|
210
|
+
reject(new Error("Timeout waiting for session creation"));
|
|
211
|
+
}, 1e4);
|
|
212
|
+
const cleanup = () => {
|
|
213
|
+
clearTimeout(timeout);
|
|
214
|
+
ws.removeEventListener("message", handleMessage);
|
|
215
|
+
ws.removeEventListener("close", handleClose);
|
|
216
|
+
ws.removeEventListener("error", handleError);
|
|
217
|
+
};
|
|
218
|
+
const handleMessage = (event) => {
|
|
219
|
+
try {
|
|
220
|
+
const parsed = parseRealtimeEvent(event.data);
|
|
221
|
+
if (parsed.type === "session.created") {
|
|
222
|
+
cleanup();
|
|
223
|
+
resolve(parsed);
|
|
224
|
+
} else if (parsed.type === "error") {
|
|
225
|
+
cleanup();
|
|
226
|
+
ws.close();
|
|
227
|
+
reject(
|
|
228
|
+
new Error(
|
|
229
|
+
`Realtime transcription error: ${JSON.stringify(parsed.error)}`
|
|
230
|
+
)
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
} catch (err) {
|
|
234
|
+
cleanup();
|
|
235
|
+
ws.close();
|
|
236
|
+
reject(err);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const handleClose = () => {
|
|
240
|
+
cleanup();
|
|
241
|
+
reject(new Error("WebSocket closed during handshake"));
|
|
242
|
+
};
|
|
243
|
+
const handleError = () => {
|
|
244
|
+
cleanup();
|
|
245
|
+
reject(new Error("WebSocket error during handshake"));
|
|
246
|
+
};
|
|
247
|
+
ws.addEventListener("message", handleMessage);
|
|
248
|
+
ws.addEventListener("close", handleClose);
|
|
249
|
+
ws.addEventListener("error", handleError);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
function parseRealtimeEvent(data) {
|
|
253
|
+
try {
|
|
254
|
+
const text = typeof data === "string" ? data : new TextDecoder().decode(data);
|
|
255
|
+
const payload = JSON.parse(text);
|
|
256
|
+
if (typeof payload.type !== "string") {
|
|
257
|
+
return {
|
|
258
|
+
type: "error",
|
|
259
|
+
error: { message: "Invalid event: missing type" }
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
return payload;
|
|
263
|
+
} catch (err) {
|
|
264
|
+
return {
|
|
265
|
+
type: "error",
|
|
266
|
+
error: { message: `Failed to parse event: ${err}` }
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async function sendJson(ws, payload) {
|
|
271
|
+
return new Promise((resolve, reject) => {
|
|
272
|
+
const message = JSON.stringify(payload);
|
|
273
|
+
if (typeof ws.send === "function") {
|
|
274
|
+
const send = ws.send.bind(ws);
|
|
275
|
+
try {
|
|
276
|
+
send(message, (err) => {
|
|
277
|
+
if (err) reject(err);
|
|
278
|
+
else resolve();
|
|
279
|
+
});
|
|
280
|
+
} catch {
|
|
281
|
+
ws.send(message);
|
|
282
|
+
resolve();
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
ws.send(message);
|
|
286
|
+
resolve();
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
function arrayBufferToBase64(buffer) {
|
|
291
|
+
if (typeof btoa !== "undefined") {
|
|
292
|
+
const binary = Array.from(buffer).map((byte) => String.fromCharCode(byte)).join("");
|
|
293
|
+
return btoa(binary);
|
|
294
|
+
}
|
|
295
|
+
if (typeof Buffer !== "undefined") {
|
|
296
|
+
return Buffer.from(buffer).toString("base64");
|
|
297
|
+
}
|
|
298
|
+
throw new Error("No base64 encoding available");
|
|
299
|
+
}
|
|
300
|
+
async function captureAudioFromMicrophone(sampleRate = 16e3) {
|
|
301
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
302
|
+
throw new Error(
|
|
303
|
+
"captureAudioFromMicrophone() is Node.js only. Use captureAudioFromBrowser() in browsers."
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
const { spawn } = await import("child_process");
|
|
30
307
|
const recorder = spawn(
|
|
31
308
|
"rec",
|
|
32
309
|
[
|
|
@@ -53,8 +330,7 @@ function captureAudioFromMicrophone(sampleRate = 16e3) {
|
|
|
53
330
|
{ stdio: ["ignore", "pipe", "ignore"] }
|
|
54
331
|
);
|
|
55
332
|
recorder.on("error", (err) => {
|
|
56
|
-
|
|
57
|
-
if (error.code === "ENOENT") {
|
|
333
|
+
if (err.code === "ENOENT") {
|
|
58
334
|
console.error(
|
|
59
335
|
"\nError: 'rec' command not found. Please install SoX:",
|
|
60
336
|
"\n macOS: brew install sox",
|
|
@@ -85,11 +361,88 @@ function captureAudioFromMicrophone(sampleRate = 16e3) {
|
|
|
85
361
|
};
|
|
86
362
|
return { stream, stop };
|
|
87
363
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
364
|
+
async function captureAudioFromBrowser(sampleRate = 16e3) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
"Browser realtime transcription is not yet supported. Browser WebSocket API does not support authentication headers required by Mistral API. Use captureAudioFromMicrophone() in Node.js environments instead."
|
|
367
|
+
);
|
|
368
|
+
if (typeof navigator === "undefined" || !navigator.mediaDevices) {
|
|
369
|
+
throw new Error(
|
|
370
|
+
"captureAudioFromBrowser() requires a browser environment with getUserMedia support"
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
const mediaStream = await navigator.mediaDevices.getUserMedia({
|
|
374
|
+
audio: {
|
|
375
|
+
channelCount: 1,
|
|
376
|
+
sampleRate,
|
|
377
|
+
echoCancellation: true,
|
|
378
|
+
noiseSuppression: true
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
const audioContext = new AudioContext({ sampleRate });
|
|
382
|
+
const source = audioContext.createMediaStreamSource(mediaStream);
|
|
383
|
+
const processor = audioContext.createScriptProcessor(4096, 1, 1);
|
|
384
|
+
let stopped = false;
|
|
385
|
+
const chunks = [];
|
|
386
|
+
let resolver = null;
|
|
387
|
+
processor.onaudioprocess = (event) => {
|
|
388
|
+
if (stopped) return;
|
|
389
|
+
const inputData = event.inputBuffer.getChannelData(0);
|
|
390
|
+
const pcm16 = new Int16Array(inputData.length);
|
|
391
|
+
for (let i = 0; i < inputData.length; i++) {
|
|
392
|
+
const sample = Math.max(-1, Math.min(1, inputData[i]));
|
|
393
|
+
pcm16[i] = sample < 0 ? sample * 32768 : sample * 32767;
|
|
394
|
+
}
|
|
395
|
+
const uint8 = new Uint8Array(pcm16.length * 2);
|
|
396
|
+
for (let i = 0; i < pcm16.length; i++) {
|
|
397
|
+
uint8[i * 2] = pcm16[i] & 255;
|
|
398
|
+
uint8[i * 2 + 1] = pcm16[i] >> 8 & 255;
|
|
399
|
+
}
|
|
400
|
+
if (resolver) {
|
|
401
|
+
const resolve = resolver;
|
|
402
|
+
resolver = null;
|
|
403
|
+
resolve({ value: uint8, done: false });
|
|
404
|
+
} else {
|
|
405
|
+
chunks.push(pcm16);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
source.connect(processor);
|
|
409
|
+
processor.connect(audioContext.destination);
|
|
410
|
+
const stream = (async function* () {
|
|
411
|
+
try {
|
|
412
|
+
while (!stopped) {
|
|
413
|
+
if (chunks.length > 0) {
|
|
414
|
+
const pcm16 = chunks.shift();
|
|
415
|
+
const uint8 = new Uint8Array(pcm16.length * 2);
|
|
416
|
+
for (let i = 0; i < pcm16.length; i++) {
|
|
417
|
+
uint8[i * 2] = pcm16[i] & 255;
|
|
418
|
+
uint8[i * 2 + 1] = pcm16[i] >> 8 & 255;
|
|
419
|
+
}
|
|
420
|
+
yield uint8;
|
|
421
|
+
} else {
|
|
422
|
+
await new Promise((resolve) => {
|
|
423
|
+
resolver = resolve;
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
} finally {
|
|
428
|
+
processor.disconnect();
|
|
429
|
+
source.disconnect();
|
|
430
|
+
mediaStream.getTracks().forEach((track) => track.stop());
|
|
431
|
+
await audioContext.close();
|
|
432
|
+
}
|
|
433
|
+
})();
|
|
434
|
+
const stop = () => {
|
|
435
|
+
stopped = true;
|
|
436
|
+
if (resolver) {
|
|
437
|
+
resolver({ value: void 0, done: true });
|
|
438
|
+
resolver = null;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
return { stream, stop };
|
|
442
|
+
}
|
|
91
443
|
export {
|
|
92
|
-
|
|
444
|
+
AudioEncoding,
|
|
445
|
+
captureAudioFromBrowser,
|
|
93
446
|
captureAudioFromMicrophone,
|
|
94
447
|
createRealtimeTranscriber
|
|
95
448
|
};
|
|
@@ -115,8 +115,6 @@ export declare class WhisperProvider implements TranscriptionProvider {
|
|
|
115
115
|
export declare const VOXTRAL_LIMITS: {
|
|
116
116
|
/** Maximum audio duration in seconds (3 hours for Voxtral Transcribe 2) */
|
|
117
117
|
maxAudioDurationSec: number;
|
|
118
|
-
/** Recommended max duration before splitting (for reliability) */
|
|
119
|
-
recommendedMaxDurationSec: number;
|
|
120
118
|
/** Maximum context biasing words/phrases */
|
|
121
119
|
maxContextBiasingTerms: number;
|
|
122
120
|
/** Maximum file size in bytes (1GB) */
|
|
@@ -125,14 +123,6 @@ export declare const VOXTRAL_LIMITS: {
|
|
|
125
123
|
export declare class MistralProvider implements TranscriptionProvider {
|
|
126
124
|
name: string;
|
|
127
125
|
maxAudioDurationSec: number;
|
|
128
|
-
/**
|
|
129
|
-
* Check if audio duration exceeds recommended limits
|
|
130
|
-
*/
|
|
131
|
-
static shouldSplit(durationSec: number): boolean;
|
|
132
|
-
/**
|
|
133
|
-
* Get the recommended max segment duration for splitting
|
|
134
|
-
*/
|
|
135
|
-
static getRecommendedMaxSegment(): number;
|
|
136
126
|
transcribe(params: TranscribeParams): Promise<TranscriptionResult>;
|
|
137
127
|
}
|
|
138
128
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../src/utils/transcription/providers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,WAAW,CAAC,EAAE,GAAG,CAAA;IACjB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;CACnE;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iEAAiE;IACjE,oBAAoB,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzC,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oCAAoC;IACpC,MAAM,CAAC,EAAE,GAAG,CAAA;CACb;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAE5D;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,qBAAqB,CAW9F;AASD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,qBAAqB;IAC3D,IAAI,SAAY;IAEhB,OAAO,CAAC,QAAQ,CAAQ;IAExB,MAAM,CAAC,QAAQ;;;;;;;;;;;;;;;MAkBd;gBAEW,MAAM,CAAC,EAAE,GAAG;IAKlB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC;YA+F1D,4BAA4B;CAkC3C;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;IACzB,2EAA2E;;IAE3E,
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../../src/utils/transcription/providers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAUH;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,sEAAsE;IACtE,WAAW,CAAC,EAAE,GAAG,CAAA;IACjB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,GAAG,EAAE,CAAA;IACb,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;OAIG;IACH,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;CACnE;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iEAAiE;IACjE,oBAAoB,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzC,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oCAAoC;IACpC,MAAM,CAAC,EAAE,GAAG,CAAA;CACb;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;AAE5D;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,qBAAqB,CAW9F;AASD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,qBAAqB;IAC3D,IAAI,SAAY;IAEhB,OAAO,CAAC,QAAQ,CAAQ;IAExB,MAAM,CAAC,QAAQ;;;;;;;;;;;;;;;MAkBd;gBAEW,MAAM,CAAC,EAAE,GAAG;IAKlB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC;YA+F1D,4BAA4B;CAkC3C;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;IACzB,2EAA2E;;IAE3E,4CAA4C;;IAE5C,uCAAuC;;CAExC,CAAA;AAED,qBAAa,eAAgB,YAAW,qBAAqB;IAC3D,IAAI,SAAY;IAChB,mBAAmB,SAAqC;IAElD,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAwGzE;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,qBAAqB;IAC3D,IAAI,SAAY;IAEV,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAkGzE"}
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* Provides a simple, event-driven interface for streaming audio transcription.
|
|
5
5
|
* Users provide audio as AsyncIterable<Uint8Array> and receive typed events.
|
|
6
6
|
*
|
|
7
|
+
* Browser-compatible: Uses native WebSocket in browsers/Deno, 'ws' package in Node.js
|
|
8
|
+
*
|
|
7
9
|
* @example
|
|
8
10
|
* ```typescript
|
|
9
11
|
* import { createRealtimeTranscriber } from '@wovin/tranz/realtime'
|
|
@@ -19,7 +21,27 @@
|
|
|
19
21
|
* }
|
|
20
22
|
* ```
|
|
21
23
|
*/
|
|
22
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Audio encoding formats supported by the transcription service
|
|
26
|
+
*/
|
|
27
|
+
export declare enum AudioEncoding {
|
|
28
|
+
PcmS16le = "pcm_s16le",
|
|
29
|
+
PcmS16be = "pcm_s16be",
|
|
30
|
+
PcmU16le = "pcm_u16le",
|
|
31
|
+
PcmU16be = "pcm_u16be",
|
|
32
|
+
PcmS24le = "pcm_s24le",
|
|
33
|
+
PcmS24be = "pcm_s24be",
|
|
34
|
+
PcmU24le = "pcm_u24le",
|
|
35
|
+
PcmU24be = "pcm_u24be",
|
|
36
|
+
PcmS32le = "pcm_s32le",
|
|
37
|
+
PcmS32be = "pcm_s32be",
|
|
38
|
+
PcmU32le = "pcm_u32le",
|
|
39
|
+
PcmU32be = "pcm_u32be",
|
|
40
|
+
PcmF32le = "pcm_f32le",
|
|
41
|
+
PcmF32be = "pcm_f32be",
|
|
42
|
+
PcmF64le = "pcm_f64le",
|
|
43
|
+
PcmF64be = "pcm_f64be"
|
|
44
|
+
}
|
|
23
45
|
/**
|
|
24
46
|
* Audio format configuration for realtime transcription
|
|
25
47
|
*/
|
|
@@ -59,6 +81,7 @@ export interface SessionCreatedEvent {
|
|
|
59
81
|
type: "session.created";
|
|
60
82
|
session: {
|
|
61
83
|
id: string;
|
|
84
|
+
audioFormat: AudioFormat;
|
|
62
85
|
};
|
|
63
86
|
}
|
|
64
87
|
/**
|
|
@@ -112,6 +135,7 @@ export interface ErrorEvent {
|
|
|
112
135
|
type: "error";
|
|
113
136
|
error: {
|
|
114
137
|
message: string | unknown;
|
|
138
|
+
code?: string;
|
|
115
139
|
};
|
|
116
140
|
}
|
|
117
141
|
/**
|
|
@@ -167,7 +191,7 @@ export interface AudioCaptureResult {
|
|
|
167
191
|
stop: () => void;
|
|
168
192
|
}
|
|
169
193
|
/**
|
|
170
|
-
* Capture audio from microphone using SoX `rec` command
|
|
194
|
+
* Capture audio from microphone using SoX `rec` command (Node.js only)
|
|
171
195
|
*
|
|
172
196
|
* Yields PCM 16-bit signed little-endian mono audio chunks suitable for
|
|
173
197
|
* realtime transcription.
|
|
@@ -177,6 +201,8 @@ export interface AudioCaptureResult {
|
|
|
177
201
|
* - macOS: `brew install sox`
|
|
178
202
|
* - Linux: `sudo apt install sox`
|
|
179
203
|
*
|
|
204
|
+
* **Note:** This is Node.js only. For browser audio capture, use `captureAudioFromBrowser()`
|
|
205
|
+
*
|
|
180
206
|
* @param sampleRate - Sample rate in Hz (default: 16000)
|
|
181
207
|
* @returns Object with audio stream and stop function
|
|
182
208
|
*
|
|
@@ -193,5 +219,24 @@ export interface AudioCaptureResult {
|
|
|
193
219
|
* }
|
|
194
220
|
* ```
|
|
195
221
|
*/
|
|
196
|
-
export declare function captureAudioFromMicrophone(sampleRate?: number): AudioCaptureResult
|
|
222
|
+
export declare function captureAudioFromMicrophone(sampleRate?: number): Promise<AudioCaptureResult>;
|
|
223
|
+
/**
|
|
224
|
+
* Capture audio from browser microphone using Web Audio API
|
|
225
|
+
*
|
|
226
|
+
* **CURRENTLY DISABLED** - Browser support is not available yet due to
|
|
227
|
+
* WebSocket authentication limitations with Mistral API.
|
|
228
|
+
*
|
|
229
|
+
* @deprecated Browser realtime transcription is not yet supported.
|
|
230
|
+
* Use captureAudioFromMicrophone() in Node.js instead.
|
|
231
|
+
*
|
|
232
|
+
* @param sampleRate - Target sample rate in Hz (default: 16000)
|
|
233
|
+
* @returns Object with audio stream and stop function
|
|
234
|
+
*
|
|
235
|
+
* @throws Error - Always throws as browser mode is disabled
|
|
236
|
+
*
|
|
237
|
+
* @todo Enable when Mistral API supports browser WebSocket authentication
|
|
238
|
+
* @todo Migrate to AudioWorklet for better performance
|
|
239
|
+
* See: https://web.dev/patterns/media/microphone-process/
|
|
240
|
+
*/
|
|
241
|
+
export declare function captureAudioFromBrowser(sampleRate?: number): Promise<AudioCaptureResult>;
|
|
197
242
|
//# sourceMappingURL=realtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../../src/utils/transcription/realtime.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../../../src/utils/transcription/realtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime environment detection for WebSocket implementations
|
|
3
|
+
*
|
|
4
|
+
* Provides environment-aware WebSocket constructor selection:
|
|
5
|
+
* - Browser/Deno: Uses global WebSocket API
|
|
6
|
+
* - Node.js: Dynamically imports 'ws' package
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Get the appropriate WebSocket implementation for the current runtime
|
|
10
|
+
*
|
|
11
|
+
* @returns WebSocket constructor (browser WebSocket or ws package)
|
|
12
|
+
* @throws Error if WebSocket is not available in any form
|
|
13
|
+
*/
|
|
14
|
+
export declare function getWebSocketImpl(): Promise<any>;
|
|
15
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/utils/transcription/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,CAyBrD"}
|
|
@@ -25,7 +25,7 @@ export interface TranscribeOptions {
|
|
|
25
25
|
model?: string;
|
|
26
26
|
/** Enable speaker diarization (default: true) */
|
|
27
27
|
diarize?: boolean;
|
|
28
|
-
/** Timestamp granularity: 'word' | 'segment' (default: '
|
|
28
|
+
/** Timestamp granularity: 'word' | 'segment' (default: 'segment' when diarize=true, disabled if language set) */
|
|
29
29
|
timestamps?: 'word' | 'segment';
|
|
30
30
|
/** Auto-split long audio (default: true). For URLs, detects duration first. */
|
|
31
31
|
autoSplit?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcribe.d.ts","sourceRoot":"","sources":["../../../src/utils/transcription/transcribe.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,EAA6B,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAA;AAErG,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7B;AAQD,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,
|
|
1
|
+
{"version":3,"file":"transcribe.d.ts","sourceRoot":"","sources":["../../../src/utils/transcription/transcribe.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,EAA6B,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAA;AAErG,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7B;AAQD,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iHAAiH;IACjH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,iEAAiE;IACjE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,uCAAuC;IACvC,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AA6FD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAA;CAC3E;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,wBAAwB,GAAG,kBAAkB,CA4K7F;AAED,+BAA+B;AAC/B,eAAO,MAAM,UAAU,iCAA2B,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wovin/tranz",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Audio transcription library with provider support and auto-splitting",
|
|
6
6
|
"author": "gotjoshua @gotjoshua",
|
|
@@ -43,6 +43,9 @@
|
|
|
43
43
|
"@mistralai/mistralai": "^1.14.0",
|
|
44
44
|
"execa": "^9.6.1"
|
|
45
45
|
},
|
|
46
|
+
"optionalDependencies": {
|
|
47
|
+
"ws": "^8.19.0"
|
|
48
|
+
},
|
|
46
49
|
"devDependencies": {
|
|
47
50
|
"@types/node": "^24.10.1",
|
|
48
51
|
"@types/ws": "^8.5.13",
|
|
@@ -51,7 +54,6 @@
|
|
|
51
54
|
"tsup": "^8.5.0",
|
|
52
55
|
"tsx": "^4.19.2",
|
|
53
56
|
"typescript": "^5.9.3",
|
|
54
|
-
"ws": "^8.18.0",
|
|
55
57
|
"yargs": "^17.7.2",
|
|
56
58
|
"tsupconfig": "^0.0.0"
|
|
57
59
|
},
|