claude-voice 1.3.6 → 1.3.7
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/scripts/postinstall.js +154 -16
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -23,6 +23,8 @@ const CONFIG_DIR = path.join(os.homedir(), '.claude-voice');
|
|
|
23
23
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
24
24
|
const DEFAULT_CONFIG = path.join(__dirname, '..', 'config', 'default.json');
|
|
25
25
|
const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
|
|
26
|
+
const MODELS_DIR = path.join(CONFIG_DIR, 'models');
|
|
27
|
+
const VOICES_DIR = path.join(CONFIG_DIR, 'voices');
|
|
26
28
|
|
|
27
29
|
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
|
28
30
|
console.log('║ Claude Voice Extension - Auto Setup ║');
|
|
@@ -89,16 +91,94 @@ try {
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
// 6. Install Piper TTS and download default voice
|
|
92
|
-
const binPath = path.join(__dirname, '..', 'bin', 'claude-voice');
|
|
93
94
|
console.log('\nStep 4/7: Installing Piper TTS engine...');
|
|
94
95
|
console.log(' (First-time install may take 1-2 minutes)\n');
|
|
95
96
|
try {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
});
|
|
97
|
+
// Direct download without going through CLI
|
|
98
|
+
const voiceId = 'en_US-joe-medium';
|
|
99
|
+
const onnxPath = path.join(VOICES_DIR, `${voiceId}.onnx`);
|
|
100
|
+
const jsonPath = path.join(VOICES_DIR, `${voiceId}.onnx.json`);
|
|
101
|
+
|
|
102
|
+
if (fs.existsSync(onnxPath) && fs.existsSync(jsonPath)) {
|
|
103
|
+
console.log(` [✓] Voice already installed: ${voiceId}`);
|
|
104
|
+
} else {
|
|
105
|
+
// Create voices directory
|
|
106
|
+
if (!fs.existsSync(VOICES_DIR)) {
|
|
107
|
+
fs.mkdirSync(VOICES_DIR, { recursive: true });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Get voice URLs from HuggingFace
|
|
111
|
+
const parts = voiceId.split('-');
|
|
112
|
+
const langCode = parts[0];
|
|
113
|
+
const lang = langCode.split('_')[0];
|
|
114
|
+
const voiceName = parts[1];
|
|
115
|
+
const quality = parts[2];
|
|
116
|
+
const baseUrl = 'https://huggingface.co/rhasspy/piper-voices/resolve/main';
|
|
117
|
+
const voicePath = `${lang}/${langCode}/${voiceName}/${quality}`;
|
|
118
|
+
const onnxUrl = `${baseUrl}/${voicePath}/${voiceId}.onnx`;
|
|
119
|
+
const jsonUrl = `${baseUrl}/${voicePath}/${voiceId}.onnx.json`;
|
|
120
|
+
|
|
121
|
+
console.log(` Voice: Joe (US English)`);
|
|
122
|
+
console.log(` [1/2] Downloading voice model (~50MB)...`);
|
|
123
|
+
execSync(`curl -L --progress-bar -o "${onnxPath}" "${onnxUrl}"`, { stdio: 'inherit' });
|
|
124
|
+
|
|
125
|
+
console.log(` [2/2] Downloading voice config...`);
|
|
126
|
+
execSync(`curl -sL -o "${jsonPath}" "${jsonUrl}"`, { stdio: 'inherit' });
|
|
127
|
+
|
|
128
|
+
console.log(` [✓] Voice installed: ${voiceId}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Install Piper TTS via pip if needed
|
|
132
|
+
const PIPER_DIR = path.join(CONFIG_DIR, 'piper');
|
|
133
|
+
const PIPER_VENV = path.join(PIPER_DIR, 'venv');
|
|
134
|
+
const PIPER_BIN = path.join(PIPER_VENV, 'bin', 'piper');
|
|
135
|
+
|
|
136
|
+
if (!fs.existsSync(PIPER_BIN)) {
|
|
137
|
+
// Find Python 3.9-3.13
|
|
138
|
+
const pythonCandidates = [
|
|
139
|
+
'/opt/homebrew/bin/python3.12', '/opt/homebrew/bin/python3.11', '/opt/homebrew/bin/python3',
|
|
140
|
+
'/usr/local/bin/python3.12', '/usr/local/bin/python3.11', '/usr/local/bin/python3',
|
|
141
|
+
'/usr/bin/python3.12', '/usr/bin/python3.11', '/usr/bin/python3.10', '/usr/bin/python3.9', '/usr/bin/python3',
|
|
142
|
+
'python3.12', 'python3.11', 'python3.10', 'python3'
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
let python = null;
|
|
146
|
+
for (const py of pythonCandidates) {
|
|
147
|
+
try {
|
|
148
|
+
const version = execSync(`${py} --version 2>&1`, { encoding: 'utf-8' });
|
|
149
|
+
const match = version.match(/Python 3\.(\d+)/);
|
|
150
|
+
if (match) {
|
|
151
|
+
const minor = parseInt(match[1], 10);
|
|
152
|
+
if (minor >= 9 && minor <= 13) {
|
|
153
|
+
python = py;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} catch {}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (python) {
|
|
161
|
+
console.log(` [1/3] Found Python: ${python}`);
|
|
162
|
+
if (!fs.existsSync(PIPER_DIR)) {
|
|
163
|
+
fs.mkdirSync(PIPER_DIR, { recursive: true });
|
|
164
|
+
}
|
|
165
|
+
console.log(' [2/3] Creating Python virtual environment...');
|
|
166
|
+
execSync(`${python} -m venv "${PIPER_VENV}"`, { stdio: 'pipe' });
|
|
167
|
+
console.log(' [3/3] Installing piper-tts package...');
|
|
168
|
+
const pip = path.join(PIPER_VENV, 'bin', 'pip');
|
|
169
|
+
execSync(`"${pip}" install --quiet piper-tts`, { stdio: 'pipe' });
|
|
170
|
+
console.log(' [✓] Piper TTS installed successfully');
|
|
171
|
+
} else {
|
|
172
|
+
const installCmd = os.platform() === 'darwin'
|
|
173
|
+
? 'brew install python@3.12'
|
|
174
|
+
: 'sudo apt install python3.12 python3.12-venv';
|
|
175
|
+
console.log(` [!] Python 3.9-3.13 not found. Install with: ${installCmd}`);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
console.log(' [✓] Piper TTS already installed');
|
|
179
|
+
}
|
|
100
180
|
} catch (err) {
|
|
101
|
-
console.log(' [!] Could not install Piper voice.
|
|
181
|
+
console.log(' [!] Could not install Piper voice:', err.message);
|
|
102
182
|
console.log(' Run manually: claude-voice voice download en_US-joe-medium');
|
|
103
183
|
}
|
|
104
184
|
|
|
@@ -106,12 +186,41 @@ try {
|
|
|
106
186
|
console.log('\nStep 5/7: Downloading Whisper STT model...');
|
|
107
187
|
console.log(' (This may take 2-3 minutes depending on connection)\n');
|
|
108
188
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
189
|
+
// Direct download without going through CLI
|
|
190
|
+
const modelId = 'whisper-tiny';
|
|
191
|
+
const modelFolder = 'sherpa-onnx-whisper-tiny';
|
|
192
|
+
const modelUrl = 'https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-whisper-tiny.tar.bz2';
|
|
193
|
+
const modelPath = path.join(MODELS_DIR, modelFolder);
|
|
194
|
+
|
|
195
|
+
if (fs.existsSync(modelPath)) {
|
|
196
|
+
console.log(` [✓] Model already installed: ${modelId}`);
|
|
197
|
+
} else {
|
|
198
|
+
// Create models directory
|
|
199
|
+
if (!fs.existsSync(MODELS_DIR)) {
|
|
200
|
+
fs.mkdirSync(MODELS_DIR, { recursive: true });
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const archivePath = path.join(MODELS_DIR, `${modelId}.tar.bz2`);
|
|
204
|
+
|
|
205
|
+
console.log(` Model: Whisper Tiny (75MB)`);
|
|
206
|
+
console.log(` [1/2] Downloading model...`);
|
|
207
|
+
execSync(`curl -L --progress-bar -o "${archivePath}" "${modelUrl}"`, {
|
|
208
|
+
stdio: 'inherit',
|
|
209
|
+
cwd: MODELS_DIR
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
console.log(' [2/2] Extracting model files...');
|
|
213
|
+
execSync(`tar -xjf "${archivePath}"`, {
|
|
214
|
+
stdio: 'pipe',
|
|
215
|
+
cwd: MODELS_DIR
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Cleanup archive
|
|
219
|
+
fs.unlinkSync(archivePath);
|
|
220
|
+
console.log(` [✓] Model installed: ${modelId}`);
|
|
221
|
+
}
|
|
113
222
|
} catch (err) {
|
|
114
|
-
console.log(' [!] Could not download STT model.
|
|
223
|
+
console.log(' [!] Could not download STT model:', err.message);
|
|
115
224
|
console.log(' Run manually: claude-voice model download whisper-tiny');
|
|
116
225
|
}
|
|
117
226
|
|
|
@@ -119,12 +228,41 @@ try {
|
|
|
119
228
|
console.log('\nStep 6/7: Downloading Sherpa-ONNX Wake Word model...');
|
|
120
229
|
console.log(' (Sherpa-ONNX keyword spotting - ~19MB)\n');
|
|
121
230
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
231
|
+
// Direct download without going through CLI
|
|
232
|
+
const kwsModelId = 'kws-zipformer-gigaspeech';
|
|
233
|
+
const kwsModelFolder = 'sherpa-onnx-kws-zipformer-gigaspeech-3.3M-2024-01-01';
|
|
234
|
+
const kwsModelUrl = 'https://github.com/k2-fsa/sherpa-onnx/releases/download/kws-models/sherpa-onnx-kws-zipformer-gigaspeech-3.3M-2024-01-01.tar.bz2';
|
|
235
|
+
const kwsModelPath = path.join(MODELS_DIR, kwsModelFolder);
|
|
236
|
+
|
|
237
|
+
if (fs.existsSync(kwsModelPath)) {
|
|
238
|
+
console.log(` [✓] Model already installed: ${kwsModelId}`);
|
|
239
|
+
} else {
|
|
240
|
+
// Create models directory
|
|
241
|
+
if (!fs.existsSync(MODELS_DIR)) {
|
|
242
|
+
fs.mkdirSync(MODELS_DIR, { recursive: true });
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const archivePath = path.join(MODELS_DIR, `${kwsModelId}.tar.bz2`);
|
|
246
|
+
|
|
247
|
+
console.log(` Model: Keyword Spotter English (19MB)`);
|
|
248
|
+
console.log(` [1/2] Downloading model...`);
|
|
249
|
+
execSync(`curl -L --progress-bar -o "${archivePath}" "${kwsModelUrl}"`, {
|
|
250
|
+
stdio: 'inherit',
|
|
251
|
+
cwd: MODELS_DIR
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
console.log(' [2/2] Extracting model files...');
|
|
255
|
+
execSync(`tar -xjf "${archivePath}"`, {
|
|
256
|
+
stdio: 'pipe',
|
|
257
|
+
cwd: MODELS_DIR
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Cleanup archive
|
|
261
|
+
fs.unlinkSync(archivePath);
|
|
262
|
+
console.log(` [✓] Model installed: ${kwsModelId}`);
|
|
263
|
+
}
|
|
126
264
|
} catch (err) {
|
|
127
|
-
console.log(' [!] Could not download wake word model.
|
|
265
|
+
console.log(' [!] Could not download wake word model:', err.message);
|
|
128
266
|
console.log(' Run manually: claude-voice model download kws-zipformer-gigaspeech');
|
|
129
267
|
}
|
|
130
268
|
|