@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,62 @@
|
|
|
1
|
+
import { BuildVariant, WhisperModel } from './config.js';
|
|
2
|
+
|
|
3
|
+
interface DownloadOptions {
|
|
4
|
+
url: string;
|
|
5
|
+
destPath: string;
|
|
6
|
+
expectedSize?: number;
|
|
7
|
+
printOutput?: boolean;
|
|
8
|
+
onProgress?: ((downloaded: number, total: number) => void) | undefined;
|
|
9
|
+
signal?: AbortSignal | null | undefined;
|
|
10
|
+
}
|
|
11
|
+
declare function downloadFile(options: DownloadOptions): Promise<void>;
|
|
12
|
+
declare class PlatformMismatchError extends Error {
|
|
13
|
+
readonly variant: BuildVariant;
|
|
14
|
+
readonly compatibleVariants: BuildVariant[];
|
|
15
|
+
constructor(variant: BuildVariant, compatibleVariants: BuildVariant[]);
|
|
16
|
+
}
|
|
17
|
+
interface InstallBinaryOptions {
|
|
18
|
+
variant?: BuildVariant | undefined;
|
|
19
|
+
printOutput?: boolean | undefined;
|
|
20
|
+
force?: boolean | undefined;
|
|
21
|
+
signal?: AbortSignal | null | undefined;
|
|
22
|
+
}
|
|
23
|
+
declare function installBinary(options?: InstallBinaryOptions): Promise<string>;
|
|
24
|
+
interface InstallModelOptions {
|
|
25
|
+
model: WhisperModel;
|
|
26
|
+
modelDir?: string | undefined;
|
|
27
|
+
printOutput?: boolean;
|
|
28
|
+
force?: boolean;
|
|
29
|
+
onProgress?: ((downloaded: number, total: number) => void) | undefined;
|
|
30
|
+
signal?: AbortSignal | null | undefined;
|
|
31
|
+
}
|
|
32
|
+
declare function installModel(options: InstallModelOptions): Promise<string>;
|
|
33
|
+
interface InstallCoremlModelOptions {
|
|
34
|
+
model: WhisperModel;
|
|
35
|
+
modelDir?: string;
|
|
36
|
+
printOutput?: boolean;
|
|
37
|
+
force?: boolean;
|
|
38
|
+
signal?: AbortSignal | null | undefined;
|
|
39
|
+
}
|
|
40
|
+
declare function installCoremlModel(options: InstallCoremlModelOptions): Promise<string>;
|
|
41
|
+
interface InstallVadModelOptions {
|
|
42
|
+
modelDir?: string;
|
|
43
|
+
printOutput?: boolean;
|
|
44
|
+
force?: boolean;
|
|
45
|
+
onProgress?: (downloaded: number, total: number) => void;
|
|
46
|
+
signal?: AbortSignal | null | undefined;
|
|
47
|
+
}
|
|
48
|
+
declare function installVadModel(options?: InstallVadModelOptions): Promise<string>;
|
|
49
|
+
interface EnsureInstalledOptions {
|
|
50
|
+
model?: WhisperModel | undefined;
|
|
51
|
+
variant?: BuildVariant | undefined;
|
|
52
|
+
modelDir?: string | undefined;
|
|
53
|
+
printOutput?: boolean | undefined;
|
|
54
|
+
force?: boolean | undefined;
|
|
55
|
+
signal?: AbortSignal | null | undefined;
|
|
56
|
+
}
|
|
57
|
+
declare function ensureWhisperInstalled(options?: EnsureInstalledOptions): Promise<{
|
|
58
|
+
installDir: string;
|
|
59
|
+
modelPath: string | null;
|
|
60
|
+
}>;
|
|
61
|
+
|
|
62
|
+
export { type DownloadOptions, type EnsureInstalledOptions, type InstallBinaryOptions, type InstallCoremlModelOptions, type InstallModelOptions, type InstallVadModelOptions, PlatformMismatchError, downloadFile, ensureWhisperInstalled, installBinary, installCoremlModel, installModel, installVadModel };
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createReadStream,
|
|
3
|
+
createWriteStream,
|
|
4
|
+
existsSync,
|
|
5
|
+
statSync
|
|
6
|
+
} from "node:fs";
|
|
7
|
+
import { mkdir, rm } from "node:fs/promises";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { pipeline } from "node:stream/promises";
|
|
11
|
+
import { createGunzip } from "node:zlib";
|
|
12
|
+
import { extract } from "tar";
|
|
13
|
+
import {
|
|
14
|
+
MODEL_SIZES,
|
|
15
|
+
detectPlatform,
|
|
16
|
+
getBinaryDownloadUrl,
|
|
17
|
+
getCompatibleVariants,
|
|
18
|
+
getCoremlModelDownloadUrl,
|
|
19
|
+
getCoremlModelPath,
|
|
20
|
+
getInstallDir,
|
|
21
|
+
getInstalledVariant,
|
|
22
|
+
getModelDir,
|
|
23
|
+
getModelDownloadUrl,
|
|
24
|
+
getModelPath,
|
|
25
|
+
getVadModelDownloadUrl,
|
|
26
|
+
getVadModelPath,
|
|
27
|
+
getWhisperExecutablePath,
|
|
28
|
+
isVariantCompatibleWithCurrentPlatform,
|
|
29
|
+
needsCoremlModel
|
|
30
|
+
} from "./config.js";
|
|
31
|
+
async function downloadFile(options) {
|
|
32
|
+
const {
|
|
33
|
+
url,
|
|
34
|
+
destPath,
|
|
35
|
+
expectedSize,
|
|
36
|
+
printOutput = true,
|
|
37
|
+
onProgress,
|
|
38
|
+
signal
|
|
39
|
+
} = options;
|
|
40
|
+
console.log(`Downloading file from ${url} to ${destPath}`);
|
|
41
|
+
const response = await fetch(url, { signal: signal ?? null });
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Failed to download: ${response.status} ${response.statusText}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const contentLength = response.headers.get("content-length");
|
|
48
|
+
const totalSize = contentLength ? parseInt(contentLength, 10) : expectedSize ?? 0;
|
|
49
|
+
if (!response.body) {
|
|
50
|
+
throw new Error("Response body is null");
|
|
51
|
+
}
|
|
52
|
+
await mkdir(path.dirname(destPath), { recursive: true });
|
|
53
|
+
const fileStream = createWriteStream(destPath);
|
|
54
|
+
const reader = response.body.getReader();
|
|
55
|
+
let downloaded = 0;
|
|
56
|
+
let lastPrinted = 0;
|
|
57
|
+
try {
|
|
58
|
+
while (true) {
|
|
59
|
+
const { done, value } = await reader.read();
|
|
60
|
+
if (done) {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
downloaded += value.length;
|
|
64
|
+
fileStream.write(value);
|
|
65
|
+
onProgress == null ? void 0 : onProgress(downloaded, totalSize);
|
|
66
|
+
if (printOutput && totalSize > 0) {
|
|
67
|
+
const shouldPrint = downloaded - lastPrinted > 10 * 1024 * 1024 || downloaded === totalSize;
|
|
68
|
+
if (shouldPrint) {
|
|
69
|
+
const percent = (downloaded / totalSize * 100).toFixed(1);
|
|
70
|
+
console.log(
|
|
71
|
+
` ${(downloaded / 1024 / 1024).toFixed(1)} MB / ${(totalSize / 1024 / 1024).toFixed(1)} MB (${percent}%)`
|
|
72
|
+
);
|
|
73
|
+
lastPrinted = downloaded;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} finally {
|
|
78
|
+
fileStream.end();
|
|
79
|
+
}
|
|
80
|
+
await new Promise((resolve, reject) => {
|
|
81
|
+
fileStream.on("finish", resolve);
|
|
82
|
+
fileStream.on("error", reject);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
class PlatformMismatchError extends Error {
|
|
86
|
+
constructor(variant, compatibleVariants) {
|
|
87
|
+
const compatible = compatibleVariants.join(", ");
|
|
88
|
+
super(
|
|
89
|
+
`Variant "${variant}" is not compatible with the current platform. Compatible variants: ${compatible}. Use --force to override.`
|
|
90
|
+
);
|
|
91
|
+
this.variant = variant;
|
|
92
|
+
this.compatibleVariants = compatibleVariants;
|
|
93
|
+
this.name = "PlatformMismatchError";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function installBinary(options = {}) {
|
|
97
|
+
const {
|
|
98
|
+
variant = getInstalledVariant() ?? detectPlatform(),
|
|
99
|
+
printOutput = true,
|
|
100
|
+
force = false,
|
|
101
|
+
signal
|
|
102
|
+
} = options;
|
|
103
|
+
if (!force && !isVariantCompatibleWithCurrentPlatform(variant)) {
|
|
104
|
+
throw new PlatformMismatchError(variant, getCompatibleVariants());
|
|
105
|
+
}
|
|
106
|
+
const installDir = getInstallDir(variant);
|
|
107
|
+
const executablePath = getWhisperExecutablePath(installDir);
|
|
108
|
+
if (!force && existsSync(executablePath)) {
|
|
109
|
+
if (printOutput) {
|
|
110
|
+
console.log(`whisper.cpp (${variant}) already installed at ${installDir}`);
|
|
111
|
+
}
|
|
112
|
+
return installDir;
|
|
113
|
+
}
|
|
114
|
+
if (force && existsSync(installDir)) {
|
|
115
|
+
if (printOutput) {
|
|
116
|
+
console.log(`Removing existing installation at ${installDir}`);
|
|
117
|
+
}
|
|
118
|
+
await rm(installDir, { recursive: true });
|
|
119
|
+
}
|
|
120
|
+
const url = getBinaryDownloadUrl(variant);
|
|
121
|
+
const tmpDir = path.join(os.tmpdir(), "ghost-story-whisper-install");
|
|
122
|
+
const tarballPath = path.join(tmpDir, `whisper-cpp-${variant}.tar.gz`);
|
|
123
|
+
if (printOutput) {
|
|
124
|
+
console.log(`Downloading whisper.cpp (${variant}) from ${url}`);
|
|
125
|
+
}
|
|
126
|
+
await downloadFile({
|
|
127
|
+
url,
|
|
128
|
+
destPath: tarballPath,
|
|
129
|
+
printOutput,
|
|
130
|
+
signal
|
|
131
|
+
});
|
|
132
|
+
if (printOutput) {
|
|
133
|
+
console.log(`Extracting to ${installDir}`);
|
|
134
|
+
}
|
|
135
|
+
await mkdir(installDir, { recursive: true });
|
|
136
|
+
await pipeline(
|
|
137
|
+
createReadStream(tarballPath),
|
|
138
|
+
createGunzip(),
|
|
139
|
+
extract({ cwd: installDir, strip: 1 })
|
|
140
|
+
);
|
|
141
|
+
await rm(tmpDir, { recursive: true }).catch(() => {
|
|
142
|
+
});
|
|
143
|
+
if (printOutput) {
|
|
144
|
+
console.log(`whisper.cpp (${variant}) installed successfully`);
|
|
145
|
+
}
|
|
146
|
+
return installDir;
|
|
147
|
+
}
|
|
148
|
+
async function installModel(options) {
|
|
149
|
+
const {
|
|
150
|
+
model,
|
|
151
|
+
modelDir = getModelDir(),
|
|
152
|
+
printOutput = true,
|
|
153
|
+
force = false,
|
|
154
|
+
onProgress,
|
|
155
|
+
signal
|
|
156
|
+
} = options;
|
|
157
|
+
const modelPath = getModelPath(model, modelDir);
|
|
158
|
+
const expectedSize = MODEL_SIZES[model];
|
|
159
|
+
if (!force && existsSync(modelPath)) {
|
|
160
|
+
const stats = statSync(modelPath);
|
|
161
|
+
if (stats.size === expectedSize) {
|
|
162
|
+
if (printOutput) {
|
|
163
|
+
console.log(`Model ${model} already exists at ${modelPath}`);
|
|
164
|
+
}
|
|
165
|
+
const installedVariant2 = getInstalledVariant();
|
|
166
|
+
if (needsCoremlModel(installedVariant2 ?? void 0)) {
|
|
167
|
+
await installCoremlModel({
|
|
168
|
+
model,
|
|
169
|
+
modelDir,
|
|
170
|
+
printOutput,
|
|
171
|
+
force,
|
|
172
|
+
signal
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return modelPath;
|
|
176
|
+
}
|
|
177
|
+
if (printOutput) {
|
|
178
|
+
console.log(
|
|
179
|
+
`Model ${model} exists but has wrong size (${stats.size} vs ${expectedSize}), re-downloading`
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const url = getModelDownloadUrl(model);
|
|
184
|
+
if (printOutput) {
|
|
185
|
+
console.log(`Downloading model ${model}`);
|
|
186
|
+
}
|
|
187
|
+
await downloadFile({
|
|
188
|
+
url,
|
|
189
|
+
destPath: modelPath,
|
|
190
|
+
expectedSize,
|
|
191
|
+
printOutput,
|
|
192
|
+
onProgress,
|
|
193
|
+
signal
|
|
194
|
+
});
|
|
195
|
+
const installedVariant = getInstalledVariant();
|
|
196
|
+
if (needsCoremlModel(installedVariant ?? void 0)) {
|
|
197
|
+
await installCoremlModel({ model, modelDir, printOutput, force, signal });
|
|
198
|
+
}
|
|
199
|
+
if (printOutput) {
|
|
200
|
+
console.log(`Model ${model} installed successfully`);
|
|
201
|
+
}
|
|
202
|
+
return modelPath;
|
|
203
|
+
}
|
|
204
|
+
async function installCoremlModel(options) {
|
|
205
|
+
const {
|
|
206
|
+
model,
|
|
207
|
+
modelDir = getModelDir(),
|
|
208
|
+
printOutput = true,
|
|
209
|
+
force = false,
|
|
210
|
+
signal
|
|
211
|
+
} = options;
|
|
212
|
+
const coremlPath = getCoremlModelPath(model, modelDir);
|
|
213
|
+
if (!force && existsSync(coremlPath)) {
|
|
214
|
+
if (printOutput) {
|
|
215
|
+
console.log(`CoreML model ${model} already exists at ${coremlPath}`);
|
|
216
|
+
}
|
|
217
|
+
return coremlPath;
|
|
218
|
+
}
|
|
219
|
+
const url = getCoremlModelDownloadUrl(model);
|
|
220
|
+
const tmpDir = path.join(os.tmpdir(), "ghost-story-coreml-install");
|
|
221
|
+
const tarballPath = path.join(tmpDir, `ggml-${model}-encoder.mlmodelc.tar.gz`);
|
|
222
|
+
if (printOutput) {
|
|
223
|
+
console.log(`Downloading CoreML model ${model}`);
|
|
224
|
+
}
|
|
225
|
+
await downloadFile({
|
|
226
|
+
url,
|
|
227
|
+
destPath: tarballPath,
|
|
228
|
+
printOutput,
|
|
229
|
+
signal
|
|
230
|
+
});
|
|
231
|
+
if (printOutput) {
|
|
232
|
+
console.log(`Extracting CoreML model to ${modelDir}`);
|
|
233
|
+
}
|
|
234
|
+
await mkdir(modelDir, { recursive: true });
|
|
235
|
+
await pipeline(
|
|
236
|
+
createReadStream(tarballPath),
|
|
237
|
+
createGunzip(),
|
|
238
|
+
extract({ cwd: modelDir })
|
|
239
|
+
);
|
|
240
|
+
await rm(tmpDir, { recursive: true }).catch(() => {
|
|
241
|
+
});
|
|
242
|
+
if (printOutput) {
|
|
243
|
+
console.log(`CoreML model ${model} installed successfully`);
|
|
244
|
+
}
|
|
245
|
+
return coremlPath;
|
|
246
|
+
}
|
|
247
|
+
async function installVadModel(options = {}) {
|
|
248
|
+
const {
|
|
249
|
+
modelDir = getModelDir(),
|
|
250
|
+
printOutput = true,
|
|
251
|
+
force = false,
|
|
252
|
+
onProgress,
|
|
253
|
+
signal
|
|
254
|
+
} = options;
|
|
255
|
+
const modelPath = getVadModelPath(modelDir);
|
|
256
|
+
const expectedSize = MODEL_SIZES["silero-vad"];
|
|
257
|
+
if (!force && existsSync(modelPath)) {
|
|
258
|
+
const stats = statSync(modelPath);
|
|
259
|
+
if (stats.size === expectedSize) {
|
|
260
|
+
if (printOutput) {
|
|
261
|
+
console.log(`VAD model already exists at ${modelPath}`);
|
|
262
|
+
}
|
|
263
|
+
return modelPath;
|
|
264
|
+
}
|
|
265
|
+
if (printOutput) {
|
|
266
|
+
console.log(
|
|
267
|
+
`VAD model exists but has wrong size (${stats.size} vs ${expectedSize}), re-downloading`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const url = getVadModelDownloadUrl();
|
|
272
|
+
if (printOutput) {
|
|
273
|
+
console.log(`Downloading Silero VAD model`);
|
|
274
|
+
}
|
|
275
|
+
await downloadFile({
|
|
276
|
+
url,
|
|
277
|
+
destPath: modelPath,
|
|
278
|
+
expectedSize,
|
|
279
|
+
printOutput,
|
|
280
|
+
onProgress,
|
|
281
|
+
signal
|
|
282
|
+
});
|
|
283
|
+
if (printOutput) {
|
|
284
|
+
console.log(`VAD model installed successfully`);
|
|
285
|
+
}
|
|
286
|
+
return modelPath;
|
|
287
|
+
}
|
|
288
|
+
async function ensureWhisperInstalled(options = {}) {
|
|
289
|
+
const { model, variant, printOutput = false, force = false, signal } = options;
|
|
290
|
+
const installDir = await installBinary({
|
|
291
|
+
variant,
|
|
292
|
+
printOutput,
|
|
293
|
+
force,
|
|
294
|
+
signal
|
|
295
|
+
});
|
|
296
|
+
let modelPath = null;
|
|
297
|
+
if (model) {
|
|
298
|
+
modelPath = await installModel({
|
|
299
|
+
model,
|
|
300
|
+
modelDir: options.modelDir,
|
|
301
|
+
printOutput,
|
|
302
|
+
force,
|
|
303
|
+
signal
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return { installDir, modelPath };
|
|
307
|
+
}
|
|
308
|
+
export {
|
|
309
|
+
PlatformMismatchError,
|
|
310
|
+
downloadFile,
|
|
311
|
+
ensureWhisperInstalled,
|
|
312
|
+
installBinary,
|
|
313
|
+
installCoremlModel,
|
|
314
|
+
installModel,
|
|
315
|
+
installVadModel
|
|
316
|
+
};
|
|
@@ -0,0 +1,172 @@
|
|
|
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 whisper_server_exports = {};
|
|
20
|
+
__export(whisper_server_exports, {
|
|
21
|
+
IncompatibleBinaryError: () => IncompatibleBinaryError,
|
|
22
|
+
defaultServerOptions: () => defaultServerOptions,
|
|
23
|
+
spawnWhisperServer: () => spawnWhisperServer
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(whisper_server_exports);
|
|
26
|
+
var import_node_child_process = require("node:child_process");
|
|
27
|
+
var import_node_fs = require("node:fs");
|
|
28
|
+
var import_config = require("./config.cjs");
|
|
29
|
+
var import_install = require("./install.cjs");
|
|
30
|
+
const defaultServerOptions = {
|
|
31
|
+
model: "tiny.en",
|
|
32
|
+
port: 8080,
|
|
33
|
+
host: "0.0.0.0",
|
|
34
|
+
threads: 4,
|
|
35
|
+
processors: 4,
|
|
36
|
+
convert: true,
|
|
37
|
+
autoInstall: true
|
|
38
|
+
};
|
|
39
|
+
class IncompatibleBinaryError extends Error {
|
|
40
|
+
constructor(installedVariant) {
|
|
41
|
+
super(
|
|
42
|
+
`Installed binary "${installedVariant}" is not compatible with the current platform. Reinstall with a compatible variant or use --force to attempt running anyway.`
|
|
43
|
+
);
|
|
44
|
+
this.installedVariant = installedVariant;
|
|
45
|
+
this.name = "IncompatibleBinaryError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function spawnWhisperServer(options) {
|
|
49
|
+
const installedVariant = (0, import_config.getInstalledVariant)();
|
|
50
|
+
if (installedVariant && !options.force) {
|
|
51
|
+
if (!(0, import_config.isVariantCompatibleWithCurrentPlatform)(installedVariant)) {
|
|
52
|
+
throw new IncompatibleBinaryError(installedVariant);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const installDir = options.variant ? (0, import_config.getInstallDir)(options.variant) : (0, import_config.getInstallDir)();
|
|
56
|
+
const modelPath = (0, import_config.getModelPath)(options.model);
|
|
57
|
+
console.log("Setting up whisper.cpp server...");
|
|
58
|
+
console.log(` Model: ${options.model}`);
|
|
59
|
+
console.log(` Port: ${options.port}`);
|
|
60
|
+
console.log(` Host: ${options.host}`);
|
|
61
|
+
console.log(` Threads: ${options.threads}`);
|
|
62
|
+
console.log(` Processors: ${options.processors}`);
|
|
63
|
+
if (installedVariant) {
|
|
64
|
+
console.log(` Variant: ${installedVariant}`);
|
|
65
|
+
}
|
|
66
|
+
console.log("");
|
|
67
|
+
const serverPath = (0, import_config.getWhisperServerExecutablePath)(installDir);
|
|
68
|
+
if (options.autoInstall) {
|
|
69
|
+
if (!(0, import_node_fs.existsSync)(serverPath)) {
|
|
70
|
+
console.log("Installing whisper.cpp binary...");
|
|
71
|
+
await (0, import_install.installBinary)({
|
|
72
|
+
variant: options.variant,
|
|
73
|
+
printOutput: true,
|
|
74
|
+
force: options.force
|
|
75
|
+
});
|
|
76
|
+
console.log("");
|
|
77
|
+
}
|
|
78
|
+
if ((0, import_node_fs.existsSync)(serverPath) && !((0, import_node_fs.statSync)(serverPath).mode & 73)) {
|
|
79
|
+
console.log("Making whisper.cpp binary executable...");
|
|
80
|
+
(0, import_node_fs.chmodSync)(serverPath, 493);
|
|
81
|
+
}
|
|
82
|
+
if (!(0, import_node_fs.existsSync)(modelPath)) {
|
|
83
|
+
console.log(`Installing model ${options.model}...`);
|
|
84
|
+
await (0, import_install.installModel)({ model: options.model, printOutput: true });
|
|
85
|
+
console.log("");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!(0, import_node_fs.existsSync)(serverPath)) {
|
|
89
|
+
console.error(`Server executable not found at ${serverPath}`);
|
|
90
|
+
console.error("Run 'storywhisper install binary' to install whisper.cpp");
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
if (!(0, import_node_fs.existsSync)(modelPath)) {
|
|
94
|
+
console.error(`Model not found at ${modelPath}`);
|
|
95
|
+
console.error(
|
|
96
|
+
`Run 'storywhisper install model ${options.model}' to install the model`
|
|
97
|
+
);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
console.log("Starting whisper server...");
|
|
101
|
+
console.log(` Executable: ${serverPath}`);
|
|
102
|
+
console.log(` Model: ${modelPath}`);
|
|
103
|
+
console.log("");
|
|
104
|
+
const serverArgs = [
|
|
105
|
+
"-m",
|
|
106
|
+
modelPath,
|
|
107
|
+
"--host",
|
|
108
|
+
options.host,
|
|
109
|
+
"--port",
|
|
110
|
+
String(options.port),
|
|
111
|
+
"-t",
|
|
112
|
+
String(options.threads),
|
|
113
|
+
"-p",
|
|
114
|
+
String(options.processors),
|
|
115
|
+
"--inference-path",
|
|
116
|
+
"/audio/transcriptions",
|
|
117
|
+
"--suppress-nst",
|
|
118
|
+
"--flash-attn"
|
|
119
|
+
];
|
|
120
|
+
if (options.convert) {
|
|
121
|
+
serverArgs.push("--convert");
|
|
122
|
+
}
|
|
123
|
+
if (options.vadModelPath) {
|
|
124
|
+
serverArgs.push("--vad", "--vad-model", options.vadModelPath);
|
|
125
|
+
if (options.vadThreshold !== void 0) {
|
|
126
|
+
serverArgs.push("--vad-threshold", String(options.vadThreshold));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const server = (0, import_node_child_process.spawn)(serverPath, serverArgs, {
|
|
131
|
+
stdio: "inherit",
|
|
132
|
+
cwd: installDir
|
|
133
|
+
});
|
|
134
|
+
server.on("error", (err) => {
|
|
135
|
+
console.error("Failed to start server:", err.message);
|
|
136
|
+
if (err.message.includes("ENOEXEC")) {
|
|
137
|
+
const variant = (0, import_config.getInstalledVariant)();
|
|
138
|
+
console.error(
|
|
139
|
+
`The installed binary${variant ? ` (${variant})` : ""} cannot be executed on this platform.`
|
|
140
|
+
);
|
|
141
|
+
console.error(
|
|
142
|
+
"Reinstall with a compatible variant: storywhisper install binary --force"
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
process.exit(1);
|
|
146
|
+
});
|
|
147
|
+
server.on("exit", (code, signal) => {
|
|
148
|
+
if (signal) {
|
|
149
|
+
console.log(`Server terminated by signal: ${signal}`);
|
|
150
|
+
} else {
|
|
151
|
+
console.log(`Server exited with code: ${code}`);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
process.on("SIGINT", () => {
|
|
155
|
+
console.log("\nShutting down server...");
|
|
156
|
+
server.kill("SIGTERM");
|
|
157
|
+
});
|
|
158
|
+
process.on("SIGTERM", () => {
|
|
159
|
+
server.kill("SIGTERM");
|
|
160
|
+
});
|
|
161
|
+
return server;
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error("Failed to start server:", error);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
168
|
+
0 && (module.exports = {
|
|
169
|
+
IncompatibleBinaryError,
|
|
170
|
+
defaultServerOptions,
|
|
171
|
+
spawnWhisperServer
|
|
172
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as child_process from 'child_process';
|
|
2
|
+
import { WhisperModel, BuildVariant } from './config.cjs';
|
|
3
|
+
|
|
4
|
+
interface ServerOptions {
|
|
5
|
+
model: WhisperModel;
|
|
6
|
+
port: number;
|
|
7
|
+
host: string;
|
|
8
|
+
threads: number;
|
|
9
|
+
processors: number;
|
|
10
|
+
convert: boolean;
|
|
11
|
+
autoInstall: boolean;
|
|
12
|
+
variant?: BuildVariant | undefined;
|
|
13
|
+
force?: boolean | undefined;
|
|
14
|
+
vadModelPath?: string | undefined;
|
|
15
|
+
vadThreshold?: number | undefined;
|
|
16
|
+
}
|
|
17
|
+
declare const defaultServerOptions: ServerOptions;
|
|
18
|
+
declare class IncompatibleBinaryError extends Error {
|
|
19
|
+
readonly installedVariant: BuildVariant;
|
|
20
|
+
constructor(installedVariant: BuildVariant);
|
|
21
|
+
}
|
|
22
|
+
declare function spawnWhisperServer(options: ServerOptions): Promise<child_process.ChildProcess>;
|
|
23
|
+
|
|
24
|
+
export { IncompatibleBinaryError, type ServerOptions, defaultServerOptions, spawnWhisperServer };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as child_process from 'child_process';
|
|
2
|
+
import { WhisperModel, BuildVariant } from './config.js';
|
|
3
|
+
|
|
4
|
+
interface ServerOptions {
|
|
5
|
+
model: WhisperModel;
|
|
6
|
+
port: number;
|
|
7
|
+
host: string;
|
|
8
|
+
threads: number;
|
|
9
|
+
processors: number;
|
|
10
|
+
convert: boolean;
|
|
11
|
+
autoInstall: boolean;
|
|
12
|
+
variant?: BuildVariant | undefined;
|
|
13
|
+
force?: boolean | undefined;
|
|
14
|
+
vadModelPath?: string | undefined;
|
|
15
|
+
vadThreshold?: number | undefined;
|
|
16
|
+
}
|
|
17
|
+
declare const defaultServerOptions: ServerOptions;
|
|
18
|
+
declare class IncompatibleBinaryError extends Error {
|
|
19
|
+
readonly installedVariant: BuildVariant;
|
|
20
|
+
constructor(installedVariant: BuildVariant);
|
|
21
|
+
}
|
|
22
|
+
declare function spawnWhisperServer(options: ServerOptions): Promise<child_process.ChildProcess>;
|
|
23
|
+
|
|
24
|
+
export { IncompatibleBinaryError, type ServerOptions, defaultServerOptions, spawnWhisperServer };
|