@drakulavich/kesha-voice-kit 1.9.0 → 1.10.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 +21 -0
- package/SKILL.md +2 -0
- package/package.json +2 -2
- package/src/cli/say.ts +1 -1
- package/src/say.ts +7 -5
package/README.md
CHANGED
|
@@ -86,6 +86,27 @@ kesha say --voice ru-vosk-m02 --ssml \
|
|
|
86
86
|
|
|
87
87
|
Detection rule: auto-expand fires when the token cannot be pronounced as a natural Russian syllable — length ≤ 2 (ИП, ЕС), 0 vowels (ФСБ, СНГ), 2+ consecutive vowels (ОАЭ), or 2+ consecutive consonants (США, ЦСКА). Tokens with strict CVC/CVCV alternation pass through (ВОЗ → "воз", НАТО → "нато", ОПЕК → "опек"). Small stop-list for common short words (ОН, МЫ, ВЫ, КАК, ЧТО, …) and Ъ/Ь-containing tokens are always skipped. See [#232](https://github.com/drakulavich/kesha-voice-kit/issues/232).
|
|
88
88
|
|
|
89
|
+
**English acronyms** (`en-*` voices, Kokoro-82M):
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Auto-expand on by default — FBI reads as "ef bee eye"
|
|
93
|
+
kesha say --voice en-am_michael 'The FBI is investigating.'
|
|
94
|
+
|
|
95
|
+
# Force a literal reading (Kokoro fuses unknown caps tokens to one syllable)
|
|
96
|
+
kesha say --voice en-am_michael --no-expand-abbrev 'FBI.'
|
|
97
|
+
|
|
98
|
+
# Explicit SSML control (overrides the rule and the stop-list)
|
|
99
|
+
kesha say --voice en-am_michael --ssml \
|
|
100
|
+
'<speak><say-as interpret-as="characters">NASA</say-as></speak>'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Three-table mechanism:
|
|
104
|
+
- **Letter-spell** — uppercase Latin tokens 2–5 chars (no digits, no mixed case) get expanded letter-by-letter (FBI → "ef bee eye"). Disable with `--no-expand-abbrev`.
|
|
105
|
+
- **`STOP_LIST`** (30 entries) — natural-English caps words pass through unchanged: NASA, NATO, AIDS, OPEC, IKEA, ASCII, NAFTA, LASER, RADAR, SCUBA + emphatic length-2 caps (OK, NO, GO, IT, IS, AS, AT, BY, IN, ON, OR, OF, TO, WE, US, MY, ME, HE, BE, DO).
|
|
106
|
+
- **`IPA_LEXICON`** (20 entries) — case-sensitive token → IPA-phoneme map that bypasses G2P entirely. Covers all-caps acronyms with industry pronunciations (EPAM, JSON, JPEG, SQL, ASAP, GIF, CRUD, JWT) AND mixed-case proper nouns (Anthropic, Microsoft, Claude, NVIDIA, Kubernetes, PostgreSQL, GraphQL, Linux, Tokio, macOS, Granola, OAuth). IPA hits fire even with `--no-expand-abbrev` — they're intent-explicit, parallel to `<say-as>`.
|
|
107
|
+
|
|
108
|
+
Override per-token via SSML `<say-as interpret-as="characters">…</say-as>` (always letter-spells via the table). See [#244](https://github.com/drakulavich/kesha-voice-kit/issues/244).
|
|
109
|
+
|
|
89
110
|
**Russian word stress** (`ru-vosk-*` voices):
|
|
90
111
|
|
|
91
112
|
```bash
|
package/SKILL.md
CHANGED
|
@@ -76,6 +76,8 @@ Format is also inferred from `--out` extension (`.ogg` / `.opus` / `.oga` → OG
|
|
|
76
76
|
|
|
77
77
|
**Russian abbreviation handling** (`ru-vosk-*` only): all-uppercase Cyrillic tokens (length 2–5) auto-expand letter-by-letter when the token cannot be pronounced as a natural Russian syllable — `ФСБ объявила` → `эф-эс-бэ объявила`. Tokens with strict CVC/CVCV alternation pass through (ВОЗ → "воз", НАТО → "нато"). Disable per call with `--no-expand-abbrev`. Override per-token via SSML `<say-as interpret-as="characters">…</say-as>` (always wins, even with `--no-expand-abbrev`). Stop-list for common short words (ОН, МЫ, ВЫ, КАК, ЧТО) prevents false positives. Closes [#232](https://github.com/drakulavich/kesha-voice-kit/issues/232).
|
|
78
78
|
|
|
79
|
+
**English acronym handling** (`en-*` Kokoro-82M only). Three tables: (1) **letter-spell** for uppercase 2–5-char tokens not on the stop-list (FBI → "ef bee eye", HTTP → "aitch tee tee pee"); (2) **`STOP_LIST`** (30 entries) — natural-English caps words pass through (NASA, NATO, AIDS, OPEC, IKEA, ASCII, NAFTA, LASER, RADAR, SCUBA + 20 emphatic length-2 caps); (3) **`IPA_LEXICON`** (20 entries) — case-sensitive token → IPA-phoneme map that bypasses G2P entirely. Covers industry-pronunciation acronyms (EPAM /ˈiːpæm/, JSON /ˈdʒeɪsən/, JPEG, SQL, ASAP, GIF, CRUD, JWT, OAuth) AND mixed-case proper nouns (Anthropic /ænˈθrɒpɪk/, Microsoft, Claude, NVIDIA, Kubernetes, PostgreSQL, GraphQL, Linux, Tokio, macOS, Granola). Disable letter-spell with `--no-expand-abbrev` — IPA hits still fire (intent-explicit). Override per-token via SSML `<say-as interpret-as="characters">…</say-as>` (always wins). Closes [#244](https://github.com/drakulavich/kesha-voice-kit/issues/244).
|
|
80
|
+
|
|
79
81
|
**Russian word stress** (`ru-vosk-*` only): `<emphasis>сл+ово</emphasis>` shifts stress to the vowel marked with `+`. `<emphasis level="none">сл+ово</emphasis>` strips the `+` (cancel inherited emphasis). Other voices (`en-*`, `macos-*`) silently strip the `+` and warn once per process. Auto-stress dictionary not provided — caller writes the `+` manually. Closes [#233](https://github.com/drakulavich/kesha-voice-kit/issues/233).
|
|
80
82
|
|
|
81
83
|
## Language detection standalone
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drakulavich/kesha-voice-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.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.
|
|
33
|
+
"version": "1.10.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"test": "bun test",
|
package/src/cli/say.ts
CHANGED
|
@@ -86,7 +86,7 @@ export const sayCommand = defineCommand({
|
|
|
86
86
|
type: "boolean",
|
|
87
87
|
description:
|
|
88
88
|
"Disable Russian acronym auto-expansion (ВОЗ → 'вэ о зэ') for ru-vosk-* voices. " +
|
|
89
|
-
"<say-as interpret-as='characters'> still works.
|
|
89
|
+
"<say-as interpret-as='characters'> still works. Applies to Russian (ru-vosk-*) and English (en-*) voices.",
|
|
90
90
|
},
|
|
91
91
|
verbose: {
|
|
92
92
|
type: "boolean",
|
package/src/say.ts
CHANGED
|
@@ -39,9 +39,9 @@ export interface SayOptions {
|
|
|
39
39
|
*/
|
|
40
40
|
sampleRate?: number;
|
|
41
41
|
/**
|
|
42
|
-
* Disable
|
|
42
|
+
* Disable acronym auto-expansion for `ru-vosk-*` and `en-*` voices.
|
|
43
43
|
* When true, passes `--no-expand-abbrev` to the engine (requires engine
|
|
44
|
-
* capability `tts.ru_acronym_expansion`; silently dropped for older engines).
|
|
44
|
+
* capability `tts.ru_acronym_expansion` or `tts.en_acronym_expansion`; silently dropped for older engines).
|
|
45
45
|
* `<say-as interpret-as="characters">` still works regardless of this flag.
|
|
46
46
|
*/
|
|
47
47
|
noExpandAbbrev?: boolean;
|
|
@@ -59,12 +59,14 @@ export function buildSayArgs(o: SayOptions, capabilities?: EngineCapabilities |
|
|
|
59
59
|
if (o.bitrate !== undefined) args.push("--bitrate", String(o.bitrate));
|
|
60
60
|
if (o.sampleRate !== undefined) args.push("--sample-rate", String(o.sampleRate));
|
|
61
61
|
if (o.noExpandAbbrev) {
|
|
62
|
-
const
|
|
63
|
-
|
|
62
|
+
const supportsExpand = capabilities?.features?.some(
|
|
63
|
+
(f) => f === "tts.ru_acronym_expansion" || f === "tts.en_acronym_expansion",
|
|
64
|
+
) ?? false;
|
|
65
|
+
if (supportsExpand) {
|
|
64
66
|
args.push("--no-expand-abbrev");
|
|
65
67
|
} else {
|
|
66
68
|
log.debug(
|
|
67
|
-
"kesha-engine does not advertise tts.ru_acronym_expansion; dropping --no-expand-abbrev",
|
|
69
|
+
"kesha-engine does not advertise tts.ru_acronym_expansion or tts.en_acronym_expansion; dropping --no-expand-abbrev",
|
|
68
70
|
);
|
|
69
71
|
}
|
|
70
72
|
}
|