@drakulavich/parakeet-cli 0.6.0 → 0.7.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/README.md +23 -10
- package/package.json +3 -2
- package/src/models.ts +67 -14
package/README.md
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# 🦜 parakeet-cli
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@drakulavich/parakeet-cli)
|
|
4
3
|
[](https://github.com/drakulavich/parakeet-cli/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@drakulavich/parakeet-cli)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://bun.sh)
|
|
7
|
-
[](https://drakulavich.github.io/parakeet-cli/reports/allure)
|
|
8
7
|
|
|
9
8
|
Fast local speech-to-text. 25 languages. ~18x faster than Whisper on Apple Silicon.
|
|
10
9
|
|
|
@@ -39,21 +38,31 @@ Stdout: transcript. Stderr: errors. Pipe-friendly.
|
|
|
39
38
|
- [ffmpeg](https://ffmpeg.org) in PATH (ONNX backend only)
|
|
40
39
|
- ~3GB disk (ONNX models)
|
|
41
40
|
|
|
42
|
-
##
|
|
41
|
+
## Benchmark
|
|
43
42
|
|
|
44
|
-
|
|
43
|
+
> **~18x faster than Whisper** on Apple Silicon (CoreML)
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
<details>
|
|
46
|
+
<summary>MacBook Pro M3 Pro — 10 Russian voice messages</summary>
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
```
|
|
49
|
+
faster-whisper (CPU): 35.3s ██████████████████████████████████████
|
|
50
|
+
Parakeet (CoreML): 1.9s ██
|
|
51
|
+
```
|
|
49
52
|
|
|
50
|
-
| | faster-whisper
|
|
51
|
-
|
|
52
|
-
|
|
|
53
|
-
| **
|
|
53
|
+
| | faster-whisper | Parakeet | Speedup |
|
|
54
|
+
|---|---|---|---|
|
|
55
|
+
| Apple Silicon (CoreML) | 35.3s | **1.9s** | **~18x** |
|
|
56
|
+
| Linux CI (ONNX) | 79.2s | **45.4s** | **~1.7x** |
|
|
57
|
+
|
|
58
|
+
</details>
|
|
54
59
|
|
|
55
60
|
Full results with transcripts: [BENCHMARK.md](BENCHMARK.md)
|
|
56
61
|
|
|
62
|
+
## Supported Languages
|
|
63
|
+
|
|
64
|
+
:bulgaria: Bulgarian, :croatia: Croatian, :czech_republic: Czech, :denmark: Danish, :netherlands: Dutch, :gb: English, :estonia: Estonian, :finland: Finnish, :fr: French, :de: German, :greece: Greek, :hungary: Hungarian, :it: Italian, :latvia: Latvian, :lithuania: Lithuanian, :malta: Maltese, :poland: Polish, :portugal: Portuguese, :romania: Romanian, :ru: Russian, :slovakia: Slovak, :slovenia: Slovenian, :es: Spanish, :sweden: Swedish, :ukraine: Ukrainian
|
|
65
|
+
|
|
57
66
|
## How It Works
|
|
58
67
|
|
|
59
68
|
```
|
|
@@ -83,6 +92,10 @@ Drop-in replacement for OpenClaw voice processing — no API keys, runs locally.
|
|
|
83
92
|
}
|
|
84
93
|
```
|
|
85
94
|
|
|
95
|
+
## Contributing
|
|
96
|
+
|
|
97
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
98
|
+
|
|
86
99
|
## License
|
|
87
100
|
|
|
88
101
|
MIT
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drakulavich/parakeet-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Fast
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Fast local speech-to-text CLI. CoreML on Apple Silicon, ONNX on CPU. 25 languages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"parakeet": "bin/parakeet.js"
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/bun": "latest",
|
|
52
|
+
"fast-xml-parser": "^5.5.10",
|
|
52
53
|
"typescript": "^6.0.2"
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
package/src/models.ts
CHANGED
|
@@ -53,7 +53,7 @@ export async function downloadModel(noCache = false, modelDir?: string): Promise
|
|
|
53
53
|
const dir = modelDir ?? getModelDir();
|
|
54
54
|
|
|
55
55
|
if (!noCache && isModelCached(dir)) {
|
|
56
|
-
console.
|
|
56
|
+
console.log("Model already downloaded.");
|
|
57
57
|
return dir;
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -67,21 +67,50 @@ export async function downloadModel(noCache = false, modelDir?: string): Promise
|
|
|
67
67
|
|
|
68
68
|
console.error(`Downloading ${file}...`);
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
let res: Response;
|
|
71
|
+
try {
|
|
72
|
+
res = await fetch(url, { redirect: "follow" });
|
|
73
|
+
} catch (e) {
|
|
74
|
+
throw new Error(`failed to fetch ${file}: ${e instanceof Error ? e.message : e}`);
|
|
75
|
+
}
|
|
71
76
|
|
|
72
77
|
if (!res.ok) {
|
|
73
|
-
throw new Error(`failed to download
|
|
78
|
+
throw new Error(`failed to download ${file}: HTTP ${res.status}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!res.body) {
|
|
82
|
+
throw new Error(`empty response body for ${file}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const writer = Bun.file(dest).writer();
|
|
86
|
+
let bytes = 0;
|
|
87
|
+
try {
|
|
88
|
+
for await (const chunk of res.body) {
|
|
89
|
+
writer.write(chunk);
|
|
90
|
+
bytes += chunk.length;
|
|
91
|
+
}
|
|
92
|
+
} finally {
|
|
93
|
+
writer.end();
|
|
74
94
|
}
|
|
75
95
|
|
|
76
|
-
|
|
96
|
+
if (bytes === 0) {
|
|
97
|
+
throw new Error(`downloaded 0 bytes for ${file}`);
|
|
98
|
+
}
|
|
77
99
|
}
|
|
78
100
|
|
|
79
|
-
console.
|
|
101
|
+
console.log("Model downloaded successfully.");
|
|
80
102
|
return dir;
|
|
81
103
|
}
|
|
82
104
|
|
|
105
|
+
const COREML_BINARY_NAME = "parakeet-coreml-darwin-arm64";
|
|
106
|
+
const GITHUB_REPO = "drakulavich/parakeet-cli";
|
|
107
|
+
|
|
83
108
|
export function getCoreMLDownloadURL(version: string): string {
|
|
84
|
-
return `https://github.com/
|
|
109
|
+
return `https://github.com/${GITHUB_REPO}/releases/download/v${version}/${COREML_BINARY_NAME}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getCoreMLLatestDownloadURL(): string {
|
|
113
|
+
return `https://github.com/${GITHUB_REPO}/releases/latest/download/${COREML_BINARY_NAME}`;
|
|
85
114
|
}
|
|
86
115
|
|
|
87
116
|
export async function downloadCoreML(noCache = false): Promise<string> {
|
|
@@ -89,19 +118,32 @@ export async function downloadCoreML(noCache = false): Promise<string> {
|
|
|
89
118
|
const binPath = getCoreMLBinPath();
|
|
90
119
|
|
|
91
120
|
if (!noCache && existsSync(binPath)) {
|
|
92
|
-
|
|
93
|
-
|
|
121
|
+
// Binary exists — ensure models are also downloaded
|
|
122
|
+
const checkProc = Bun.spawnSync([binPath, "--download-only"], {
|
|
123
|
+
stdout: "pipe",
|
|
124
|
+
stderr: "pipe",
|
|
125
|
+
});
|
|
126
|
+
if (checkProc.exitCode === 0) {
|
|
127
|
+
console.log("CoreML backend already installed.");
|
|
128
|
+
return binPath;
|
|
129
|
+
}
|
|
130
|
+
// Models missing — continue to re-download
|
|
94
131
|
}
|
|
95
132
|
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
133
|
+
// Try latest release first, fall back to version-specific
|
|
134
|
+
const latestUrl = getCoreMLLatestDownloadURL();
|
|
99
135
|
console.error("Downloading parakeet-coreml binary...");
|
|
100
136
|
|
|
101
|
-
|
|
137
|
+
let res = await fetch(latestUrl, { redirect: "follow" });
|
|
138
|
+
|
|
139
|
+
if (!res.ok) {
|
|
140
|
+
const pkg = await Bun.file(new URL("../package.json", import.meta.url)).json();
|
|
141
|
+
const versionUrl = getCoreMLDownloadURL(pkg.version);
|
|
142
|
+
res = await fetch(versionUrl, { redirect: "follow" });
|
|
143
|
+
}
|
|
102
144
|
|
|
103
145
|
if (!res.ok) {
|
|
104
|
-
throw new Error(`Failed to download CoreML binary
|
|
146
|
+
throw new Error(`Failed to download CoreML binary (HTTP ${res.status}). No release found with ${COREML_BINARY_NAME}.`);
|
|
105
147
|
}
|
|
106
148
|
|
|
107
149
|
mkdirSync(dirname(binPath), { recursive: true });
|
|
@@ -110,6 +152,17 @@ export async function downloadCoreML(noCache = false): Promise<string> {
|
|
|
110
152
|
|
|
111
153
|
chmodSync(binPath, 0o755);
|
|
112
154
|
|
|
113
|
-
|
|
155
|
+
// Download CoreML model files (first transcription would be slow without this)
|
|
156
|
+
console.error("Downloading CoreML models...");
|
|
157
|
+
const downloadProc = Bun.spawnSync([binPath, "--download-only"], {
|
|
158
|
+
stdout: "inherit",
|
|
159
|
+
stderr: "inherit",
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (downloadProc.exitCode !== 0) {
|
|
163
|
+
throw new Error("Failed to download CoreML models");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
console.log("CoreML backend installed successfully.");
|
|
114
167
|
return binPath;
|
|
115
168
|
}
|