feat(audio): add downloadable extra Piper voices with accents
Adds Alma (sv), Alan, Northern English, Cori, Alba (British/Scottish) and Joe, John, Norman (American) as optional voices downloaded one at a time from Settings, with gender (measured pitch) and accent shown in the voice lists. The standard install is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,7 +36,7 @@ function listVoices(voiceDirs) {
|
||||
entries.filter((entry) => entry.endsWith(".onnx") && entries.includes(`${entry}.json`)).forEach((entry) => {
|
||||
const name = entry.slice(0, -".onnx".length);
|
||||
const known = VOICE_CATALOG.find((voice) => voice.name === name);
|
||||
if (!voices.has(name)) voices.set(name, { name, file: path.join(dir, entry), language: name.split(/[_-]/)[0].toLowerCase(), gender: known?.gender || "", label: known?.label || name, isDefault: Boolean(known?.default) });
|
||||
if (!voices.has(name)) voices.set(name, { name, file: path.join(dir, entry), language: name.split(/[_-]/)[0].toLowerCase(), gender: known?.gender || "", accent: known?.accent || "", label: known?.label || name, isDefault: Boolean(known?.default) });
|
||||
});
|
||||
});
|
||||
return [...voices.values()].sort((a, b) => a.name.localeCompare(b.name));
|
||||
@@ -64,7 +64,11 @@ function createTts({ dataDir, projectDir, piperBin = process.env.RC_PIPER_BIN ||
|
||||
const voices = listVoices(voiceDirs);
|
||||
let cachedLines = 0;
|
||||
try { cachedLines = fs.readdirSync(cacheDir).filter((entry) => entry.endsWith(".wav")).length; } catch {}
|
||||
return { available: Boolean(binary && voices.length), binary, voices: voices.map(({ name, language, gender, label, isDefault }) => ({ name, language, gender, label, isDefault })), voiceDirs, cachedLines };
|
||||
const installed = new Set(voices.map((voice) => voice.name));
|
||||
// Catalog voices not installed yet, offered for download in Settings.
|
||||
const available = VOICE_CATALOG.filter((voice) => !installed.has(voice.name))
|
||||
.map(({ name, language, gender, accent = "", label }) => ({ name, language, gender, accent, label }));
|
||||
return { available: Boolean(binary && voices.length), binary, voices: voices.map(({ name, language, gender, accent, label, isDefault }) => ({ name, language, gender, accent, label, isDefault })), downloadable: available, voiceDirs, cachedLines };
|
||||
}
|
||||
|
||||
// The voice name and speed are part of the key, so changing either never replays a stale line.
|
||||
|
||||
Reference in New Issue
Block a user