@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,77 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var VoiceActivityDetection_exports = {};
30
+ __export(VoiceActivityDetection_exports, {
31
+ detectVoiceActivity: () => detectVoiceActivity
32
+ });
33
+ module.exports = __toCommonJS(VoiceActivityDetection_exports);
34
+ var import_ObjectUtilities = require("../utilities/ObjectUtilities.cjs");
35
+ const defaultVoiceActivityDetectionOptions = {
36
+ engine: "active-gate-og"
37
+ };
38
+ async function detectVoiceActivity(inputPath, options = defaultVoiceActivityDetectionOptions) {
39
+ const opts = (0, import_ObjectUtilities.extendDeep)(defaultVoiceActivityDetectionOptions, options);
40
+ switch (opts.engine) {
41
+ case "silero": {
42
+ const SileroVAD = await import("../vad/Silero.cjs");
43
+ const sileroOpts = "silero" in opts ? opts.silero : void 0;
44
+ return SileroVAD.detectVoiceActivity(inputPath, sileroOpts);
45
+ }
46
+ case "active-gate-og": {
47
+ const ActiveGateOgVAD = await import("../vad/ActiveGateOg.cjs");
48
+ const activeGateOgOpts = "activeGateOg" in opts ? opts.activeGateOg : void 0;
49
+ const timeline = await ActiveGateOgVAD.detectVoiceActivity(
50
+ inputPath,
51
+ activeGateOgOpts
52
+ );
53
+ return timeline.map((seg) => ({
54
+ startTime: seg.startTime,
55
+ endTime: seg.endTime,
56
+ isSpeech: seg.type === "segment" && seg.text === "active"
57
+ }));
58
+ }
59
+ case "active-gate": {
60
+ const ActiveGateVAD = await import("../vad/ActiveGate.cjs");
61
+ const activeGateOpts = "activeGate" in opts ? opts.activeGate : void 0;
62
+ const segments = await ActiveGateVAD.vadFromFile(
63
+ inputPath,
64
+ activeGateOpts
65
+ );
66
+ return segments.map((seg) => ({
67
+ startTime: seg.startTime,
68
+ endTime: seg.endTime,
69
+ isSpeech: seg.isActive
70
+ }));
71
+ }
72
+ }
73
+ }
74
+ // Annotate the CommonJS export names for ESM import in node:
75
+ 0 && (module.exports = {
76
+ detectVoiceActivity
77
+ });
@@ -0,0 +1,24 @@
1
+ import { StreamOptions } from '../vad/ActiveGate.cjs';
2
+ import { AdaptiveGateVADOptions } from '../vad/ActiveGateOg.cjs';
3
+ import { SileroOptions } from '../vad/Silero.cjs';
4
+ import 'node:stream';
5
+ import '../utilities/Timeline.cjs';
6
+
7
+ interface VadSegment {
8
+ startTime: number;
9
+ endTime: number;
10
+ isSpeech: boolean;
11
+ }
12
+ type VoiceActivityDetectionOptions = {
13
+ engine: "silero";
14
+ silero?: SileroOptions;
15
+ } | {
16
+ engine: "active-gate";
17
+ activeGate?: StreamOptions;
18
+ } | {
19
+ engine: "active-gate-og";
20
+ activeGateOg?: AdaptiveGateVADOptions;
21
+ };
22
+ declare function detectVoiceActivity(inputPath: string, options?: VoiceActivityDetectionOptions): Promise<VadSegment[]>;
23
+
24
+ export { type VadSegment, type VoiceActivityDetectionOptions, detectVoiceActivity };
@@ -0,0 +1,24 @@
1
+ import { StreamOptions } from '../vad/ActiveGate.js';
2
+ import { AdaptiveGateVADOptions } from '../vad/ActiveGateOg.js';
3
+ import { SileroOptions } from '../vad/Silero.js';
4
+ import 'node:stream';
5
+ import '../utilities/Timeline.js';
6
+
7
+ interface VadSegment {
8
+ startTime: number;
9
+ endTime: number;
10
+ isSpeech: boolean;
11
+ }
12
+ type VoiceActivityDetectionOptions = {
13
+ engine: "silero";
14
+ silero?: SileroOptions;
15
+ } | {
16
+ engine: "active-gate";
17
+ activeGate?: StreamOptions;
18
+ } | {
19
+ engine: "active-gate-og";
20
+ activeGateOg?: AdaptiveGateVADOptions;
21
+ };
22
+ declare function detectVoiceActivity(inputPath: string, options?: VoiceActivityDetectionOptions): Promise<VadSegment[]>;
23
+
24
+ export { type VadSegment, type VoiceActivityDetectionOptions, detectVoiceActivity };
@@ -0,0 +1,43 @@
1
+ import { extendDeep } from "../utilities/ObjectUtilities.js";
2
+ const defaultVoiceActivityDetectionOptions = {
3
+ engine: "active-gate-og"
4
+ };
5
+ async function detectVoiceActivity(inputPath, options = defaultVoiceActivityDetectionOptions) {
6
+ const opts = extendDeep(defaultVoiceActivityDetectionOptions, options);
7
+ switch (opts.engine) {
8
+ case "silero": {
9
+ const SileroVAD = await import("../vad/Silero.js");
10
+ const sileroOpts = "silero" in opts ? opts.silero : void 0;
11
+ return SileroVAD.detectVoiceActivity(inputPath, sileroOpts);
12
+ }
13
+ case "active-gate-og": {
14
+ const ActiveGateOgVAD = await import("../vad/ActiveGateOg.js");
15
+ const activeGateOgOpts = "activeGateOg" in opts ? opts.activeGateOg : void 0;
16
+ const timeline = await ActiveGateOgVAD.detectVoiceActivity(
17
+ inputPath,
18
+ activeGateOgOpts
19
+ );
20
+ return timeline.map((seg) => ({
21
+ startTime: seg.startTime,
22
+ endTime: seg.endTime,
23
+ isSpeech: seg.type === "segment" && seg.text === "active"
24
+ }));
25
+ }
26
+ case "active-gate": {
27
+ const ActiveGateVAD = await import("../vad/ActiveGate.js");
28
+ const activeGateOpts = "activeGate" in opts ? opts.activeGate : void 0;
29
+ const segments = await ActiveGateVAD.vadFromFile(
30
+ inputPath,
31
+ activeGateOpts
32
+ );
33
+ return segments.map((seg) => ({
34
+ startTime: seg.startTime,
35
+ endTime: seg.endTime,
36
+ isSpeech: seg.isActive
37
+ }));
38
+ }
39
+ }
40
+ }
41
+ export {
42
+ detectVoiceActivity
43
+ };
@@ -0,0 +1,331 @@
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 AudioConverter_exports = {};
20
+ __export(AudioConverter_exports, {
21
+ convertToBuffer: () => convertToBuffer,
22
+ convertToFile: () => convertToFile,
23
+ convertToStream: () => convertToStream,
24
+ createStreamForUpload: () => createStreamForUpload,
25
+ createStreamingConversion: () => createStreamingConversion,
26
+ getAudioDuration: () => getAudioDuration,
27
+ prepareForService: () => prepareForService,
28
+ prepareWavForService: () => prepareWavForService
29
+ });
30
+ module.exports = __toCommonJS(AudioConverter_exports);
31
+ var import_node_child_process = require("node:child_process");
32
+ var import_node_fs = require("node:fs");
33
+ var import_promises = require("node:fs/promises");
34
+ var import_node_os = require("node:os");
35
+ var import_node_path = require("node:path");
36
+ var import_promises2 = require("node:stream/promises");
37
+ var import_node_util = require("node:util");
38
+ var import_ffmpeg_stream = require("ffmpeg-stream");
39
+ var import_config = require("../config.cjs");
40
+ var import_AudioFormat = require("./AudioFormat.cjs");
41
+ var import_AudioSource = require("./AudioSource.cjs");
42
+ const execFilePromisified = (0, import_node_util.promisify)(import_node_child_process.execFile);
43
+ async function execFileAsync(cmd, args) {
44
+ return execFilePromisified(cmd, args);
45
+ }
46
+ function getFFmpegFormatOptions(format, sampleRate, channels) {
47
+ const opts = {};
48
+ switch (format) {
49
+ case "wav":
50
+ opts["f"] = "wav";
51
+ opts["acodec"] = "pcm_s16le";
52
+ break;
53
+ case "flac":
54
+ opts["f"] = "flac";
55
+ opts["acodec"] = "flac";
56
+ break;
57
+ case "opus":
58
+ opts["f"] = "ogg";
59
+ opts["acodec"] = "libopus";
60
+ break;
61
+ case "ogg":
62
+ opts["f"] = "ogg";
63
+ opts["acodec"] = "libvorbis";
64
+ break;
65
+ case "mp3":
66
+ opts["f"] = "mp3";
67
+ opts["acodec"] = "libmp3lame";
68
+ break;
69
+ default:
70
+ opts["f"] = format;
71
+ }
72
+ if (sampleRate) {
73
+ opts["ar"] = String(sampleRate);
74
+ }
75
+ if (channels) {
76
+ opts["ac"] = String(channels);
77
+ }
78
+ return opts;
79
+ }
80
+ function getFFmpegInputFormat(format) {
81
+ switch (format) {
82
+ case "pcm":
83
+ return { f: "s16le", ar: "16000", ac: "1" };
84
+ default:
85
+ return {};
86
+ }
87
+ }
88
+ async function convertToFile(source, options) {
89
+ const tempPath = (0, import_node_path.join)(
90
+ (0, import_node_os.tmpdir)(),
91
+ `audio-convert-${Date.now()}${(0, import_AudioFormat.formatToExtension)(options.targetFormat)}`
92
+ );
93
+ const converter = new import_ffmpeg_stream.Converter();
94
+ const inputPath = (0, import_AudioSource.toFilePath)(source);
95
+ if (inputPath) {
96
+ converter.createInputFromFile(inputPath);
97
+ } else {
98
+ const inputOpts = getFFmpegInputFormat(source.format);
99
+ const inputStream = converter.createInputStream(inputOpts);
100
+ const readable = (0, import_AudioSource.toReadStream)(source);
101
+ readable.pipe(inputStream);
102
+ }
103
+ const outputOpts = getFFmpegFormatOptions(
104
+ options.targetFormat,
105
+ options.sampleRate,
106
+ options.channels
107
+ );
108
+ converter.createOutputToFile(tempPath, outputOpts);
109
+ await converter.run();
110
+ return {
111
+ source: (0, import_AudioSource.audioSourceFromFile)(tempPath, options.targetFormat),
112
+ cleanup: async () => {
113
+ await (0, import_promises.rm)(tempPath, { force: true }).catch(() => {
114
+ });
115
+ }
116
+ };
117
+ }
118
+ async function convertToBuffer(source, options) {
119
+ const converter = new import_ffmpeg_stream.Converter();
120
+ const inputPath = (0, import_AudioSource.toFilePath)(source);
121
+ if (inputPath) {
122
+ converter.createInputFromFile(inputPath);
123
+ } else {
124
+ const inputOpts = getFFmpegInputFormat(source.format);
125
+ const inputStream = converter.createInputStream(inputOpts);
126
+ const readable = (0, import_AudioSource.toReadStream)(source);
127
+ readable.pipe(inputStream);
128
+ }
129
+ const outputOpts = getFFmpegFormatOptions(
130
+ options.targetFormat,
131
+ options.sampleRate,
132
+ options.channels
133
+ );
134
+ const outputStream = converter.createOutputStream(outputOpts);
135
+ const chunks = [];
136
+ outputStream.on("data", (chunk) => chunks.push(chunk));
137
+ const bufferPromise = new Promise((resolve, reject) => {
138
+ outputStream.on("end", () => {
139
+ resolve(Buffer.concat(chunks));
140
+ });
141
+ outputStream.on("error", reject);
142
+ });
143
+ await converter.run();
144
+ const buffer = await bufferPromise;
145
+ return {
146
+ source: (0, import_AudioSource.audioSourceFromBuffer)(buffer, options.targetFormat),
147
+ cleanup: async () => {
148
+ }
149
+ };
150
+ }
151
+ function convertToStream(source, options) {
152
+ const converter = new import_ffmpeg_stream.Converter();
153
+ const inputPath = (0, import_AudioSource.toFilePath)(source);
154
+ if (inputPath) {
155
+ converter.createInputFromFile(inputPath);
156
+ } else {
157
+ const inputOpts = getFFmpegInputFormat(source.format);
158
+ const inputStream = converter.createInputStream(inputOpts);
159
+ const readable = (0, import_AudioSource.toReadStream)(source);
160
+ readable.pipe(inputStream);
161
+ }
162
+ const outputOpts = getFFmpegFormatOptions(
163
+ options.targetFormat,
164
+ options.sampleRate,
165
+ options.channels
166
+ );
167
+ const outputStream = converter.createOutputStream(outputOpts);
168
+ return {
169
+ stream: outputStream,
170
+ runConversion: () => converter.run()
171
+ };
172
+ }
173
+ async function prepareForService(source, options) {
174
+ const caps = import_AudioFormat.serviceCapabilities[options.service];
175
+ if (!caps) {
176
+ throw new Error(`Unknown service: ${options.service}`);
177
+ }
178
+ const inputFormat = source.format;
179
+ const requiresConversion = (0, import_AudioFormat.needsConversion)(inputFormat, options.service);
180
+ const targetFormat = (0, import_AudioFormat.getTargetFormat)(inputFormat, options.service);
181
+ if (!requiresConversion) {
182
+ if (caps.requiresFile && source.type !== "file") {
183
+ return writeToTempFile(source);
184
+ }
185
+ return { source, cleanup: async () => {
186
+ } };
187
+ }
188
+ const conversionOptions = {
189
+ targetFormat,
190
+ sampleRate: caps.preferredSampleRate,
191
+ channels: caps.preferredChannels
192
+ };
193
+ if (caps.requiresFile || options.preferFile) {
194
+ return convertToFile(source, conversionOptions);
195
+ }
196
+ if (caps.requiresBase64) {
197
+ return convertToBuffer(source, conversionOptions);
198
+ }
199
+ return convertToFile(source, conversionOptions);
200
+ }
201
+ async function writeToTempFile(source) {
202
+ const tempPath = (0, import_node_path.join)(
203
+ (0, import_node_os.tmpdir)(),
204
+ `audio-temp-${Date.now()}${(0, import_AudioFormat.formatToExtension)(source.format)}`
205
+ );
206
+ const readable = (0, import_AudioSource.toReadStream)(source);
207
+ const writable = (0, import_node_fs.createWriteStream)(tempPath);
208
+ await (0, import_promises2.pipeline)(readable, writable);
209
+ return {
210
+ source: (0, import_AudioSource.audioSourceFromFile)(tempPath, source.format),
211
+ cleanup: async () => {
212
+ await (0, import_promises.rm)(tempPath, { force: true }).catch(() => {
213
+ });
214
+ }
215
+ };
216
+ }
217
+ async function prepareWavForService(source, options = {}) {
218
+ if (source.format === "wav" && source.type === "file") {
219
+ return { source, cleanup: async () => {
220
+ } };
221
+ }
222
+ return convertToFile(source, {
223
+ targetFormat: "wav",
224
+ sampleRate: options.sampleRate ?? 16e3,
225
+ channels: options.channels ?? 1
226
+ });
227
+ }
228
+ function createStreamingConversion(source, options) {
229
+ const { stream, runConversion } = convertToStream(source, options);
230
+ return { stream, start: runConversion };
231
+ }
232
+ async function createStreamForUpload(options) {
233
+ const mode = options.mode ?? (0, import_config.getConversionMode)();
234
+ const needsConvert = options.source.format !== options.targetFormat;
235
+ if (!needsConvert) {
236
+ const stream = (0, import_AudioSource.toReadStream)(options.source);
237
+ return {
238
+ stream,
239
+ format: options.source.format,
240
+ cleanup: async () => {
241
+ },
242
+ mode
243
+ };
244
+ }
245
+ if (mode === "file-first") {
246
+ const tempPath = (0, import_node_path.join)(
247
+ (0, import_node_os.tmpdir)(),
248
+ `upload-${Date.now()}${(0, import_AudioFormat.formatToExtension)(options.targetFormat)}`
249
+ );
250
+ const converter2 = new import_ffmpeg_stream.Converter();
251
+ const inputPath2 = (0, import_AudioSource.toFilePath)(options.source);
252
+ if (inputPath2) {
253
+ converter2.createInputFromFile(inputPath2);
254
+ } else {
255
+ const inputOpts = getFFmpegInputFormat(options.source.format);
256
+ const inputStream = converter2.createInputStream(inputOpts);
257
+ const readable = (0, import_AudioSource.toReadStream)(options.source);
258
+ readable.pipe(inputStream);
259
+ }
260
+ const outputOpts2 = getFFmpegFormatOptions(
261
+ options.targetFormat,
262
+ options.sampleRate,
263
+ options.channels
264
+ );
265
+ converter2.createOutputToFile(tempPath, outputOpts2);
266
+ await converter2.run();
267
+ const stream = (0, import_node_fs.createReadStream)(tempPath);
268
+ return {
269
+ stream,
270
+ format: options.targetFormat,
271
+ cleanup: async () => {
272
+ await (0, import_promises.rm)(tempPath, { force: true }).catch(() => {
273
+ });
274
+ },
275
+ mode
276
+ };
277
+ }
278
+ const converter = new import_ffmpeg_stream.Converter();
279
+ const inputPath = (0, import_AudioSource.toFilePath)(options.source);
280
+ if (inputPath) {
281
+ converter.createInputFromFile(inputPath);
282
+ } else {
283
+ const inputOpts = getFFmpegInputFormat(options.source.format);
284
+ const inputStream = converter.createInputStream(inputOpts);
285
+ const readable = (0, import_AudioSource.toReadStream)(options.source);
286
+ readable.pipe(inputStream);
287
+ }
288
+ const outputOpts = getFFmpegFormatOptions(
289
+ options.targetFormat,
290
+ options.sampleRate,
291
+ options.channels
292
+ );
293
+ const outputStream = converter.createOutputStream(outputOpts);
294
+ return {
295
+ stream: outputStream,
296
+ format: options.targetFormat,
297
+ cleanup: async () => {
298
+ },
299
+ start: () => converter.run(),
300
+ mode
301
+ };
302
+ }
303
+ async function getAudioDuration(filePath) {
304
+ const { stdout } = await execFileAsync("ffprobe", [
305
+ "-v",
306
+ "quiet",
307
+ "-show_entries",
308
+ "format=duration",
309
+ "-of",
310
+ "default=noprint_wrappers=1:nokey=1",
311
+ filePath
312
+ ]);
313
+ const duration = parseFloat(stdout.trim());
314
+ if (Number.isNaN(duration)) {
315
+ throw new Error(
316
+ `Failed to parse audio duration from ffprobe output: ${stdout}`
317
+ );
318
+ }
319
+ return duration;
320
+ }
321
+ // Annotate the CommonJS export names for ESM import in node:
322
+ 0 && (module.exports = {
323
+ convertToBuffer,
324
+ convertToFile,
325
+ convertToStream,
326
+ createStreamForUpload,
327
+ createStreamingConversion,
328
+ getAudioDuration,
329
+ prepareForService,
330
+ prepareWavForService
331
+ });
@@ -0,0 +1,53 @@
1
+ import { AudioFormat } from './AudioFormat.cjs';
2
+ import { AudioSource } from './AudioSource.cjs';
3
+ import { Readable } from 'node:stream';
4
+ import { ConversionMode } from '../config.cjs';
5
+ import 'node:fs';
6
+
7
+ interface ConversionOptions {
8
+ targetFormat: AudioFormat;
9
+ sampleRate?: number | undefined;
10
+ channels?: number | undefined;
11
+ }
12
+ interface PreparedAudio {
13
+ source: AudioSource;
14
+ cleanup: () => Promise<void>;
15
+ }
16
+ declare function convertToFile(source: AudioSource, options: ConversionOptions): Promise<PreparedAudio>;
17
+ declare function convertToBuffer(source: AudioSource, options: ConversionOptions): Promise<PreparedAudio>;
18
+ declare function convertToStream(source: AudioSource, options: ConversionOptions): {
19
+ stream: Readable;
20
+ runConversion: () => Promise<void>;
21
+ };
22
+ interface PrepareForServiceOptions {
23
+ service: string;
24
+ preferFile?: boolean;
25
+ preferStream?: boolean;
26
+ }
27
+ declare function prepareForService(source: AudioSource, options: PrepareForServiceOptions): Promise<PreparedAudio>;
28
+ declare function prepareWavForService(source: AudioSource, options?: {
29
+ sampleRate?: number | undefined;
30
+ channels?: number | undefined;
31
+ }): Promise<PreparedAudio>;
32
+ declare function createStreamingConversion(source: AudioSource, options: ConversionOptions): {
33
+ stream: Readable;
34
+ start: () => Promise<void>;
35
+ };
36
+ interface StreamForUploadOptions {
37
+ source: AudioSource;
38
+ targetFormat: AudioFormat;
39
+ sampleRate?: number | undefined;
40
+ channels?: number | undefined;
41
+ mode?: ConversionMode | undefined;
42
+ }
43
+ interface StreamForUploadResult {
44
+ stream: Readable;
45
+ format: AudioFormat;
46
+ cleanup: () => Promise<void>;
47
+ start?: () => Promise<void>;
48
+ mode: ConversionMode;
49
+ }
50
+ declare function createStreamForUpload(options: StreamForUploadOptions): Promise<StreamForUploadResult>;
51
+ declare function getAudioDuration(filePath: string): Promise<number>;
52
+
53
+ export { type ConversionOptions, type PrepareForServiceOptions, type PreparedAudio, type StreamForUploadOptions, type StreamForUploadResult, convertToBuffer, convertToFile, convertToStream, createStreamForUpload, createStreamingConversion, getAudioDuration, prepareForService, prepareWavForService };
@@ -0,0 +1,53 @@
1
+ import { AudioFormat } from './AudioFormat.js';
2
+ import { AudioSource } from './AudioSource.js';
3
+ import { Readable } from 'node:stream';
4
+ import { ConversionMode } from '../config.js';
5
+ import 'node:fs';
6
+
7
+ interface ConversionOptions {
8
+ targetFormat: AudioFormat;
9
+ sampleRate?: number | undefined;
10
+ channels?: number | undefined;
11
+ }
12
+ interface PreparedAudio {
13
+ source: AudioSource;
14
+ cleanup: () => Promise<void>;
15
+ }
16
+ declare function convertToFile(source: AudioSource, options: ConversionOptions): Promise<PreparedAudio>;
17
+ declare function convertToBuffer(source: AudioSource, options: ConversionOptions): Promise<PreparedAudio>;
18
+ declare function convertToStream(source: AudioSource, options: ConversionOptions): {
19
+ stream: Readable;
20
+ runConversion: () => Promise<void>;
21
+ };
22
+ interface PrepareForServiceOptions {
23
+ service: string;
24
+ preferFile?: boolean;
25
+ preferStream?: boolean;
26
+ }
27
+ declare function prepareForService(source: AudioSource, options: PrepareForServiceOptions): Promise<PreparedAudio>;
28
+ declare function prepareWavForService(source: AudioSource, options?: {
29
+ sampleRate?: number | undefined;
30
+ channels?: number | undefined;
31
+ }): Promise<PreparedAudio>;
32
+ declare function createStreamingConversion(source: AudioSource, options: ConversionOptions): {
33
+ stream: Readable;
34
+ start: () => Promise<void>;
35
+ };
36
+ interface StreamForUploadOptions {
37
+ source: AudioSource;
38
+ targetFormat: AudioFormat;
39
+ sampleRate?: number | undefined;
40
+ channels?: number | undefined;
41
+ mode?: ConversionMode | undefined;
42
+ }
43
+ interface StreamForUploadResult {
44
+ stream: Readable;
45
+ format: AudioFormat;
46
+ cleanup: () => Promise<void>;
47
+ start?: () => Promise<void>;
48
+ mode: ConversionMode;
49
+ }
50
+ declare function createStreamForUpload(options: StreamForUploadOptions): Promise<StreamForUploadResult>;
51
+ declare function getAudioDuration(filePath: string): Promise<number>;
52
+
53
+ export { type ConversionOptions, type PrepareForServiceOptions, type PreparedAudio, type StreamForUploadOptions, type StreamForUploadResult, convertToBuffer, convertToFile, convertToStream, createStreamForUpload, createStreamingConversion, getAudioDuration, prepareForService, prepareWavForService };