@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.
Files changed (135) hide show
  1. package/LICENSE.md +611 -0
  2. package/README.md +18 -0
  3. package/dist/api/APIOptions.cjs +16 -0
  4. package/dist/api/APIOptions.d.cts +18 -0
  5. package/dist/api/APIOptions.d.ts +18 -0
  6. package/dist/api/APIOptions.js +0 -0
  7. package/dist/api/Recognition.cjs +263 -0
  8. package/dist/api/Recognition.d.cts +77 -0
  9. package/dist/api/Recognition.d.ts +77 -0
  10. package/dist/api/Recognition.js +233 -0
  11. package/dist/api/VoiceActivityDetection.cjs +77 -0
  12. package/dist/api/VoiceActivityDetection.d.cts +24 -0
  13. package/dist/api/VoiceActivityDetection.d.ts +24 -0
  14. package/dist/api/VoiceActivityDetection.js +43 -0
  15. package/dist/audio/AudioConverter.cjs +331 -0
  16. package/dist/audio/AudioConverter.d.cts +53 -0
  17. package/dist/audio/AudioConverter.d.ts +53 -0
  18. package/dist/audio/AudioConverter.js +310 -0
  19. package/dist/audio/AudioFormat.cjs +151 -0
  20. package/dist/audio/AudioFormat.d.cts +25 -0
  21. package/dist/audio/AudioFormat.d.ts +25 -0
  22. package/dist/audio/AudioFormat.js +123 -0
  23. package/dist/audio/AudioSource.cjs +119 -0
  24. package/dist/audio/AudioSource.d.cts +33 -0
  25. package/dist/audio/AudioSource.d.ts +33 -0
  26. package/dist/audio/AudioSource.js +88 -0
  27. package/dist/audio/index.cjs +74 -0
  28. package/dist/audio/index.d.cts +6 -0
  29. package/dist/audio/index.d.ts +6 -0
  30. package/dist/audio/index.js +54 -0
  31. package/dist/cli/bin.cjs +277 -0
  32. package/dist/cli/bin.d.cts +1 -0
  33. package/dist/cli/bin.d.ts +1 -0
  34. package/dist/cli/bin.js +275 -0
  35. package/dist/cli/config.cjs +347 -0
  36. package/dist/cli/config.d.cts +33 -0
  37. package/dist/cli/config.d.ts +33 -0
  38. package/dist/cli/config.js +285 -0
  39. package/dist/cli/install.cjs +334 -0
  40. package/dist/cli/install.d.cts +62 -0
  41. package/dist/cli/install.d.ts +62 -0
  42. package/dist/cli/install.js +316 -0
  43. package/dist/cli/whisper-server.cjs +172 -0
  44. package/dist/cli/whisper-server.d.cts +24 -0
  45. package/dist/cli/whisper-server.d.ts +24 -0
  46. package/dist/cli/whisper-server.js +152 -0
  47. package/dist/config.cjs +60 -0
  48. package/dist/config.d.cts +12 -0
  49. package/dist/config.d.ts +12 -0
  50. package/dist/config.js +32 -0
  51. package/dist/convert.cjs +88 -0
  52. package/dist/convert.d.cts +12 -0
  53. package/dist/convert.d.ts +12 -0
  54. package/dist/convert.js +63 -0
  55. package/dist/encodings/Ascii.cjs +75 -0
  56. package/dist/encodings/Ascii.d.cts +13 -0
  57. package/dist/encodings/Ascii.d.ts +13 -0
  58. package/dist/encodings/Ascii.js +48 -0
  59. package/dist/encodings/Base64.cjs +155 -0
  60. package/dist/encodings/Base64.d.cts +5 -0
  61. package/dist/encodings/Base64.d.ts +5 -0
  62. package/dist/encodings/Base64.js +129 -0
  63. package/dist/encodings/TextEncodingsCommon.cjs +16 -0
  64. package/dist/encodings/TextEncodingsCommon.d.cts +6 -0
  65. package/dist/encodings/TextEncodingsCommon.d.ts +6 -0
  66. package/dist/encodings/TextEncodingsCommon.js +0 -0
  67. package/dist/index.cjs +153 -0
  68. package/dist/index.d.cts +15 -0
  69. package/dist/index.d.ts +15 -0
  70. package/dist/index.js +140 -0
  71. package/dist/recognition/AmazonTranscribeSTT.cjs +188 -0
  72. package/dist/recognition/AmazonTranscribeSTT.d.cts +21 -0
  73. package/dist/recognition/AmazonTranscribeSTT.d.ts +21 -0
  74. package/dist/recognition/AmazonTranscribeSTT.js +160 -0
  75. package/dist/recognition/AzureCognitiveServicesSTT.cjs +124 -0
  76. package/dist/recognition/AzureCognitiveServicesSTT.d.cts +21 -0
  77. package/dist/recognition/AzureCognitiveServicesSTT.d.ts +21 -0
  78. package/dist/recognition/AzureCognitiveServicesSTT.js +95 -0
  79. package/dist/recognition/DeepgramSTT.cjs +172 -0
  80. package/dist/recognition/DeepgramSTT.d.cts +23 -0
  81. package/dist/recognition/DeepgramSTT.d.ts +23 -0
  82. package/dist/recognition/DeepgramSTT.js +153 -0
  83. package/dist/recognition/GoogleCloudSTT.cjs +125 -0
  84. package/dist/recognition/GoogleCloudSTT.d.cts +35 -0
  85. package/dist/recognition/GoogleCloudSTT.d.ts +35 -0
  86. package/dist/recognition/GoogleCloudSTT.js +107 -0
  87. package/dist/recognition/OpenAICloudSTT.cjs +180 -0
  88. package/dist/recognition/OpenAICloudSTT.d.cts +29 -0
  89. package/dist/recognition/OpenAICloudSTT.d.ts +29 -0
  90. package/dist/recognition/OpenAICloudSTT.js +150 -0
  91. package/dist/recognition/WhisperCppSTT.cjs +296 -0
  92. package/dist/recognition/WhisperCppSTT.d.cts +40 -0
  93. package/dist/recognition/WhisperCppSTT.d.ts +40 -0
  94. package/dist/recognition/WhisperCppSTT.js +275 -0
  95. package/dist/recognition/WhisperServerSTT.cjs +119 -0
  96. package/dist/recognition/WhisperServerSTT.d.cts +24 -0
  97. package/dist/recognition/WhisperServerSTT.d.ts +24 -0
  98. package/dist/recognition/WhisperServerSTT.js +105 -0
  99. package/dist/utilities/FileSystem.cjs +54 -0
  100. package/dist/utilities/FileSystem.d.cts +3 -0
  101. package/dist/utilities/FileSystem.d.ts +3 -0
  102. package/dist/utilities/FileSystem.js +20 -0
  103. package/dist/utilities/Locale.cjs +46 -0
  104. package/dist/utilities/Locale.d.cts +9 -0
  105. package/dist/utilities/Locale.d.ts +9 -0
  106. package/dist/utilities/Locale.js +20 -0
  107. package/dist/utilities/ObjectUtilities.cjs +41 -0
  108. package/dist/utilities/ObjectUtilities.d.cts +3 -0
  109. package/dist/utilities/ObjectUtilities.d.ts +3 -0
  110. package/dist/utilities/ObjectUtilities.js +7 -0
  111. package/dist/utilities/Timeline.cjs +120 -0
  112. package/dist/utilities/Timeline.d.cts +23 -0
  113. package/dist/utilities/Timeline.d.ts +23 -0
  114. package/dist/utilities/Timeline.js +94 -0
  115. package/dist/utilities/Timing.cjs +287 -0
  116. package/dist/utilities/Timing.d.cts +64 -0
  117. package/dist/utilities/Timing.d.ts +64 -0
  118. package/dist/utilities/Timing.js +256 -0
  119. package/dist/utilities/WhisperTimeline.cjs +344 -0
  120. package/dist/utilities/WhisperTimeline.d.cts +86 -0
  121. package/dist/utilities/WhisperTimeline.d.ts +86 -0
  122. package/dist/utilities/WhisperTimeline.js +313 -0
  123. package/dist/vad/ActiveGate.cjs +357 -0
  124. package/dist/vad/ActiveGate.d.cts +53 -0
  125. package/dist/vad/ActiveGate.d.ts +53 -0
  126. package/dist/vad/ActiveGate.js +329 -0
  127. package/dist/vad/ActiveGateOg.cjs +1366 -0
  128. package/dist/vad/ActiveGateOg.d.cts +33 -0
  129. package/dist/vad/ActiveGateOg.d.ts +33 -0
  130. package/dist/vad/ActiveGateOg.js +1341 -0
  131. package/dist/vad/Silero.cjs +174 -0
  132. package/dist/vad/Silero.d.cts +25 -0
  133. package/dist/vad/Silero.d.ts +25 -0
  134. package/dist/vad/Silero.js +153 -0
  135. 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
+ };