@drakulavich/parakeet-cli 0.3.0 → 0.4.0
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/package.json +1 -1
- package/src/cli.ts +20 -5
- package/src/lib.ts +5 -11
- package/src/models.ts +24 -2
- package/src/transcribe.ts +2 -4
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
import { transcribe } from "./lib";
|
|
4
|
+
import { downloadModel } from "./models";
|
|
4
5
|
|
|
5
6
|
async function main(): Promise<void> {
|
|
6
7
|
const args = process.argv.slice(2);
|
|
@@ -11,20 +12,34 @@ async function main(): Promise<void> {
|
|
|
11
12
|
process.exit(0);
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
|
|
15
|
+
const positional = args.filter((a) => !a.startsWith("--"));
|
|
16
|
+
|
|
17
|
+
if (positional[0] === "install") {
|
|
18
|
+
const noCache = args.includes("--no-cache");
|
|
19
|
+
try {
|
|
20
|
+
await downloadModel(noCache);
|
|
21
|
+
} catch (err: unknown) {
|
|
22
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23
|
+
console.error(`Error: ${message}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const file = positional[0];
|
|
16
30
|
|
|
17
31
|
if (!file) {
|
|
18
|
-
console.error("Usage: parakeet [--
|
|
32
|
+
console.error("Usage: parakeet [--version] <audio_file>");
|
|
33
|
+
console.error(" parakeet install [--no-cache]");
|
|
19
34
|
process.exit(1);
|
|
20
35
|
}
|
|
21
36
|
|
|
22
37
|
try {
|
|
23
|
-
const text = await transcribe(file
|
|
38
|
+
const text = await transcribe(file);
|
|
24
39
|
if (text) process.stdout.write(text + "\n");
|
|
25
40
|
} catch (err: unknown) {
|
|
26
41
|
const message = err instanceof Error ? err.message : String(err);
|
|
27
|
-
console.error(
|
|
42
|
+
console.error(message);
|
|
28
43
|
process.exit(1);
|
|
29
44
|
}
|
|
30
45
|
}
|
package/src/lib.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
|
-
import { transcribe as internalTranscribe } from "./transcribe";
|
|
2
|
+
import { transcribe as internalTranscribe, type TranscribeOptions } from "./transcribe";
|
|
3
|
+
import { downloadModel } from "./models";
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
noCache?: boolean;
|
|
7
|
-
modelDir?: string;
|
|
8
|
-
}
|
|
5
|
+
export type { TranscribeOptions };
|
|
6
|
+
export { downloadModel };
|
|
9
7
|
|
|
10
8
|
export async function transcribe(
|
|
11
9
|
audioPath: string,
|
|
@@ -15,9 +13,5 @@ export async function transcribe(
|
|
|
15
13
|
throw new Error(`File not found: ${audioPath}`);
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
return internalTranscribe(audioPath,
|
|
19
|
-
noCache: options.noCache ?? false,
|
|
20
|
-
beamWidth: options.beamWidth,
|
|
21
|
-
modelDir: options.modelDir,
|
|
22
|
-
});
|
|
16
|
+
return internalTranscribe(audioPath, options);
|
|
23
17
|
}
|
package/src/models.ts
CHANGED
|
@@ -21,10 +21,31 @@ export function isModelCached(dir?: string): boolean {
|
|
|
21
21
|
return MODEL_FILES.every((f) => existsSync(join(d, f)));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export
|
|
24
|
+
export function requireModel(modelDir?: string): string {
|
|
25
25
|
const dir = modelDir ?? getModelDir();
|
|
26
26
|
|
|
27
|
-
if (!
|
|
27
|
+
if (!isModelCached(dir)) {
|
|
28
|
+
const lines = [
|
|
29
|
+
`Error: Model not found at ${dir}`,
|
|
30
|
+
"",
|
|
31
|
+
"╔══════════════════════════════════════════════════════════╗",
|
|
32
|
+
"║ Looks like Parakeet model is not downloaded yet. ║",
|
|
33
|
+
"║ Please run the following command to download the model: ║",
|
|
34
|
+
"║ ║",
|
|
35
|
+
"║ npx @drakulavich/parakeet-cli install ║",
|
|
36
|
+
"╚══════════════════════════════════════════════════════════╝",
|
|
37
|
+
];
|
|
38
|
+
throw new Error(lines.join("\n"));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return dir;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function downloadModel(noCache = false, modelDir?: string): Promise<string> {
|
|
45
|
+
const dir = modelDir ?? getModelDir();
|
|
46
|
+
|
|
47
|
+
if (!noCache && isModelCached(dir)) {
|
|
48
|
+
console.error("Model already downloaded.");
|
|
28
49
|
return dir;
|
|
29
50
|
}
|
|
30
51
|
|
|
@@ -47,5 +68,6 @@ export async function ensureModel(noCache = false, modelDir?: string): Promise<s
|
|
|
47
68
|
await Bun.write(dest, res);
|
|
48
69
|
}
|
|
49
70
|
|
|
71
|
+
console.error("Model downloaded successfully.");
|
|
50
72
|
return dir;
|
|
51
73
|
}
|
package/src/transcribe.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireModel } from "./models";
|
|
2
2
|
import { convertToFloat32PCM } from "./audio";
|
|
3
3
|
import { initPreprocessor, preprocess } from "./preprocess";
|
|
4
4
|
import { initEncoder, encode } from "./encoder";
|
|
@@ -25,7 +25,6 @@ const DECODER_LAYERS = 2;
|
|
|
25
25
|
const DECODER_HIDDEN = 640;
|
|
26
26
|
|
|
27
27
|
export interface TranscribeOptions {
|
|
28
|
-
noCache?: boolean;
|
|
29
28
|
beamWidth?: number;
|
|
30
29
|
modelDir?: string;
|
|
31
30
|
}
|
|
@@ -40,9 +39,8 @@ export async function transcribe(audioPath: string, opts: TranscribeOptions = {}
|
|
|
40
39
|
return "";
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
const noCache = opts.noCache ?? false;
|
|
44
42
|
const beamWidth = opts.beamWidth ?? 4;
|
|
45
|
-
const modelDir =
|
|
43
|
+
const modelDir = requireModel(opts.modelDir);
|
|
46
44
|
const tokenizer = await Tokenizer.fromFile(join(modelDir, "vocab.txt"));
|
|
47
45
|
|
|
48
46
|
await initPreprocessor(modelDir);
|