@storyteller-platform/ghost-story 0.0.1
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/LICENSE.md +611 -0
- package/README.md +18 -0
- package/dist/api/APIOptions.cjs +16 -0
- package/dist/api/APIOptions.d.cts +18 -0
- package/dist/api/APIOptions.d.ts +18 -0
- package/dist/api/APIOptions.js +0 -0
- package/dist/api/Recognition.cjs +263 -0
- package/dist/api/Recognition.d.cts +77 -0
- package/dist/api/Recognition.d.ts +77 -0
- package/dist/api/Recognition.js +233 -0
- package/dist/api/VoiceActivityDetection.cjs +77 -0
- package/dist/api/VoiceActivityDetection.d.cts +24 -0
- package/dist/api/VoiceActivityDetection.d.ts +24 -0
- package/dist/api/VoiceActivityDetection.js +43 -0
- package/dist/audio/AudioConverter.cjs +331 -0
- package/dist/audio/AudioConverter.d.cts +53 -0
- package/dist/audio/AudioConverter.d.ts +53 -0
- package/dist/audio/AudioConverter.js +310 -0
- package/dist/audio/AudioFormat.cjs +151 -0
- package/dist/audio/AudioFormat.d.cts +25 -0
- package/dist/audio/AudioFormat.d.ts +25 -0
- package/dist/audio/AudioFormat.js +123 -0
- package/dist/audio/AudioSource.cjs +119 -0
- package/dist/audio/AudioSource.d.cts +33 -0
- package/dist/audio/AudioSource.d.ts +33 -0
- package/dist/audio/AudioSource.js +88 -0
- package/dist/audio/index.cjs +74 -0
- package/dist/audio/index.d.cts +6 -0
- package/dist/audio/index.d.ts +6 -0
- package/dist/audio/index.js +54 -0
- package/dist/cli/bin.cjs +277 -0
- package/dist/cli/bin.d.cts +1 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +275 -0
- package/dist/cli/config.cjs +347 -0
- package/dist/cli/config.d.cts +33 -0
- package/dist/cli/config.d.ts +33 -0
- package/dist/cli/config.js +285 -0
- package/dist/cli/install.cjs +334 -0
- package/dist/cli/install.d.cts +62 -0
- package/dist/cli/install.d.ts +62 -0
- package/dist/cli/install.js +316 -0
- package/dist/cli/whisper-server.cjs +172 -0
- package/dist/cli/whisper-server.d.cts +24 -0
- package/dist/cli/whisper-server.d.ts +24 -0
- package/dist/cli/whisper-server.js +152 -0
- package/dist/config.cjs +60 -0
- package/dist/config.d.cts +12 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.js +32 -0
- package/dist/convert.cjs +88 -0
- package/dist/convert.d.cts +12 -0
- package/dist/convert.d.ts +12 -0
- package/dist/convert.js +63 -0
- package/dist/encodings/Ascii.cjs +75 -0
- package/dist/encodings/Ascii.d.cts +13 -0
- package/dist/encodings/Ascii.d.ts +13 -0
- package/dist/encodings/Ascii.js +48 -0
- package/dist/encodings/Base64.cjs +155 -0
- package/dist/encodings/Base64.d.cts +5 -0
- package/dist/encodings/Base64.d.ts +5 -0
- package/dist/encodings/Base64.js +129 -0
- package/dist/encodings/TextEncodingsCommon.cjs +16 -0
- package/dist/encodings/TextEncodingsCommon.d.cts +6 -0
- package/dist/encodings/TextEncodingsCommon.d.ts +6 -0
- package/dist/encodings/TextEncodingsCommon.js +0 -0
- package/dist/index.cjs +153 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +140 -0
- package/dist/recognition/AmazonTranscribeSTT.cjs +188 -0
- package/dist/recognition/AmazonTranscribeSTT.d.cts +21 -0
- package/dist/recognition/AmazonTranscribeSTT.d.ts +21 -0
- package/dist/recognition/AmazonTranscribeSTT.js +160 -0
- package/dist/recognition/AzureCognitiveServicesSTT.cjs +124 -0
- package/dist/recognition/AzureCognitiveServicesSTT.d.cts +21 -0
- package/dist/recognition/AzureCognitiveServicesSTT.d.ts +21 -0
- package/dist/recognition/AzureCognitiveServicesSTT.js +95 -0
- package/dist/recognition/DeepgramSTT.cjs +172 -0
- package/dist/recognition/DeepgramSTT.d.cts +23 -0
- package/dist/recognition/DeepgramSTT.d.ts +23 -0
- package/dist/recognition/DeepgramSTT.js +153 -0
- package/dist/recognition/GoogleCloudSTT.cjs +125 -0
- package/dist/recognition/GoogleCloudSTT.d.cts +35 -0
- package/dist/recognition/GoogleCloudSTT.d.ts +35 -0
- package/dist/recognition/GoogleCloudSTT.js +107 -0
- package/dist/recognition/OpenAICloudSTT.cjs +180 -0
- package/dist/recognition/OpenAICloudSTT.d.cts +29 -0
- package/dist/recognition/OpenAICloudSTT.d.ts +29 -0
- package/dist/recognition/OpenAICloudSTT.js +150 -0
- package/dist/recognition/WhisperCppSTT.cjs +296 -0
- package/dist/recognition/WhisperCppSTT.d.cts +40 -0
- package/dist/recognition/WhisperCppSTT.d.ts +40 -0
- package/dist/recognition/WhisperCppSTT.js +275 -0
- package/dist/recognition/WhisperServerSTT.cjs +119 -0
- package/dist/recognition/WhisperServerSTT.d.cts +24 -0
- package/dist/recognition/WhisperServerSTT.d.ts +24 -0
- package/dist/recognition/WhisperServerSTT.js +105 -0
- package/dist/utilities/FileSystem.cjs +54 -0
- package/dist/utilities/FileSystem.d.cts +3 -0
- package/dist/utilities/FileSystem.d.ts +3 -0
- package/dist/utilities/FileSystem.js +20 -0
- package/dist/utilities/Locale.cjs +46 -0
- package/dist/utilities/Locale.d.cts +9 -0
- package/dist/utilities/Locale.d.ts +9 -0
- package/dist/utilities/Locale.js +20 -0
- package/dist/utilities/ObjectUtilities.cjs +41 -0
- package/dist/utilities/ObjectUtilities.d.cts +3 -0
- package/dist/utilities/ObjectUtilities.d.ts +3 -0
- package/dist/utilities/ObjectUtilities.js +7 -0
- package/dist/utilities/Timeline.cjs +120 -0
- package/dist/utilities/Timeline.d.cts +23 -0
- package/dist/utilities/Timeline.d.ts +23 -0
- package/dist/utilities/Timeline.js +94 -0
- package/dist/utilities/Timing.cjs +287 -0
- package/dist/utilities/Timing.d.cts +64 -0
- package/dist/utilities/Timing.d.ts +64 -0
- package/dist/utilities/Timing.js +256 -0
- package/dist/utilities/WhisperTimeline.cjs +344 -0
- package/dist/utilities/WhisperTimeline.d.cts +86 -0
- package/dist/utilities/WhisperTimeline.d.ts +86 -0
- package/dist/utilities/WhisperTimeline.js +313 -0
- package/dist/vad/ActiveGate.cjs +357 -0
- package/dist/vad/ActiveGate.d.cts +53 -0
- package/dist/vad/ActiveGate.d.ts +53 -0
- package/dist/vad/ActiveGate.js +329 -0
- package/dist/vad/ActiveGateOg.cjs +1366 -0
- package/dist/vad/ActiveGateOg.d.cts +33 -0
- package/dist/vad/ActiveGateOg.d.ts +33 -0
- package/dist/vad/ActiveGateOg.js +1341 -0
- package/dist/vad/Silero.cjs +174 -0
- package/dist/vad/Silero.d.cts +25 -0
- package/dist/vad/Silero.d.ts +25 -0
- package/dist/vad/Silero.js +153 -0
- package/package.json +125 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { createReadStream, createWriteStream } from "node:fs";
|
|
3
|
+
import { rm } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { pipeline } from "node:stream/promises";
|
|
7
|
+
import { promisify } from "node:util";
|
|
8
|
+
import { Converter } from "ffmpeg-stream";
|
|
9
|
+
const execFilePromisified = promisify(execFile);
|
|
10
|
+
async function execFileAsync(cmd, args) {
|
|
11
|
+
return execFilePromisified(cmd, args);
|
|
12
|
+
}
|
|
13
|
+
import { getConversionMode } from "../config.js";
|
|
14
|
+
import {
|
|
15
|
+
formatToExtension,
|
|
16
|
+
getTargetFormat,
|
|
17
|
+
needsConversion,
|
|
18
|
+
serviceCapabilities
|
|
19
|
+
} from "./AudioFormat.js";
|
|
20
|
+
import {
|
|
21
|
+
audioSourceFromBuffer,
|
|
22
|
+
audioSourceFromFile,
|
|
23
|
+
toFilePath,
|
|
24
|
+
toReadStream
|
|
25
|
+
} from "./AudioSource.js";
|
|
26
|
+
function getFFmpegFormatOptions(format, sampleRate, channels) {
|
|
27
|
+
const opts = {};
|
|
28
|
+
switch (format) {
|
|
29
|
+
case "wav":
|
|
30
|
+
opts["f"] = "wav";
|
|
31
|
+
opts["acodec"] = "pcm_s16le";
|
|
32
|
+
break;
|
|
33
|
+
case "flac":
|
|
34
|
+
opts["f"] = "flac";
|
|
35
|
+
opts["acodec"] = "flac";
|
|
36
|
+
break;
|
|
37
|
+
case "opus":
|
|
38
|
+
opts["f"] = "ogg";
|
|
39
|
+
opts["acodec"] = "libopus";
|
|
40
|
+
break;
|
|
41
|
+
case "ogg":
|
|
42
|
+
opts["f"] = "ogg";
|
|
43
|
+
opts["acodec"] = "libvorbis";
|
|
44
|
+
break;
|
|
45
|
+
case "mp3":
|
|
46
|
+
opts["f"] = "mp3";
|
|
47
|
+
opts["acodec"] = "libmp3lame";
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
opts["f"] = format;
|
|
51
|
+
}
|
|
52
|
+
if (sampleRate) {
|
|
53
|
+
opts["ar"] = String(sampleRate);
|
|
54
|
+
}
|
|
55
|
+
if (channels) {
|
|
56
|
+
opts["ac"] = String(channels);
|
|
57
|
+
}
|
|
58
|
+
return opts;
|
|
59
|
+
}
|
|
60
|
+
function getFFmpegInputFormat(format) {
|
|
61
|
+
switch (format) {
|
|
62
|
+
case "pcm":
|
|
63
|
+
return { f: "s16le", ar: "16000", ac: "1" };
|
|
64
|
+
default:
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function convertToFile(source, options) {
|
|
69
|
+
const tempPath = join(
|
|
70
|
+
tmpdir(),
|
|
71
|
+
`audio-convert-${Date.now()}${formatToExtension(options.targetFormat)}`
|
|
72
|
+
);
|
|
73
|
+
const converter = new Converter();
|
|
74
|
+
const inputPath = toFilePath(source);
|
|
75
|
+
if (inputPath) {
|
|
76
|
+
converter.createInputFromFile(inputPath);
|
|
77
|
+
} else {
|
|
78
|
+
const inputOpts = getFFmpegInputFormat(source.format);
|
|
79
|
+
const inputStream = converter.createInputStream(inputOpts);
|
|
80
|
+
const readable = toReadStream(source);
|
|
81
|
+
readable.pipe(inputStream);
|
|
82
|
+
}
|
|
83
|
+
const outputOpts = getFFmpegFormatOptions(
|
|
84
|
+
options.targetFormat,
|
|
85
|
+
options.sampleRate,
|
|
86
|
+
options.channels
|
|
87
|
+
);
|
|
88
|
+
converter.createOutputToFile(tempPath, outputOpts);
|
|
89
|
+
await converter.run();
|
|
90
|
+
return {
|
|
91
|
+
source: audioSourceFromFile(tempPath, options.targetFormat),
|
|
92
|
+
cleanup: async () => {
|
|
93
|
+
await rm(tempPath, { force: true }).catch(() => {
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async function convertToBuffer(source, options) {
|
|
99
|
+
const converter = new Converter();
|
|
100
|
+
const inputPath = toFilePath(source);
|
|
101
|
+
if (inputPath) {
|
|
102
|
+
converter.createInputFromFile(inputPath);
|
|
103
|
+
} else {
|
|
104
|
+
const inputOpts = getFFmpegInputFormat(source.format);
|
|
105
|
+
const inputStream = converter.createInputStream(inputOpts);
|
|
106
|
+
const readable = toReadStream(source);
|
|
107
|
+
readable.pipe(inputStream);
|
|
108
|
+
}
|
|
109
|
+
const outputOpts = getFFmpegFormatOptions(
|
|
110
|
+
options.targetFormat,
|
|
111
|
+
options.sampleRate,
|
|
112
|
+
options.channels
|
|
113
|
+
);
|
|
114
|
+
const outputStream = converter.createOutputStream(outputOpts);
|
|
115
|
+
const chunks = [];
|
|
116
|
+
outputStream.on("data", (chunk) => chunks.push(chunk));
|
|
117
|
+
const bufferPromise = new Promise((resolve, reject) => {
|
|
118
|
+
outputStream.on("end", () => {
|
|
119
|
+
resolve(Buffer.concat(chunks));
|
|
120
|
+
});
|
|
121
|
+
outputStream.on("error", reject);
|
|
122
|
+
});
|
|
123
|
+
await converter.run();
|
|
124
|
+
const buffer = await bufferPromise;
|
|
125
|
+
return {
|
|
126
|
+
source: audioSourceFromBuffer(buffer, options.targetFormat),
|
|
127
|
+
cleanup: async () => {
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function convertToStream(source, options) {
|
|
132
|
+
const converter = new Converter();
|
|
133
|
+
const inputPath = toFilePath(source);
|
|
134
|
+
if (inputPath) {
|
|
135
|
+
converter.createInputFromFile(inputPath);
|
|
136
|
+
} else {
|
|
137
|
+
const inputOpts = getFFmpegInputFormat(source.format);
|
|
138
|
+
const inputStream = converter.createInputStream(inputOpts);
|
|
139
|
+
const readable = toReadStream(source);
|
|
140
|
+
readable.pipe(inputStream);
|
|
141
|
+
}
|
|
142
|
+
const outputOpts = getFFmpegFormatOptions(
|
|
143
|
+
options.targetFormat,
|
|
144
|
+
options.sampleRate,
|
|
145
|
+
options.channels
|
|
146
|
+
);
|
|
147
|
+
const outputStream = converter.createOutputStream(outputOpts);
|
|
148
|
+
return {
|
|
149
|
+
stream: outputStream,
|
|
150
|
+
runConversion: () => converter.run()
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
async function prepareForService(source, options) {
|
|
154
|
+
const caps = serviceCapabilities[options.service];
|
|
155
|
+
if (!caps) {
|
|
156
|
+
throw new Error(`Unknown service: ${options.service}`);
|
|
157
|
+
}
|
|
158
|
+
const inputFormat = source.format;
|
|
159
|
+
const requiresConversion = needsConversion(inputFormat, options.service);
|
|
160
|
+
const targetFormat = getTargetFormat(inputFormat, options.service);
|
|
161
|
+
if (!requiresConversion) {
|
|
162
|
+
if (caps.requiresFile && source.type !== "file") {
|
|
163
|
+
return writeToTempFile(source);
|
|
164
|
+
}
|
|
165
|
+
return { source, cleanup: async () => {
|
|
166
|
+
} };
|
|
167
|
+
}
|
|
168
|
+
const conversionOptions = {
|
|
169
|
+
targetFormat,
|
|
170
|
+
sampleRate: caps.preferredSampleRate,
|
|
171
|
+
channels: caps.preferredChannels
|
|
172
|
+
};
|
|
173
|
+
if (caps.requiresFile || options.preferFile) {
|
|
174
|
+
return convertToFile(source, conversionOptions);
|
|
175
|
+
}
|
|
176
|
+
if (caps.requiresBase64) {
|
|
177
|
+
return convertToBuffer(source, conversionOptions);
|
|
178
|
+
}
|
|
179
|
+
return convertToFile(source, conversionOptions);
|
|
180
|
+
}
|
|
181
|
+
async function writeToTempFile(source) {
|
|
182
|
+
const tempPath = join(
|
|
183
|
+
tmpdir(),
|
|
184
|
+
`audio-temp-${Date.now()}${formatToExtension(source.format)}`
|
|
185
|
+
);
|
|
186
|
+
const readable = toReadStream(source);
|
|
187
|
+
const writable = createWriteStream(tempPath);
|
|
188
|
+
await pipeline(readable, writable);
|
|
189
|
+
return {
|
|
190
|
+
source: audioSourceFromFile(tempPath, source.format),
|
|
191
|
+
cleanup: async () => {
|
|
192
|
+
await rm(tempPath, { force: true }).catch(() => {
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
async function prepareWavForService(source, options = {}) {
|
|
198
|
+
if (source.format === "wav" && source.type === "file") {
|
|
199
|
+
return { source, cleanup: async () => {
|
|
200
|
+
} };
|
|
201
|
+
}
|
|
202
|
+
return convertToFile(source, {
|
|
203
|
+
targetFormat: "wav",
|
|
204
|
+
sampleRate: options.sampleRate ?? 16e3,
|
|
205
|
+
channels: options.channels ?? 1
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function createStreamingConversion(source, options) {
|
|
209
|
+
const { stream, runConversion } = convertToStream(source, options);
|
|
210
|
+
return { stream, start: runConversion };
|
|
211
|
+
}
|
|
212
|
+
async function createStreamForUpload(options) {
|
|
213
|
+
const mode = options.mode ?? getConversionMode();
|
|
214
|
+
const needsConvert = options.source.format !== options.targetFormat;
|
|
215
|
+
if (!needsConvert) {
|
|
216
|
+
const stream = toReadStream(options.source);
|
|
217
|
+
return {
|
|
218
|
+
stream,
|
|
219
|
+
format: options.source.format,
|
|
220
|
+
cleanup: async () => {
|
|
221
|
+
},
|
|
222
|
+
mode
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (mode === "file-first") {
|
|
226
|
+
const tempPath = join(
|
|
227
|
+
tmpdir(),
|
|
228
|
+
`upload-${Date.now()}${formatToExtension(options.targetFormat)}`
|
|
229
|
+
);
|
|
230
|
+
const converter2 = new Converter();
|
|
231
|
+
const inputPath2 = toFilePath(options.source);
|
|
232
|
+
if (inputPath2) {
|
|
233
|
+
converter2.createInputFromFile(inputPath2);
|
|
234
|
+
} else {
|
|
235
|
+
const inputOpts = getFFmpegInputFormat(options.source.format);
|
|
236
|
+
const inputStream = converter2.createInputStream(inputOpts);
|
|
237
|
+
const readable = toReadStream(options.source);
|
|
238
|
+
readable.pipe(inputStream);
|
|
239
|
+
}
|
|
240
|
+
const outputOpts2 = getFFmpegFormatOptions(
|
|
241
|
+
options.targetFormat,
|
|
242
|
+
options.sampleRate,
|
|
243
|
+
options.channels
|
|
244
|
+
);
|
|
245
|
+
converter2.createOutputToFile(tempPath, outputOpts2);
|
|
246
|
+
await converter2.run();
|
|
247
|
+
const stream = createReadStream(tempPath);
|
|
248
|
+
return {
|
|
249
|
+
stream,
|
|
250
|
+
format: options.targetFormat,
|
|
251
|
+
cleanup: async () => {
|
|
252
|
+
await rm(tempPath, { force: true }).catch(() => {
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
mode
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
const converter = new Converter();
|
|
259
|
+
const inputPath = toFilePath(options.source);
|
|
260
|
+
if (inputPath) {
|
|
261
|
+
converter.createInputFromFile(inputPath);
|
|
262
|
+
} else {
|
|
263
|
+
const inputOpts = getFFmpegInputFormat(options.source.format);
|
|
264
|
+
const inputStream = converter.createInputStream(inputOpts);
|
|
265
|
+
const readable = toReadStream(options.source);
|
|
266
|
+
readable.pipe(inputStream);
|
|
267
|
+
}
|
|
268
|
+
const outputOpts = getFFmpegFormatOptions(
|
|
269
|
+
options.targetFormat,
|
|
270
|
+
options.sampleRate,
|
|
271
|
+
options.channels
|
|
272
|
+
);
|
|
273
|
+
const outputStream = converter.createOutputStream(outputOpts);
|
|
274
|
+
return {
|
|
275
|
+
stream: outputStream,
|
|
276
|
+
format: options.targetFormat,
|
|
277
|
+
cleanup: async () => {
|
|
278
|
+
},
|
|
279
|
+
start: () => converter.run(),
|
|
280
|
+
mode
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
async function getAudioDuration(filePath) {
|
|
284
|
+
const { stdout } = await execFileAsync("ffprobe", [
|
|
285
|
+
"-v",
|
|
286
|
+
"quiet",
|
|
287
|
+
"-show_entries",
|
|
288
|
+
"format=duration",
|
|
289
|
+
"-of",
|
|
290
|
+
"default=noprint_wrappers=1:nokey=1",
|
|
291
|
+
filePath
|
|
292
|
+
]);
|
|
293
|
+
const duration = parseFloat(stdout.trim());
|
|
294
|
+
if (Number.isNaN(duration)) {
|
|
295
|
+
throw new Error(
|
|
296
|
+
`Failed to parse audio duration from ffprobe output: ${stdout}`
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return duration;
|
|
300
|
+
}
|
|
301
|
+
export {
|
|
302
|
+
convertToBuffer,
|
|
303
|
+
convertToFile,
|
|
304
|
+
convertToStream,
|
|
305
|
+
createStreamForUpload,
|
|
306
|
+
createStreamingConversion,
|
|
307
|
+
getAudioDuration,
|
|
308
|
+
prepareForService,
|
|
309
|
+
prepareWavForService
|
|
310
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var AudioFormat_exports = {};
|
|
20
|
+
__export(AudioFormat_exports, {
|
|
21
|
+
formatFromExtension: () => formatFromExtension,
|
|
22
|
+
formatToExtension: () => formatToExtension,
|
|
23
|
+
getTargetFormat: () => getTargetFormat,
|
|
24
|
+
needsConversion: () => needsConversion,
|
|
25
|
+
serviceCapabilities: () => serviceCapabilities
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(AudioFormat_exports);
|
|
28
|
+
var import_node_path = require("node:path");
|
|
29
|
+
const extensionToFormat = {
|
|
30
|
+
".wav": "wav",
|
|
31
|
+
".wave": "wav",
|
|
32
|
+
".flac": "flac",
|
|
33
|
+
".opus": "opus",
|
|
34
|
+
".ogg": "ogg",
|
|
35
|
+
".mp3": "mp3",
|
|
36
|
+
".webm": "webm",
|
|
37
|
+
".m4a": "m4a",
|
|
38
|
+
".aac": "aac",
|
|
39
|
+
".pcm": "pcm",
|
|
40
|
+
".mp4": "mp4"
|
|
41
|
+
};
|
|
42
|
+
function formatFromExtension(filepath) {
|
|
43
|
+
const ext = (0, import_node_path.extname)(filepath).toLowerCase();
|
|
44
|
+
return extensionToFormat[ext] ?? null;
|
|
45
|
+
}
|
|
46
|
+
function formatToExtension(format) {
|
|
47
|
+
switch (format) {
|
|
48
|
+
case "wav":
|
|
49
|
+
return ".wav";
|
|
50
|
+
case "flac":
|
|
51
|
+
return ".flac";
|
|
52
|
+
case "opus":
|
|
53
|
+
return ".opus";
|
|
54
|
+
case "ogg":
|
|
55
|
+
return ".ogg";
|
|
56
|
+
case "mp3":
|
|
57
|
+
return ".mp3";
|
|
58
|
+
case "webm":
|
|
59
|
+
return ".webm";
|
|
60
|
+
case "m4a":
|
|
61
|
+
return ".m4a";
|
|
62
|
+
case "aac":
|
|
63
|
+
return ".aac";
|
|
64
|
+
case "pcm":
|
|
65
|
+
return ".pcm";
|
|
66
|
+
case "mp4":
|
|
67
|
+
return ".mp4";
|
|
68
|
+
default:
|
|
69
|
+
return ".unknown";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const serviceCapabilities = {
|
|
73
|
+
"whisper.cpp": {
|
|
74
|
+
acceptsFormats: ["wav", "flac", "ogg", "mp3"],
|
|
75
|
+
preferredFormat: "wav",
|
|
76
|
+
requiresFile: true,
|
|
77
|
+
supportsStreaming: false,
|
|
78
|
+
requiresBase64: false,
|
|
79
|
+
preferredSampleRate: 16e3,
|
|
80
|
+
preferredChannels: 1
|
|
81
|
+
},
|
|
82
|
+
"whisper-server": {
|
|
83
|
+
acceptsFormats: ["wav", "flac", "ogg", "mp3"],
|
|
84
|
+
preferredFormat: "wav",
|
|
85
|
+
requiresFile: true,
|
|
86
|
+
supportsStreaming: false,
|
|
87
|
+
requiresBase64: false,
|
|
88
|
+
preferredSampleRate: 16e3,
|
|
89
|
+
preferredChannels: 1
|
|
90
|
+
},
|
|
91
|
+
"openai-cloud": {
|
|
92
|
+
acceptsFormats: ["wav", "flac", "mp3", "m4a", "ogg", "webm"],
|
|
93
|
+
preferredFormat: "mp3",
|
|
94
|
+
requiresFile: false,
|
|
95
|
+
supportsStreaming: true,
|
|
96
|
+
requiresBase64: false
|
|
97
|
+
},
|
|
98
|
+
"google-cloud": {
|
|
99
|
+
acceptsFormats: ["wav", "flac", "mp3", "ogg", "opus", "webm"],
|
|
100
|
+
preferredFormat: "flac",
|
|
101
|
+
requiresFile: false,
|
|
102
|
+
supportsStreaming: false,
|
|
103
|
+
requiresBase64: true,
|
|
104
|
+
preferredSampleRate: 16e3,
|
|
105
|
+
preferredChannels: 1
|
|
106
|
+
},
|
|
107
|
+
"microsoft-azure": {
|
|
108
|
+
acceptsFormats: ["wav"],
|
|
109
|
+
preferredFormat: "wav",
|
|
110
|
+
requiresFile: false,
|
|
111
|
+
supportsStreaming: true,
|
|
112
|
+
requiresBase64: false,
|
|
113
|
+
preferredSampleRate: 16e3,
|
|
114
|
+
preferredChannels: 1
|
|
115
|
+
},
|
|
116
|
+
"amazon-transcribe": {
|
|
117
|
+
acceptsFormats: ["flac", "opus", "ogg"],
|
|
118
|
+
preferredFormat: "flac",
|
|
119
|
+
requiresFile: false,
|
|
120
|
+
supportsStreaming: true,
|
|
121
|
+
requiresBase64: false,
|
|
122
|
+
preferredSampleRate: 16e3,
|
|
123
|
+
preferredChannels: 1
|
|
124
|
+
},
|
|
125
|
+
deepgram: {
|
|
126
|
+
acceptsFormats: ["wav", "flac", "mp3", "opus", "ogg", "webm", "m4a"],
|
|
127
|
+
preferredFormat: "wav",
|
|
128
|
+
requiresFile: false,
|
|
129
|
+
supportsStreaming: true,
|
|
130
|
+
requiresBase64: false
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
function needsConversion(inputFormat, service) {
|
|
134
|
+
const caps = serviceCapabilities[service];
|
|
135
|
+
if (!caps) return true;
|
|
136
|
+
return !caps.acceptsFormats.includes(inputFormat);
|
|
137
|
+
}
|
|
138
|
+
function getTargetFormat(inputFormat, service) {
|
|
139
|
+
const caps = serviceCapabilities[service];
|
|
140
|
+
if (!caps) return "wav";
|
|
141
|
+
if (caps.acceptsFormats.includes(inputFormat)) return inputFormat;
|
|
142
|
+
return caps.preferredFormat;
|
|
143
|
+
}
|
|
144
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
145
|
+
0 && (module.exports = {
|
|
146
|
+
formatFromExtension,
|
|
147
|
+
formatToExtension,
|
|
148
|
+
getTargetFormat,
|
|
149
|
+
needsConversion,
|
|
150
|
+
serviceCapabilities
|
|
151
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type AudioFormat = "unknown" | "wav" | "flac" | "opus" | "ogg" | "mp3" | "webm" | "m4a" | "aac" | "pcm" | "mp4";
|
|
2
|
+
type AudioEncoding = "pcm_s16le" | "flac" | "opus" | "mp3" | "aac";
|
|
3
|
+
interface AudioFormatInfo {
|
|
4
|
+
format: AudioFormat;
|
|
5
|
+
sampleRate?: number;
|
|
6
|
+
channels?: number;
|
|
7
|
+
bitDepth?: number;
|
|
8
|
+
}
|
|
9
|
+
declare function formatFromExtension(filepath: string): AudioFormat | null;
|
|
10
|
+
declare function formatToExtension(format: AudioFormat): string;
|
|
11
|
+
interface ServiceCapabilities {
|
|
12
|
+
acceptsFormats: AudioFormat[];
|
|
13
|
+
preferredFormat: AudioFormat;
|
|
14
|
+
requiresFile: boolean;
|
|
15
|
+
supportsStreaming: boolean;
|
|
16
|
+
requiresBase64: boolean;
|
|
17
|
+
maxSampleRate?: number;
|
|
18
|
+
preferredSampleRate?: number;
|
|
19
|
+
preferredChannels?: number;
|
|
20
|
+
}
|
|
21
|
+
declare const serviceCapabilities: Record<string, ServiceCapabilities>;
|
|
22
|
+
declare function needsConversion(inputFormat: AudioFormat, service: string): boolean;
|
|
23
|
+
declare function getTargetFormat(inputFormat: AudioFormat, service: string): AudioFormat;
|
|
24
|
+
|
|
25
|
+
export { type AudioEncoding, type AudioFormat, type AudioFormatInfo, type ServiceCapabilities, formatFromExtension, formatToExtension, getTargetFormat, needsConversion, serviceCapabilities };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type AudioFormat = "unknown" | "wav" | "flac" | "opus" | "ogg" | "mp3" | "webm" | "m4a" | "aac" | "pcm" | "mp4";
|
|
2
|
+
type AudioEncoding = "pcm_s16le" | "flac" | "opus" | "mp3" | "aac";
|
|
3
|
+
interface AudioFormatInfo {
|
|
4
|
+
format: AudioFormat;
|
|
5
|
+
sampleRate?: number;
|
|
6
|
+
channels?: number;
|
|
7
|
+
bitDepth?: number;
|
|
8
|
+
}
|
|
9
|
+
declare function formatFromExtension(filepath: string): AudioFormat | null;
|
|
10
|
+
declare function formatToExtension(format: AudioFormat): string;
|
|
11
|
+
interface ServiceCapabilities {
|
|
12
|
+
acceptsFormats: AudioFormat[];
|
|
13
|
+
preferredFormat: AudioFormat;
|
|
14
|
+
requiresFile: boolean;
|
|
15
|
+
supportsStreaming: boolean;
|
|
16
|
+
requiresBase64: boolean;
|
|
17
|
+
maxSampleRate?: number;
|
|
18
|
+
preferredSampleRate?: number;
|
|
19
|
+
preferredChannels?: number;
|
|
20
|
+
}
|
|
21
|
+
declare const serviceCapabilities: Record<string, ServiceCapabilities>;
|
|
22
|
+
declare function needsConversion(inputFormat: AudioFormat, service: string): boolean;
|
|
23
|
+
declare function getTargetFormat(inputFormat: AudioFormat, service: string): AudioFormat;
|
|
24
|
+
|
|
25
|
+
export { type AudioEncoding, type AudioFormat, type AudioFormatInfo, type ServiceCapabilities, formatFromExtension, formatToExtension, getTargetFormat, needsConversion, serviceCapabilities };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { extname } from "node:path";
|
|
2
|
+
const extensionToFormat = {
|
|
3
|
+
".wav": "wav",
|
|
4
|
+
".wave": "wav",
|
|
5
|
+
".flac": "flac",
|
|
6
|
+
".opus": "opus",
|
|
7
|
+
".ogg": "ogg",
|
|
8
|
+
".mp3": "mp3",
|
|
9
|
+
".webm": "webm",
|
|
10
|
+
".m4a": "m4a",
|
|
11
|
+
".aac": "aac",
|
|
12
|
+
".pcm": "pcm",
|
|
13
|
+
".mp4": "mp4"
|
|
14
|
+
};
|
|
15
|
+
function formatFromExtension(filepath) {
|
|
16
|
+
const ext = extname(filepath).toLowerCase();
|
|
17
|
+
return extensionToFormat[ext] ?? null;
|
|
18
|
+
}
|
|
19
|
+
function formatToExtension(format) {
|
|
20
|
+
switch (format) {
|
|
21
|
+
case "wav":
|
|
22
|
+
return ".wav";
|
|
23
|
+
case "flac":
|
|
24
|
+
return ".flac";
|
|
25
|
+
case "opus":
|
|
26
|
+
return ".opus";
|
|
27
|
+
case "ogg":
|
|
28
|
+
return ".ogg";
|
|
29
|
+
case "mp3":
|
|
30
|
+
return ".mp3";
|
|
31
|
+
case "webm":
|
|
32
|
+
return ".webm";
|
|
33
|
+
case "m4a":
|
|
34
|
+
return ".m4a";
|
|
35
|
+
case "aac":
|
|
36
|
+
return ".aac";
|
|
37
|
+
case "pcm":
|
|
38
|
+
return ".pcm";
|
|
39
|
+
case "mp4":
|
|
40
|
+
return ".mp4";
|
|
41
|
+
default:
|
|
42
|
+
return ".unknown";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const serviceCapabilities = {
|
|
46
|
+
"whisper.cpp": {
|
|
47
|
+
acceptsFormats: ["wav", "flac", "ogg", "mp3"],
|
|
48
|
+
preferredFormat: "wav",
|
|
49
|
+
requiresFile: true,
|
|
50
|
+
supportsStreaming: false,
|
|
51
|
+
requiresBase64: false,
|
|
52
|
+
preferredSampleRate: 16e3,
|
|
53
|
+
preferredChannels: 1
|
|
54
|
+
},
|
|
55
|
+
"whisper-server": {
|
|
56
|
+
acceptsFormats: ["wav", "flac", "ogg", "mp3"],
|
|
57
|
+
preferredFormat: "wav",
|
|
58
|
+
requiresFile: true,
|
|
59
|
+
supportsStreaming: false,
|
|
60
|
+
requiresBase64: false,
|
|
61
|
+
preferredSampleRate: 16e3,
|
|
62
|
+
preferredChannels: 1
|
|
63
|
+
},
|
|
64
|
+
"openai-cloud": {
|
|
65
|
+
acceptsFormats: ["wav", "flac", "mp3", "m4a", "ogg", "webm"],
|
|
66
|
+
preferredFormat: "mp3",
|
|
67
|
+
requiresFile: false,
|
|
68
|
+
supportsStreaming: true,
|
|
69
|
+
requiresBase64: false
|
|
70
|
+
},
|
|
71
|
+
"google-cloud": {
|
|
72
|
+
acceptsFormats: ["wav", "flac", "mp3", "ogg", "opus", "webm"],
|
|
73
|
+
preferredFormat: "flac",
|
|
74
|
+
requiresFile: false,
|
|
75
|
+
supportsStreaming: false,
|
|
76
|
+
requiresBase64: true,
|
|
77
|
+
preferredSampleRate: 16e3,
|
|
78
|
+
preferredChannels: 1
|
|
79
|
+
},
|
|
80
|
+
"microsoft-azure": {
|
|
81
|
+
acceptsFormats: ["wav"],
|
|
82
|
+
preferredFormat: "wav",
|
|
83
|
+
requiresFile: false,
|
|
84
|
+
supportsStreaming: true,
|
|
85
|
+
requiresBase64: false,
|
|
86
|
+
preferredSampleRate: 16e3,
|
|
87
|
+
preferredChannels: 1
|
|
88
|
+
},
|
|
89
|
+
"amazon-transcribe": {
|
|
90
|
+
acceptsFormats: ["flac", "opus", "ogg"],
|
|
91
|
+
preferredFormat: "flac",
|
|
92
|
+
requiresFile: false,
|
|
93
|
+
supportsStreaming: true,
|
|
94
|
+
requiresBase64: false,
|
|
95
|
+
preferredSampleRate: 16e3,
|
|
96
|
+
preferredChannels: 1
|
|
97
|
+
},
|
|
98
|
+
deepgram: {
|
|
99
|
+
acceptsFormats: ["wav", "flac", "mp3", "opus", "ogg", "webm", "m4a"],
|
|
100
|
+
preferredFormat: "wav",
|
|
101
|
+
requiresFile: false,
|
|
102
|
+
supportsStreaming: true,
|
|
103
|
+
requiresBase64: false
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
function needsConversion(inputFormat, service) {
|
|
107
|
+
const caps = serviceCapabilities[service];
|
|
108
|
+
if (!caps) return true;
|
|
109
|
+
return !caps.acceptsFormats.includes(inputFormat);
|
|
110
|
+
}
|
|
111
|
+
function getTargetFormat(inputFormat, service) {
|
|
112
|
+
const caps = serviceCapabilities[service];
|
|
113
|
+
if (!caps) return "wav";
|
|
114
|
+
if (caps.acceptsFormats.includes(inputFormat)) return inputFormat;
|
|
115
|
+
return caps.preferredFormat;
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
formatFromExtension,
|
|
119
|
+
formatToExtension,
|
|
120
|
+
getTargetFormat,
|
|
121
|
+
needsConversion,
|
|
122
|
+
serviceCapabilities
|
|
123
|
+
};
|