@drakulavich/kesha-voice-kit 1.19.0 → 1.20.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 +17 -3
- package/SKILL.md +6 -0
- package/completions/kesha.fish +1 -1
- package/completions/kesha.zsh +1 -1
- package/man/kesha.1 +2 -2
- package/package.json +3 -3
- package/src/cli/say.ts +7 -4
- package/src/synth.ts +3 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="docs/assets/logo.png" alt="Kesha Voice Kit" width="200">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/drakulavich/kesha-voice-kit/main/docs/assets/logo.png" alt="Kesha Voice Kit" width="200">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">Kesha Voice Kit</h1>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
See [Product positioning](docs/product-positioning.md) for supported workflows, non-goals, maturity labels, and the platform matrix.
|
|
22
22
|
|
|
23
23
|
<p align="center">
|
|
24
|
-
<img src="
|
|
24
|
+
<img src="https://raw.githubusercontent.com/drakulavich/kesha-voice-kit/main/demo.gif" alt="kesha demo — English + Russian transcription with automatic language detection" width="800">
|
|
25
25
|
</p>
|
|
26
26
|
|
|
27
27
|
## Quick Start
|
|
@@ -104,6 +104,16 @@ kesha say "Hello, world" > hello.wav
|
|
|
104
104
|
kesha say "Привет, мир" > privet.wav # auto-routes (Milena on darwin, ru-vosk-m02 elsewhere)
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
+
**Output formats** (`--format`, or inferred from `--out` extension):
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
kesha say "Hello" --out hi.wav # WAV (default, uncompressed)
|
|
111
|
+
kesha say "Hello" --format ogg-opus --out hi.ogg # OGG/Opus — messenger voice notes (Telegram/WhatsApp/Signal)
|
|
112
|
+
kesha say "Hello" --format flac --out hi.flac # FLAC — lossless, royalty-free, plays in every browser incl. Safari/iOS
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
FLAC is the format for web-embeddable samples: it plays natively in all modern browsers (including Safari/iOS, where OGG/Opus does not), stays royalty-free like Opus, and keeps the engine's native sample rate (no resample). `--bitrate` / `--sample-rate` apply only to `--format ogg-opus`.
|
|
116
|
+
|
|
107
117
|
**Russian abbreviations** (`ru-vosk-*`): all-uppercase Cyrillic 2-5-char tokens auto-expand letter-by-letter when not pronounceable as a Russian syllable (ФСБ → "эф-эс-бэ", ВОЗ → "воз"). Disable with `--no-expand-abbrev`. See [docs/tts.md#russian-abbreviation-auto-expansion](docs/tts.md#russian-abbreviation-auto-expansion).
|
|
108
118
|
|
|
109
119
|
**English acronyms** (`en-*`, Kokoro): three-table mechanism (letter-spell rule + STOP_LIST + IPA_LEXICON) auto-expands FBI → "ef bee eye" and gives EPAM/JSON/Anthropic the right IPA. Disable letter-spell with `--no-expand-abbrev`. See [docs/tts.md#english-acronym-auto-expansion](docs/tts.md#english-acronym-auto-expansion).
|
|
@@ -232,7 +242,7 @@ mandb ~/.local/share/man 2>/dev/null || true
|
|
|
232
242
|
|
|
233
243
|
Compared against Whisper `large-v3-turbo` — all engines auto-detect language.
|
|
234
244
|
|
|
235
|
-

|
|
245
|
+

|
|
236
246
|
|
|
237
247
|
See [BENCHMARK.md](BENCHMARK.md) for the full per-file breakdown (Russian + English).
|
|
238
248
|
|
|
@@ -280,6 +290,10 @@ Cache boundary: `kesha install` and opt-in feature installs populate the local
|
|
|
280
290
|
cache; ordinary transcription and speech commands fail fast if required assets
|
|
281
291
|
are missing.
|
|
282
292
|
|
|
293
|
+
Contributors: see [`docs/architecture.md`](docs/architecture.md) for the
|
|
294
|
+
code-level map (repo layout, CLI↔engine boundary, backends, model pinning,
|
|
295
|
+
tests, and a "where to change X" table).
|
|
296
|
+
|
|
283
297
|
## What's Inside
|
|
284
298
|
|
|
285
299
|
| Model | Task | Size | Source |
|
package/SKILL.md
CHANGED
|
@@ -168,6 +168,12 @@ kesha say --list-voices # Kokoro + Vosk-TTS + ~180 ma
|
|
|
168
168
|
|
|
169
169
|
Output: WAV mono float32 by default. `--out <path>` writes to a file instead of stdout. For Telegram/OpenClaw replies, prefer `--format ogg-opus --out reply.ogg` or the OpenClaw-provided `{{OutputPath}}`.
|
|
170
170
|
|
|
171
|
+
**Output formats** (`--format`, or inferred from the `--out` extension): `wav` (default, uncompressed), `ogg-opus` (messenger voice notes), `flac` (lossless, royalty-free, plays in every browser incl. Safari/iOS — the format for web-embeddable samples). FLAC keeps the engine's native rate; `--bitrate` / `--sample-rate` apply only to `ogg-opus`.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
kesha say --format flac --out sample.flac "Hello" # web-embeddable, Safari-safe
|
|
175
|
+
```
|
|
176
|
+
|
|
171
177
|
**Voice notes (Telegram / WhatsApp / Signal / Discord):** add `--format ogg-opus` to emit OGG/Opus directly — the format messenger APIs render as a native voice message:
|
|
172
178
|
|
|
173
179
|
```bash
|
package/completions/kesha.fish
CHANGED
|
@@ -69,7 +69,7 @@ complete -c kesha -n '__fish_seen_subcommand_from say' -l out -r -d 'Write audio
|
|
|
69
69
|
complete -c kesha -n '__fish_seen_subcommand_from say' -l rate -r -d 'Speaking rate 0.5–2.0'
|
|
70
70
|
complete -c kesha -n '__fish_seen_subcommand_from say' -l list-voices -d 'List installed voices and exit'
|
|
71
71
|
complete -c kesha -n '__fish_seen_subcommand_from say' -l ssml -d 'Parse input as SSML (supports <speak>, <break>; strips unknown tags)'
|
|
72
|
-
complete -c kesha -n '__fish_seen_subcommand_from say' -l format -r -d 'Output format: wav (default)
|
|
72
|
+
complete -c kesha -n '__fish_seen_subcommand_from say' -l format -r -d 'Output format: wav (default), ogg-opus (Telegram-ready voice note), or flac (lossless, plays in all browsers incl. Safari). Inferred from --out extension when omitted.'
|
|
73
73
|
complete -c kesha -n '__fish_seen_subcommand_from say' -l bitrate -r -d 'Opus bitrate in bits/sec (e.g. 32000). Only with --format ogg-opus.'
|
|
74
74
|
complete -c kesha -n '__fish_seen_subcommand_from say' -l sample-rate -r -d 'Opus encoder sample rate (8000/12000/16000/24000/48000). Only with --format ogg-opus.'
|
|
75
75
|
complete -c kesha -n '__fish_seen_subcommand_from say' -l no-expand-abbrev -d 'Disable Russian acronym auto-expansion (ВОЗ → \'вэ о зэ\') for ru-vosk-* voices. <say-as interpret-as=\'characters\'> still works. Applies to Russian (ru-vosk-*) and English (en-*) voices.'
|
package/completions/kesha.zsh
CHANGED
|
@@ -99,7 +99,7 @@ _kesha() {
|
|
|
99
99
|
'--rate=[Speaking rate 0.5–2.0]:rate:' \
|
|
100
100
|
'--list-voices[List installed voices and exit]' \
|
|
101
101
|
'--ssml[Parse input as SSML (supports <speak>, <break>; strips unknown tags)]' \
|
|
102
|
-
'--format=[Output format: wav (default)
|
|
102
|
+
'--format=[Output format: wav (default), ogg-opus (Telegram-ready voice note), or flac (lossless, plays in all browsers incl. Safari). Inferred from --out extension when omitted.]:format:' \
|
|
103
103
|
'--bitrate=[Opus bitrate in bits/sec (e.g. 32000). Only with --format ogg-opus.]:bitrate:' \
|
|
104
104
|
'--sample-rate=[Opus encoder sample rate (8000/12000/16000/24000/48000). Only with --format ogg-opus.]:sample rate:' \
|
|
105
105
|
'--no-expand-abbrev[Disable Russian acronym auto-expansion (ВОЗ → '\''вэ о зэ'\'') for ru-vosk-* voices. <say-as interpret-as='\''characters'\''> still works. Applies to Russian (ru-vosk-*) and English (en-*) voices.]' \
|
package/man/kesha.1
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.TH KESHA 1 "May 2026" "kesha 1.
|
|
1
|
+
.TH KESHA 1 "May 2026" "kesha 1.20.0" "User Commands"
|
|
2
2
|
.SH NAME
|
|
3
3
|
kesha \- open-source local voice toolkit
|
|
4
4
|
.SH SYNOPSIS
|
|
@@ -167,7 +167,7 @@ List installed voices and exit
|
|
|
167
167
|
Parse input as SSML (supports <speak>, <break>; strips unknown tags)
|
|
168
168
|
.TP
|
|
169
169
|
.B \-\-format
|
|
170
|
-
Output format: wav (default)
|
|
170
|
+
Output format: wav (default), ogg\-opus (Telegram\-ready voice note), or flac (lossless, plays in all browsers incl. Safari). Inferred from \-\-out extension when omitted.
|
|
171
171
|
.TP
|
|
172
172
|
.B \-\-bitrate
|
|
173
173
|
Opus bitrate in bits/sec (e.g. 32000). Only with \-\-format ogg\-opus.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drakulavich/kesha-voice-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Give your local tools a voice: fast STT in 25 languages (~19x faster than Whisper on Apple Silicon, ONNX CPU fallback), TTS via Kokoro/Vosk/macOS voices, VAD + 107-language detection. Rust engine, Bun CLI, OpenClaw skill.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
]
|
|
33
33
|
},
|
|
34
34
|
"keshaEngine": {
|
|
35
|
-
"version": "1.
|
|
35
|
+
"version": "1.20.0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"test": "bun test",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@types/bun": "latest",
|
|
81
81
|
"@typescript/native-preview": "^7.0.0-dev.20260423.1",
|
|
82
|
-
"fast-xml-parser": "^5.
|
|
82
|
+
"fast-xml-parser": "^5.8.0",
|
|
83
83
|
"typescript": "^6.0.2",
|
|
84
84
|
"yaml": "^2.9.0"
|
|
85
85
|
},
|
package/src/cli/say.ts
CHANGED
|
@@ -100,7 +100,7 @@ export const sayCommand = defineCommand({
|
|
|
100
100
|
format: {
|
|
101
101
|
type: "string",
|
|
102
102
|
description:
|
|
103
|
-
"Output format: wav (default)
|
|
103
|
+
"Output format: wav (default), ogg-opus (Telegram-ready voice note), or flac (lossless, plays in all browsers incl. Safari). Inferred from --out extension when omitted.",
|
|
104
104
|
},
|
|
105
105
|
bitrate: {
|
|
106
106
|
type: "string",
|
|
@@ -145,12 +145,12 @@ export const sayCommand = defineCommand({
|
|
|
145
145
|
const fmtArg = typeof args.format === "string" ? args.format.toLowerCase() : undefined;
|
|
146
146
|
let format: SayFormat | undefined;
|
|
147
147
|
if (fmtArg) {
|
|
148
|
-
if (fmtArg === "wav" || fmtArg === "ogg-opus") {
|
|
148
|
+
if (fmtArg === "wav" || fmtArg === "ogg-opus" || fmtArg === "flac") {
|
|
149
149
|
format = fmtArg;
|
|
150
150
|
} else if (fmtArg === "opus" || fmtArg === "ogg") {
|
|
151
151
|
format = "ogg-opus";
|
|
152
152
|
} else {
|
|
153
|
-
log.error(`unknown --format '${args.format}'. supported: wav, ogg-opus`);
|
|
153
|
+
log.error(`unknown --format '${args.format}'. supported: wav, ogg-opus, flac`);
|
|
154
154
|
process.exit(2);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
@@ -166,7 +166,10 @@ export const sayCommand = defineCommand({
|
|
|
166
166
|
? args.out.split(".").pop()?.toLowerCase()
|
|
167
167
|
: undefined;
|
|
168
168
|
const impliesOpus = outExt && ["ogg", "opus", "oga"].includes(outExt);
|
|
169
|
-
|
|
169
|
+
// --bitrate / --sample-rate are Opus-only. Reject for wav and flac
|
|
170
|
+
// (both lossless / no encoder knobs) and for any non-Opus extension.
|
|
171
|
+
const resolvesToOpus = format === "ogg-opus" || (format === undefined && impliesOpus);
|
|
172
|
+
if (!resolvesToOpus) {
|
|
170
173
|
log.error("--bitrate and --sample-rate are only valid with --format ogg-opus");
|
|
171
174
|
process.exit(2);
|
|
172
175
|
}
|
package/src/synth.ts
CHANGED
|
@@ -14,8 +14,10 @@ import { registerProcessTree } from "./process-tree";
|
|
|
14
14
|
* - `wav` (default): RIFF WAV at the engine's native sample rate.
|
|
15
15
|
* - `ogg-opus`: OGG-encapsulated Opus, mono. The format Telegram, WhatsApp,
|
|
16
16
|
* Signal, and Discord render as native voice messages. See #223.
|
|
17
|
+
* - `flac`: lossless, royalty-free, plays in every modern browser including
|
|
18
|
+
* Safari/iOS. Keeps the engine's native rate; no bitrate knob.
|
|
17
19
|
*/
|
|
18
|
-
export type SayFormat = "wav" | "ogg-opus";
|
|
20
|
+
export type SayFormat = "wav" | "ogg-opus" | "flac";
|
|
19
21
|
export const MAX_TEXT_CHARS = 5000;
|
|
20
22
|
|
|
21
23
|
export interface SayOptions {
|