@drakulavich/kesha-voice-kit 1.10.1 → 1.11.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drakulavich/kesha-voice-kit",
3
- "version": "1.10.1",
3
+ "version": "1.11.0",
4
4
  "description": "Open-source voice toolkit. Speech-to-text (25 langs, ~19x faster than Whisper on Apple Silicon, ONNX fallback on CPU), text-to-speech (Kokoro + Vosk-TTS + ~180 macOS system voices, SSML), voice-activity detection, language detection (107 langs). Rust engine, OpenClaw skill.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,7 +30,7 @@
30
30
  ]
31
31
  },
32
32
  "keshaEngine": {
33
- "version": "1.10.0"
33
+ "version": "1.11.0"
34
34
  },
35
35
  "scripts": {
36
36
  "test": "bun test",
package/src/engine.ts CHANGED
@@ -1,8 +1,15 @@
1
1
  import { join } from "path";
2
2
  import { homedir } from "os";
3
- import { existsSync } from "fs";
3
+ import { existsSync, statSync } from "fs";
4
4
  import { log } from "./log";
5
5
 
6
+ /**
7
+ * Capability-flag string surfaced via `kesha-engine --capabilities-json`. Single
8
+ * source of truth so the engine, the TS CLI gate, and the integration tests
9
+ * can't drift. Mirrors `rust/src/transcribe.rs::TRANSCRIBE_SEGMENTS_FEATURE`.
10
+ */
11
+ export const TRANSCRIBE_SEGMENTS_FEATURE = "transcribe.segments";
12
+
6
13
  export interface LangDetectResult {
7
14
  code: string;
8
15
  confidence: number;
@@ -108,7 +115,7 @@ export async function transcribeEngineWithSegments(
108
115
  opts: TranscribeEngineOptions = {},
109
116
  ): Promise<TranscriptionOutput> {
110
117
  const caps = await getEngineCapabilities();
111
- if (!caps?.features.includes("transcribe.segments")) {
118
+ if (!caps?.features.includes(TRANSCRIBE_SEGMENTS_FEATURE)) {
112
119
  throw new Error(
113
120
  "Timestamped segments require a newer kesha-engine. Run `kesha install` after upgrading Kesha Voice Kit.",
114
121
  );
@@ -162,20 +169,33 @@ export interface EngineCapabilities {
162
169
  }
163
170
 
164
171
  let cachedEngineCapabilities:
165
- | { binPath: string; capabilities: EngineCapabilities }
172
+ | { binPath: string; mtime: number; capabilities: EngineCapabilities }
166
173
  | null = null;
167
174
 
168
175
  export async function getEngineCapabilities(): Promise<EngineCapabilities | null> {
169
176
  const binPath = getEngineBinPath();
170
- if (cachedEngineCapabilities?.binPath === binPath) {
177
+ // Cache key includes `mtimeMs` so the cache invalidates when `kesha
178
+ // install` overwrites the binary in-place within a single long-lived
179
+ // process (#248). `statSync` throws on missing-file; the catch returns
180
+ // `null` — same effect as the previous explicit `isEngineInstalled()`
181
+ // pre-flight, one fewer redundant fs call.
182
+ let mtime: number;
183
+ try {
184
+ mtime = statSync(binPath).mtimeMs;
185
+ } catch {
186
+ return null;
187
+ }
188
+ if (
189
+ cachedEngineCapabilities?.binPath === binPath &&
190
+ cachedEngineCapabilities.mtime === mtime
191
+ ) {
171
192
  return cachedEngineCapabilities.capabilities;
172
193
  }
173
- if (!existsSync(binPath)) return null;
174
194
  const { stdout, exitCode } = await runEngine(["--capabilities-json"]);
175
195
  if (exitCode !== 0) return null;
176
196
  try {
177
197
  const capabilities = JSON.parse(stdout) as EngineCapabilities;
178
- cachedEngineCapabilities = { binPath, capabilities };
198
+ cachedEngineCapabilities = { binPath, mtime, capabilities };
179
199
  return capabilities;
180
200
  } catch {
181
201
  return null;
package/src/lib.ts CHANGED
@@ -44,7 +44,7 @@ export async function transcribe(
44
44
  return internalTranscribe(audioPath, { ...options, silent: true });
45
45
  }
46
46
 
47
- export async function transcribeWithSegments(
47
+ export async function transcribeWithTimestamps(
48
48
  audioPath: string,
49
49
  options: TranscribeOptions = {},
50
50
  ) {
@@ -58,3 +58,10 @@ export async function transcribeWithSegments(
58
58
  silent: true,
59
59
  });
60
60
  }
61
+
62
+ /**
63
+ * @deprecated Renamed to {@link transcribeWithTimestamps} (#248). The old
64
+ * name shipped briefly in v1.9.0; this alias keeps existing imports working
65
+ * for one minor-version cycle. Will be removed in v1.12.0.
66
+ */
67
+ export const transcribeWithSegments = transcribeWithTimestamps;