klaudio 0.10.2 → 0.10.3

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 (2) hide show
  1. package/package.json +1 -2
  2. package/src/tts.js +56 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klaudio",
3
- "version": "0.10.2",
3
+ "version": "0.10.3",
4
4
  "description": "Add sound effects to your coding sessions — play sounds when tasks complete, notifications arrive, and more",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,7 +32,6 @@
32
32
  "ink": "^6.8.0",
33
33
  "ink-select-input": "^6.2.0",
34
34
  "ink-spinner": "^5.0.0",
35
- "kokoro-js": "^1.2.1",
36
35
  "react": "^19.2.4"
37
36
  },
38
37
  "engines": {
package/src/tts.js CHANGED
@@ -40,17 +40,70 @@ const KOKORO_VOICES = [
40
40
  // Singleton: reuse the loaded model across calls
41
41
  let kokoroInstance = null;
42
42
  let kokoroLoadPromise = null;
43
+ const KOKORO_DIR = join(homedir(), ".klaudio", "kokoro");
43
44
 
44
45
  /**
45
- * Load the Kokoro TTS model (singleton, downloads ~86MB on first use).
46
- * Uses CPU backend (DirectML has ConvTranspose compatibility issues).
46
+ * Ensure kokoro-js is installed in ~/.klaudio/kokoro.
47
+ * Installs on first use via npm.
48
+ */
49
+ async function ensureKokoroInstalled() {
50
+ const kokoroMod = join(KOKORO_DIR, "node_modules", "kokoro-js");
51
+ try {
52
+ await stat(join(kokoroMod, "package.json"));
53
+ return; // already installed
54
+ } catch { /* needs install */ }
55
+
56
+ await mkdir(KOKORO_DIR, { recursive: true });
57
+ await fsWriteFile(join(KOKORO_DIR, "package.json"), '{"private":true}', "utf-8");
58
+
59
+ const npmCmd = platform() === "win32" ? "npm.cmd" : "npm";
60
+ await new Promise((resolve, reject) => {
61
+ execFile(npmCmd, ["install", "kokoro-js"], {
62
+ cwd: KOKORO_DIR,
63
+ windowsHide: true,
64
+ timeout: 180000,
65
+ }, (err) => err ? reject(err) : resolve());
66
+ });
67
+ }
68
+
69
+ /**
70
+ * Try to import kokoro-js from various locations.
71
+ */
72
+ async function importKokoro() {
73
+ // 1. Try local ~/.klaudio/kokoro install
74
+ try {
75
+ const { createRequire } = await import("node:module");
76
+ const req = createRequire(join(KOKORO_DIR, "node_modules", "kokoro-js", "package.json"));
77
+ return req("kokoro-js");
78
+ } catch { /* not there */ }
79
+
80
+ // 2. Try global/project import (dev environment or globally installed)
81
+ try {
82
+ return await import("kokoro-js");
83
+ } catch { /* not available */ }
84
+
85
+ throw new Error("kokoro-js not available");
86
+ }
87
+
88
+ /**
89
+ * Load the Kokoro TTS model (singleton).
90
+ * Auto-installs kokoro-js on first use, then downloads ~25MB model on first generate.
47
91
  */
48
92
  async function getKokoro() {
49
93
  if (kokoroInstance) return kokoroInstance;
50
94
  if (kokoroLoadPromise) return kokoroLoadPromise;
51
95
 
52
96
  kokoroLoadPromise = (async () => {
53
- const { KokoroTTS } = await import("kokoro-js");
97
+ // Try import first (already installed?), otherwise install then import
98
+ let mod;
99
+ try {
100
+ mod = await importKokoro();
101
+ } catch {
102
+ await ensureKokoroInstalled();
103
+ mod = await importKokoro();
104
+ }
105
+
106
+ const { KokoroTTS } = mod;
54
107
  kokoroInstance = await KokoroTTS.from_pretrained(
55
108
  "onnx-community/Kokoro-82M-v1.0-ONNX",
56
109
  { dtype: "q4", device: "cpu" },