mia-narrative 1.0.2 → 1.0.4
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/dist/src/commands/voices.d.ts.map +1 -1
- package/dist/src/commands/voices.js +11 -9
- package/dist/src/commands/voices.js.map +1 -1
- package/dist/src/config/voices.js +20 -20
- package/dist/src/config/voices.js.map +1 -1
- package/dist/src/engines/base.d.ts +1 -0
- package/dist/src/engines/base.d.ts.map +1 -1
- package/dist/src/engines/base.js.map +1 -1
- package/dist/src/engines/piper.d.ts.map +1 -1
- package/dist/src/engines/piper.js +22 -4
- package/dist/src/engines/piper.js.map +1 -1
- package/package.json +1 -1
- package/scripts/setup.js +62 -36
- package/src/commands/voices.ts +11 -9
- package/src/config/voices.ts +20 -20
- package/src/engines/base.ts +1 -0
- package/src/engines/piper.ts +27 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voices.d.ts","sourceRoot":"","sources":["../../../src/commands/voices.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAIlE,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;CACpC;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"voices.d.ts","sourceRoot":"","sources":["../../../src/commands/voices.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAIlE,UAAU,iBAAiB;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;CACpC;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2D7E"}
|
|
@@ -32,17 +32,19 @@ export async function voicesCommand(options) {
|
|
|
32
32
|
// Table format
|
|
33
33
|
Logger.log('');
|
|
34
34
|
Logger.log(`Available Voices for ${engineType}:`);
|
|
35
|
-
Logger.log('─'.repeat(
|
|
36
|
-
const idHeader = 'ID'.padEnd(
|
|
37
|
-
const nameHeader = 'Name';
|
|
38
|
-
|
|
39
|
-
Logger.log(
|
|
35
|
+
Logger.log('─'.repeat(100));
|
|
36
|
+
const idHeader = 'ID'.padEnd(25);
|
|
37
|
+
const nameHeader = 'Name'.padEnd(25);
|
|
38
|
+
const modelHeader = 'Model';
|
|
39
|
+
Logger.log(` ${idHeader}${nameHeader}${modelHeader}`);
|
|
40
|
+
Logger.log('─'.repeat(100));
|
|
40
41
|
voices.forEach((voice) => {
|
|
41
|
-
const idStr = (voice.id || 'unknown').padEnd(
|
|
42
|
-
const nameStr = voice.name || 'Unknown';
|
|
43
|
-
|
|
42
|
+
const idStr = (voice.id || 'unknown').padEnd(25);
|
|
43
|
+
const nameStr = (voice.name || 'Unknown').padEnd(25);
|
|
44
|
+
const modelStr = voice.model || 'system';
|
|
45
|
+
Logger.log(` ${idStr}${nameStr}${modelStr}`);
|
|
44
46
|
});
|
|
45
|
-
Logger.log('─'.repeat(
|
|
47
|
+
Logger.log('─'.repeat(100));
|
|
46
48
|
Logger.log('');
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voices.js","sourceRoot":"","sources":["../../../src/commands/voices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAc,MAAM,uBAAuB,CAAC;AAClE,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAOjD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAA0B;IAC5D,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC;QAC9C,OAAO,CAAC,KAAK,CAAC,gBAAgB,UAAU,gBAAgB,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,UAAU,EAAE;YACpD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB;YAC/C,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,yBAAyB;SACjD,CAAC,CAAC;QACH,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QAEpC,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;QACxC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAElC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,2BAA2B,UAAU,UAAU,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;QAEzC,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC7B,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;gBACvB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,eAAe;YACf,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACf,MAAM,CAAC,GAAG,CAAC,wBAAwB,UAAU,GAAG,CAAC,CAAC;YAClD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"voices.js","sourceRoot":"","sources":["../../../src/commands/voices.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,62 +1,62 @@
|
|
|
1
1
|
export const VOICE_PROFILES = {
|
|
2
|
-
"mia
|
|
3
|
-
id: "mia
|
|
2
|
+
"mia": {
|
|
3
|
+
id: "mia",
|
|
4
4
|
name: "Mia",
|
|
5
5
|
gender: "female",
|
|
6
6
|
style: "professional",
|
|
7
7
|
description: "Professional narrator for expert technical content",
|
|
8
|
-
piperModel:
|
|
8
|
+
piperModel: "en_US-hfc_female-medium",
|
|
9
9
|
},
|
|
10
|
-
"miette
|
|
11
|
-
id: "miette
|
|
10
|
+
"miette": {
|
|
11
|
+
id: "miette",
|
|
12
12
|
name: "Miette",
|
|
13
13
|
gender: "female",
|
|
14
14
|
style: "conversational",
|
|
15
15
|
description: "Friendly conversational narrator",
|
|
16
|
-
piperModel: "
|
|
16
|
+
piperModel: "en_GB-alba-medium",
|
|
17
17
|
},
|
|
18
|
-
"seraphine
|
|
19
|
-
id: "seraphine
|
|
18
|
+
"seraphine": {
|
|
19
|
+
id: "seraphine",
|
|
20
20
|
name: "Seraphine",
|
|
21
21
|
gender: "female",
|
|
22
22
|
style: "narrative",
|
|
23
23
|
description: "Expressive narrative and storytelling",
|
|
24
24
|
piperModel: "en_US-libritts-high",
|
|
25
25
|
},
|
|
26
|
-
"jeremy
|
|
27
|
-
id: "jeremy
|
|
26
|
+
"jeremy": {
|
|
27
|
+
id: "jeremy",
|
|
28
28
|
name: "Jeremy",
|
|
29
29
|
gender: "male",
|
|
30
30
|
style: "professional",
|
|
31
31
|
description: "Professional male narrator",
|
|
32
32
|
piperModel: "en_US-ryan-medium",
|
|
33
33
|
},
|
|
34
|
-
"resonova
|
|
35
|
-
id: "resonova
|
|
34
|
+
"resonova": {
|
|
35
|
+
id: "resonova",
|
|
36
36
|
name: "ResoNova",
|
|
37
|
-
gender: "
|
|
37
|
+
gender: "female",
|
|
38
38
|
style: "expressive",
|
|
39
39
|
description: "Varied and experimental voice",
|
|
40
|
-
piperModel: "en_US-
|
|
40
|
+
piperModel: "en_US-kristin-medium",
|
|
41
41
|
},
|
|
42
|
-
"zephyr
|
|
43
|
-
id: "zephyr
|
|
42
|
+
"zephyr": {
|
|
43
|
+
id: "zephyr",
|
|
44
44
|
name: "Zephyr",
|
|
45
45
|
gender: "neutral",
|
|
46
46
|
style: "narrative",
|
|
47
47
|
description: "Contemplative nature and narrative voice",
|
|
48
48
|
piperModel: "en_US-kusal-medium",
|
|
49
49
|
},
|
|
50
|
-
"echo
|
|
51
|
-
id: "echo
|
|
50
|
+
"echo": {
|
|
51
|
+
id: "echo",
|
|
52
52
|
name: "Echo",
|
|
53
53
|
gender: "female",
|
|
54
54
|
style: "expressive",
|
|
55
55
|
description: "Expressive character and dialogue voice",
|
|
56
56
|
piperModel: "en_US-libritts-high",
|
|
57
57
|
},
|
|
58
|
-
"atlas
|
|
59
|
-
id: "atlas
|
|
58
|
+
"atlas": {
|
|
59
|
+
id: "atlas",
|
|
60
60
|
name: "Atlas",
|
|
61
61
|
gender: "male",
|
|
62
62
|
style: "conversational",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voices.js","sourceRoot":"","sources":["../../../src/config/voices.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,cAAc,GAAiC;IAC1D,
|
|
1
|
+
{"version":3,"file":"voices.js","sourceRoot":"","sources":["../../../src/config/voices.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,cAAc,GAAiC;IAC1D,KAAK,EAAE;QACL,EAAE,EAAE,KAAK;QACT,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,oDAAoD;QACjE,UAAU,EAAE,yBAAyB;KACtC;IACD,QAAQ,EAAE;QACR,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,kCAAkC;QAC/C,UAAU,EAAE,mBAAmB;KAChC;IACD,WAAW,EAAE;QACX,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,WAAW;QAClB,WAAW,EAAE,uCAAuC;QACpD,UAAU,EAAE,qBAAqB;KAClC;IACD,QAAQ,EAAE;QACR,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,4BAA4B;QACzC,UAAU,EAAE,mBAAmB;KAChC;IACD,UAAU,EAAE;QACV,EAAE,EAAE,UAAU;QACd,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,+BAA+B;QAC5C,UAAU,EAAE,sBAAsB;KACnC;IACD,QAAQ,EAAE;QACR,EAAE,EAAE,QAAQ;QACZ,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,WAAW;QAClB,WAAW,EAAE,0CAA0C;QACvD,UAAU,EAAE,oBAAoB;KACjC;IACD,MAAM,EAAE;QACN,EAAE,EAAE,MAAM;QACV,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,yCAAyC;QACtD,UAAU,EAAE,qBAAqB;KAClC;IACD,OAAO,EAAE;QACP,EAAE,EAAE,OAAO;QACX,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,oCAAoC;QACjD,UAAU,EAAE,mBAAmB;KAChC;CACF,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,OAAO,cAAc,CAAC,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,MAA4C;IAE5C,OAAO,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACpD,IAAI,MAAM,EAAE,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACnE,IAAI,MAAM,EAAE,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/engines/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/engines/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,8BAAsB,SAAS;IAC7B,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3D,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IACtE,QAAQ,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,QAAQ,CAAC,OAAO,IAAI,MAAM;CAC3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/engines/base.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/engines/base.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAgB,SAAS;CAM9B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"piper.d.ts","sourceRoot":"","sources":["../../../src/engines/piper.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAGpF,qBAAa,WAAY,SAAQ,SAAS;IACxC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,SAAS,CAAc;IAEzB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAclD,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"piper.d.ts","sourceRoot":"","sources":["../../../src/engines/piper.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAGpF,qBAAa,WAAY,SAAQ,SAAS;IACxC,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,SAAS,CAAc;IAEzB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAclD,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IAkD7D,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAe7B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC,OAAO,IAAI,MAAM;IAIjB,OAAO,CAAC,QAAQ;CA4CjB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn, execSync } from 'child_process';
|
|
2
|
-
import { writeFileSync, unlinkSync, readFileSync } from 'fs';
|
|
3
|
-
import { tmpdir } from 'os';
|
|
2
|
+
import { writeFileSync, unlinkSync, readFileSync, existsSync } from 'fs';
|
|
3
|
+
import { tmpdir, homedir } from 'os';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { randomUUID } from 'crypto';
|
|
6
6
|
import { Logger } from '../utils/logger.js';
|
|
@@ -33,13 +33,21 @@ export class PiperEngine extends TTSEngine {
|
|
|
33
33
|
if (!text || text.trim().length === 0) {
|
|
34
34
|
throw new Error('Text cannot be empty');
|
|
35
35
|
}
|
|
36
|
+
// Build path to model file
|
|
37
|
+
const modelDir = join(homedir(), '.local/share/piper-tts');
|
|
38
|
+
const modelFile = join(modelDir, `${voiceProfile.piperModel}.onnx`);
|
|
39
|
+
if (!existsSync(modelFile)) {
|
|
40
|
+
throw new Error(`Piper model not found: ${voiceProfile.piperModel}\n` +
|
|
41
|
+
`Expected location: ${modelFile}\n` +
|
|
42
|
+
`Run 'npm run setup' to download models.`);
|
|
43
|
+
}
|
|
36
44
|
const tempDir = tmpdir();
|
|
37
45
|
const uid = randomUUID();
|
|
38
46
|
const textFile = join(tempDir, `piper-input-${uid}.txt`);
|
|
39
47
|
const audioFile = join(tempDir, `piper-output-${uid}.wav`);
|
|
40
48
|
try {
|
|
41
49
|
writeFileSync(textFile, text, 'utf-8');
|
|
42
|
-
await this.runPiper(textFile, audioFile,
|
|
50
|
+
await this.runPiper(textFile, audioFile, modelFile);
|
|
43
51
|
const audioBuffer = readFileSync(audioFile);
|
|
44
52
|
return audioBuffer;
|
|
45
53
|
}
|
|
@@ -61,7 +69,17 @@ export class PiperEngine extends TTSEngine {
|
|
|
61
69
|
}
|
|
62
70
|
}
|
|
63
71
|
async getVoices() {
|
|
64
|
-
|
|
72
|
+
const modelDir = join(homedir(), '.local/share/piper-tts');
|
|
73
|
+
return Object.values(VOICE_PROFILES)
|
|
74
|
+
.filter(v => {
|
|
75
|
+
const modelFile = join(modelDir, `${v.piperModel}.onnx`);
|
|
76
|
+
return existsSync(modelFile);
|
|
77
|
+
})
|
|
78
|
+
.map(v => ({
|
|
79
|
+
id: v.id,
|
|
80
|
+
name: `${v.name} (${v.style})`,
|
|
81
|
+
model: v.piperModel,
|
|
82
|
+
}));
|
|
65
83
|
}
|
|
66
84
|
async isAvailable() {
|
|
67
85
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"piper.js","sourceRoot":"","sources":["../../../src/engines/piper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"piper.js","sourceRoot":"","sources":["../../../src/engines/piper.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/scripts/setup.js
CHANGED
|
@@ -7,8 +7,16 @@ import { join } from 'path';
|
|
|
7
7
|
|
|
8
8
|
const HOME = homedir();
|
|
9
9
|
const PIPER_MODEL_DIR = join(HOME, '.local/share/piper-tts');
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
// Voice models to download (maps to voice profiles)
|
|
12
|
+
const MODELS = [
|
|
13
|
+
{ name: 'en_US-hfc_female-medium', voice: 'Mia', size: '54MB' },
|
|
14
|
+
{ name: 'en_GB-alba-medium', voice: 'Miette', size: '53MB' },
|
|
15
|
+
{ name: 'en_US-libritts-high', voice: 'Seraphine/Echo', size: '89MB' },
|
|
16
|
+
{ name: 'en_US-ryan-medium', voice: 'Jeremy/Atlas', size: '61MB' },
|
|
17
|
+
{ name: 'en_US-kristin-medium', voice: 'ResoNova', size: '60MB' },
|
|
18
|
+
{ name: 'en_US-kusal-medium', voice: 'Zephyr', size: '57MB' },
|
|
19
|
+
];
|
|
12
20
|
|
|
13
21
|
console.log('\n🎙️ mia-narrative Setup\n');
|
|
14
22
|
|
|
@@ -35,51 +43,69 @@ try {
|
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
// Check/Setup Piper models
|
|
38
|
-
console.log(`3️⃣
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
console.log(`3️⃣ Setting up Piper voice models...`);
|
|
47
|
+
mkdirSync(PIPER_MODEL_DIR, { recursive: true });
|
|
48
|
+
|
|
49
|
+
const totalSize = MODELS.reduce((sum, m) => {
|
|
50
|
+
const match = m.size.match(/(\d+)/);
|
|
51
|
+
return sum + (match ? parseInt(match[1]) : 0);
|
|
52
|
+
}, 0);
|
|
53
|
+
|
|
54
|
+
console.log(` 📥 Total download size: ~${totalSize}MB (may take 5-10 minutes)`);
|
|
55
|
+
console.log('');
|
|
56
|
+
|
|
57
|
+
let downloadedCount = 0;
|
|
58
|
+
for (const model of MODELS) {
|
|
59
|
+
const modelPath = join(PIPER_MODEL_DIR, `${model.name}.onnx`);
|
|
60
|
+
const configPath = `${modelPath}.json`;
|
|
61
|
+
|
|
62
|
+
if (existsSync(modelPath) && existsSync(configPath)) {
|
|
63
|
+
console.log(` ✓ ${model.name}`);
|
|
64
|
+
downloadedCount++;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
46
67
|
|
|
47
68
|
try {
|
|
48
|
-
|
|
69
|
+
console.log(` ⏳ ${model.name} (${model.size})...`);
|
|
70
|
+
|
|
71
|
+
// Determine model path in HuggingFace repo
|
|
72
|
+
// Model names like: en_US-hfc_female-medium, en_GB-alba-medium
|
|
73
|
+
let repoPath;
|
|
74
|
+
const parts = model.name.split('_');
|
|
75
|
+
const lang = parts[0]; // "en"
|
|
76
|
+
const country = parts[1].split('-')[0]; // "US" or "GB"
|
|
77
|
+
const voiceAndQuality = model.name.replace(`${lang}_${country}-`, '');
|
|
78
|
+
const qualityIndex = voiceAndQuality.lastIndexOf('-');
|
|
79
|
+
const voice = voiceAndQuality.substring(0, qualityIndex);
|
|
80
|
+
const quality = voiceAndQuality.substring(qualityIndex + 1);
|
|
81
|
+
|
|
82
|
+
repoPath = `${lang}/${lang}_${country}/${voice}/${quality}`;
|
|
83
|
+
|
|
84
|
+
const modelUrl = `https://huggingface.co/rhasspy/piper-voices/resolve/main/${repoPath}/${model.name}.onnx`;
|
|
49
85
|
const configUrl = `${modelUrl}.json`;
|
|
50
86
|
|
|
51
|
-
execSync(`curl -L "${modelUrl}" -o "${
|
|
52
|
-
execSync(`curl -L "${configUrl}" -o "${
|
|
87
|
+
execSync(`curl -L "${modelUrl}" -o "${modelPath}"`, { stdio: 'pipe' });
|
|
88
|
+
execSync(`curl -L "${configUrl}" -o "${configPath}"`, { stdio: 'pipe' });
|
|
53
89
|
|
|
54
|
-
console.log(
|
|
90
|
+
console.log(` ✓ ${model.name}`);
|
|
91
|
+
downloadedCount++;
|
|
55
92
|
} catch (error) {
|
|
56
|
-
console.log(
|
|
57
|
-
console.log(' → You can manually download from:');
|
|
58
|
-
console.log(` https://huggingface.co/rhasspy/piper-voices`);
|
|
59
|
-
process.exit(1);
|
|
93
|
+
console.log(` ✗ Failed to download ${model.name}`);
|
|
60
94
|
}
|
|
61
95
|
}
|
|
62
96
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (process.env.SHELL?.includes('zsh')) {
|
|
68
|
-
const rcFile = join(HOME, '.zshrc');
|
|
69
|
-
console.log(` Add this to ${rcFile}:`);
|
|
70
|
-
console.log(` export ${envVar}`);
|
|
71
|
-
} else if (process.env.SHELL?.includes('bash')) {
|
|
72
|
-
const rcFile = join(HOME, '.bashrc');
|
|
73
|
-
console.log(` Add this to ${rcFile}:`);
|
|
74
|
-
console.log(` export ${envVar}`);
|
|
75
|
-
} else {
|
|
76
|
-
console.log(` Set this in your shell profile:`);
|
|
77
|
-
console.log(` export ${envVar}`);
|
|
97
|
+
console.log('');
|
|
98
|
+
if (downloadedCount === 0) {
|
|
99
|
+
console.log(' ⚠️ No models downloaded. Check your internet connection.');
|
|
100
|
+
process.exit(1);
|
|
78
101
|
}
|
|
79
102
|
|
|
103
|
+
console.log(` ✓ Downloaded ${downloadedCount}/${MODELS.length} models`);
|
|
104
|
+
|
|
80
105
|
console.log('\n✅ Setup complete!');
|
|
106
|
+
console.log('\nModels installed to:', PIPER_MODEL_DIR);
|
|
81
107
|
console.log('\nNext steps:');
|
|
82
|
-
console.log('1.
|
|
83
|
-
console.log('2.
|
|
84
|
-
console.log('3.
|
|
108
|
+
console.log('1. Test: mia-narrative generate --engine piper --text "hello"');
|
|
109
|
+
console.log('2. List voices: mia-narrative voices --engine piper');
|
|
110
|
+
console.log('3. Try a specific voice: mia-narrative generate --engine piper --voice miette-default --text "hello"');
|
|
85
111
|
console.log('\n');
|
package/src/commands/voices.ts
CHANGED
|
@@ -40,20 +40,22 @@ export async function voicesCommand(options: VoicesListOptions): Promise<void> {
|
|
|
40
40
|
// Table format
|
|
41
41
|
Logger.log('');
|
|
42
42
|
Logger.log(`Available Voices for ${engineType}:`);
|
|
43
|
-
Logger.log('─'.repeat(
|
|
43
|
+
Logger.log('─'.repeat(100));
|
|
44
44
|
|
|
45
|
-
const idHeader = 'ID'.padEnd(
|
|
46
|
-
const nameHeader = 'Name';
|
|
47
|
-
|
|
48
|
-
Logger.log(
|
|
45
|
+
const idHeader = 'ID'.padEnd(25);
|
|
46
|
+
const nameHeader = 'Name'.padEnd(25);
|
|
47
|
+
const modelHeader = 'Model';
|
|
48
|
+
Logger.log(` ${idHeader}${nameHeader}${modelHeader}`);
|
|
49
|
+
Logger.log('─'.repeat(100));
|
|
49
50
|
|
|
50
51
|
voices.forEach((voice) => {
|
|
51
|
-
const idStr = (voice.id || 'unknown').padEnd(
|
|
52
|
-
const nameStr = voice.name || 'Unknown';
|
|
53
|
-
|
|
52
|
+
const idStr = (voice.id || 'unknown').padEnd(25);
|
|
53
|
+
const nameStr = (voice.name || 'Unknown').padEnd(25);
|
|
54
|
+
const modelStr = voice.model || 'system';
|
|
55
|
+
Logger.log(` ${idStr}${nameStr}${modelStr}`);
|
|
54
56
|
});
|
|
55
57
|
|
|
56
|
-
Logger.log('─'.repeat(
|
|
58
|
+
Logger.log('─'.repeat(100));
|
|
57
59
|
Logger.log('');
|
|
58
60
|
}
|
|
59
61
|
} catch (error) {
|
package/src/config/voices.ts
CHANGED
|
@@ -8,64 +8,64 @@ export interface VoiceProfile {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export const VOICE_PROFILES: Record<string, VoiceProfile> = {
|
|
11
|
-
"mia
|
|
12
|
-
id: "mia
|
|
11
|
+
"mia": {
|
|
12
|
+
id: "mia",
|
|
13
13
|
name: "Mia",
|
|
14
14
|
gender: "female",
|
|
15
15
|
style: "professional",
|
|
16
16
|
description: "Professional narrator for expert technical content",
|
|
17
|
-
piperModel:
|
|
17
|
+
piperModel: "en_US-hfc_female-medium",
|
|
18
18
|
},
|
|
19
|
-
"miette
|
|
20
|
-
id: "miette
|
|
19
|
+
"miette": {
|
|
20
|
+
id: "miette",
|
|
21
21
|
name: "Miette",
|
|
22
22
|
gender: "female",
|
|
23
23
|
style: "conversational",
|
|
24
24
|
description: "Friendly conversational narrator",
|
|
25
|
-
piperModel: "
|
|
25
|
+
piperModel: "en_GB-alba-medium",
|
|
26
26
|
},
|
|
27
|
-
"seraphine
|
|
28
|
-
id: "seraphine
|
|
27
|
+
"seraphine": {
|
|
28
|
+
id: "seraphine",
|
|
29
29
|
name: "Seraphine",
|
|
30
30
|
gender: "female",
|
|
31
31
|
style: "narrative",
|
|
32
32
|
description: "Expressive narrative and storytelling",
|
|
33
33
|
piperModel: "en_US-libritts-high",
|
|
34
34
|
},
|
|
35
|
-
"jeremy
|
|
36
|
-
id: "jeremy
|
|
35
|
+
"jeremy": {
|
|
36
|
+
id: "jeremy",
|
|
37
37
|
name: "Jeremy",
|
|
38
38
|
gender: "male",
|
|
39
39
|
style: "professional",
|
|
40
40
|
description: "Professional male narrator",
|
|
41
41
|
piperModel: "en_US-ryan-medium",
|
|
42
42
|
},
|
|
43
|
-
"resonova
|
|
44
|
-
id: "resonova
|
|
43
|
+
"resonova": {
|
|
44
|
+
id: "resonova",
|
|
45
45
|
name: "ResoNova",
|
|
46
|
-
gender: "
|
|
46
|
+
gender: "female",
|
|
47
47
|
style: "expressive",
|
|
48
48
|
description: "Varied and experimental voice",
|
|
49
|
-
piperModel: "en_US-
|
|
49
|
+
piperModel: "en_US-kristin-medium",
|
|
50
50
|
},
|
|
51
|
-
"zephyr
|
|
52
|
-
id: "zephyr
|
|
51
|
+
"zephyr": {
|
|
52
|
+
id: "zephyr",
|
|
53
53
|
name: "Zephyr",
|
|
54
54
|
gender: "neutral",
|
|
55
55
|
style: "narrative",
|
|
56
56
|
description: "Contemplative nature and narrative voice",
|
|
57
57
|
piperModel: "en_US-kusal-medium",
|
|
58
58
|
},
|
|
59
|
-
"echo
|
|
60
|
-
id: "echo
|
|
59
|
+
"echo": {
|
|
60
|
+
id: "echo",
|
|
61
61
|
name: "Echo",
|
|
62
62
|
gender: "female",
|
|
63
63
|
style: "expressive",
|
|
64
64
|
description: "Expressive character and dialogue voice",
|
|
65
65
|
piperModel: "en_US-libritts-high",
|
|
66
66
|
},
|
|
67
|
-
"atlas
|
|
68
|
-
id: "atlas
|
|
67
|
+
"atlas": {
|
|
68
|
+
id: "atlas",
|
|
69
69
|
name: "Atlas",
|
|
70
70
|
gender: "male",
|
|
71
71
|
style: "conversational",
|
package/src/engines/base.ts
CHANGED
package/src/engines/piper.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn, execSync } from 'child_process';
|
|
2
|
-
import { writeFileSync, unlinkSync, readFileSync } from 'fs';
|
|
3
|
-
import { tmpdir } from 'os';
|
|
2
|
+
import { writeFileSync, unlinkSync, readFileSync, existsSync } from 'fs';
|
|
3
|
+
import { tmpdir, homedir } from 'os';
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { randomUUID } from 'crypto';
|
|
6
6
|
import { Logger } from '../utils/logger.js';
|
|
@@ -37,6 +37,18 @@ export class PiperEngine extends TTSEngine {
|
|
|
37
37
|
throw new Error('Text cannot be empty');
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
// Build path to model file
|
|
41
|
+
const modelDir = join(homedir(), '.local/share/piper-tts');
|
|
42
|
+
const modelFile = join(modelDir, `${voiceProfile.piperModel}.onnx`);
|
|
43
|
+
|
|
44
|
+
if (!existsSync(modelFile)) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Piper model not found: ${voiceProfile.piperModel}\n` +
|
|
47
|
+
`Expected location: ${modelFile}\n` +
|
|
48
|
+
`Run 'npm run setup' to download models.`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
40
52
|
const tempDir = tmpdir();
|
|
41
53
|
const uid = randomUUID();
|
|
42
54
|
const textFile = join(tempDir, `piper-input-${uid}.txt`);
|
|
@@ -44,7 +56,7 @@ export class PiperEngine extends TTSEngine {
|
|
|
44
56
|
|
|
45
57
|
try {
|
|
46
58
|
writeFileSync(textFile, text, 'utf-8');
|
|
47
|
-
await this.runPiper(textFile, audioFile,
|
|
59
|
+
await this.runPiper(textFile, audioFile, modelFile);
|
|
48
60
|
const audioBuffer = readFileSync(audioFile);
|
|
49
61
|
return audioBuffer;
|
|
50
62
|
} finally {
|
|
@@ -64,7 +76,18 @@ export class PiperEngine extends TTSEngine {
|
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
async getVoices(): Promise<Voice[]> {
|
|
67
|
-
|
|
79
|
+
const modelDir = join(homedir(), '.local/share/piper-tts');
|
|
80
|
+
|
|
81
|
+
return Object.values(VOICE_PROFILES)
|
|
82
|
+
.filter(v => {
|
|
83
|
+
const modelFile = join(modelDir, `${v.piperModel}.onnx`);
|
|
84
|
+
return existsSync(modelFile);
|
|
85
|
+
})
|
|
86
|
+
.map(v => ({
|
|
87
|
+
id: v.id,
|
|
88
|
+
name: `${v.name} (${v.style})`,
|
|
89
|
+
model: v.piperModel,
|
|
90
|
+
}));
|
|
68
91
|
}
|
|
69
92
|
|
|
70
93
|
async isAvailable(): Promise<boolean> {
|