mia-narrative 1.0.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.
Files changed (69) hide show
  1. package/README.md +149 -0
  2. package/bin/mia-narrative.ts +86 -0
  3. package/dist/bin/mia-narrative.d.ts +3 -0
  4. package/dist/bin/mia-narrative.d.ts.map +1 -0
  5. package/dist/bin/mia-narrative.js +34 -0
  6. package/dist/bin/mia-narrative.js.map +1 -0
  7. package/dist/src/audio/processor.d.ts +6 -0
  8. package/dist/src/audio/processor.d.ts.map +1 -0
  9. package/dist/src/audio/processor.js +72 -0
  10. package/dist/src/audio/processor.js.map +1 -0
  11. package/dist/src/commands/generate.d.ts +19 -0
  12. package/dist/src/commands/generate.d.ts.map +1 -0
  13. package/dist/src/commands/generate.js +104 -0
  14. package/dist/src/commands/generate.js.map +1 -0
  15. package/dist/src/commands/voices.d.ts +8 -0
  16. package/dist/src/commands/voices.d.ts.map +1 -0
  17. package/dist/src/commands/voices.js +60 -0
  18. package/dist/src/commands/voices.js.map +1 -0
  19. package/dist/src/config/defaults.d.ts +54 -0
  20. package/dist/src/config/defaults.d.ts.map +1 -0
  21. package/dist/src/config/defaults.js +30 -0
  22. package/dist/src/config/defaults.js.map +1 -0
  23. package/dist/src/config/voices.d.ts +15 -0
  24. package/dist/src/config/voices.d.ts.map +1 -0
  25. package/dist/src/config/voices.js +79 -0
  26. package/dist/src/config/voices.js.map +1 -0
  27. package/dist/src/engines/ElevenLabsEngine.d.ts +10 -0
  28. package/dist/src/engines/ElevenLabsEngine.d.ts.map +1 -0
  29. package/dist/src/engines/ElevenLabsEngine.js +78 -0
  30. package/dist/src/engines/ElevenLabsEngine.js.map +1 -0
  31. package/dist/src/engines/SystemTtsEngine.d.ts +9 -0
  32. package/dist/src/engines/SystemTtsEngine.d.ts.map +1 -0
  33. package/dist/src/engines/SystemTtsEngine.js +56 -0
  34. package/dist/src/engines/SystemTtsEngine.js.map +1 -0
  35. package/dist/src/engines/base.d.ts +23 -0
  36. package/dist/src/engines/base.d.ts.map +1 -0
  37. package/dist/src/engines/base.js +3 -0
  38. package/dist/src/engines/base.js.map +1 -0
  39. package/dist/src/engines/factory.d.ts +6 -0
  40. package/dist/src/engines/factory.d.ts.map +1 -0
  41. package/dist/src/engines/factory.js +20 -0
  42. package/dist/src/engines/factory.js.map +1 -0
  43. package/dist/src/engines/piper.d.ts +12 -0
  44. package/dist/src/engines/piper.d.ts.map +1 -0
  45. package/dist/src/engines/piper.js +118 -0
  46. package/dist/src/engines/piper.js.map +1 -0
  47. package/dist/src/utils/file-reader.d.ts +5 -0
  48. package/dist/src/utils/file-reader.d.ts.map +1 -0
  49. package/dist/src/utils/file-reader.js +26 -0
  50. package/dist/src/utils/file-reader.js.map +1 -0
  51. package/dist/src/utils/logger.d.ts +10 -0
  52. package/dist/src/utils/logger.d.ts.map +1 -0
  53. package/dist/src/utils/logger.js +27 -0
  54. package/dist/src/utils/logger.js.map +1 -0
  55. package/package.json +35 -0
  56. package/src/audio/processor.ts +94 -0
  57. package/src/commands/generate.ts +144 -0
  58. package/src/commands/voices.ts +68 -0
  59. package/src/config/defaults.ts +41 -0
  60. package/src/config/voices.ts +89 -0
  61. package/src/engines/ElevenLabsEngine.ts +81 -0
  62. package/src/engines/SystemTtsEngine.ts +61 -0
  63. package/src/engines/base.ts +26 -0
  64. package/src/engines/factory.ts +28 -0
  65. package/src/engines/piper.ts +134 -0
  66. package/src/types/say.d.ts +26 -0
  67. package/src/utils/file-reader.ts +25 -0
  68. package/src/utils/logger.ts +33 -0
  69. package/tsconfig.json +21 -0
@@ -0,0 +1,30 @@
1
+ export const DEFAULT_AUDIO_PARAMS = {
2
+ speed: 1.0,
3
+ pitch: 1.0,
4
+ volume: 0.8,
5
+ emphasis: 0.5,
6
+ reverb: 0.2,
7
+ echo: 0.1,
8
+ compression: 0.3,
9
+ pauseLength: 0.5,
10
+ };
11
+ export const AUDIO_PARAM_RANGES = {
12
+ speed: { min: 0.5, max: 2.0 },
13
+ pitch: { min: 0.5, max: 2.0 },
14
+ volume: { min: 0.0, max: 1.0 },
15
+ emphasis: { min: 0.0, max: 1.0 },
16
+ reverb: { min: 0.0, max: 1.0 },
17
+ echo: { min: 0.1, max: 2.0 },
18
+ compression: { min: 0.0, max: 1.0 },
19
+ pauseLength: { min: 0.1, max: 2.0 },
20
+ };
21
+ export var ExitCode;
22
+ (function (ExitCode) {
23
+ ExitCode[ExitCode["SUCCESS"] = 0] = "SUCCESS";
24
+ ExitCode[ExitCode["GENERAL_ERROR"] = 1] = "GENERAL_ERROR";
25
+ ExitCode[ExitCode["INVALID_PARAMS"] = 2] = "INVALID_PARAMS";
26
+ ExitCode[ExitCode["CONFIG_ERROR"] = 3] = "CONFIG_ERROR";
27
+ ExitCode[ExitCode["TTS_ENGINE_ERROR"] = 4] = "TTS_ENGINE_ERROR";
28
+ ExitCode[ExitCode["OUTPUT_ERROR"] = 5] = "OUTPUT_ERROR";
29
+ })(ExitCode || (ExitCode = {}));
30
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../../src/config/defaults.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,oBAAoB,GAAoB;IACnD,KAAK,EAAE,GAAG;IACV,KAAK,EAAE,GAAG;IACV,MAAM,EAAE,GAAG;IACX,QAAQ,EAAE,GAAG;IACb,MAAM,EAAE,GAAG;IACX,IAAI,EAAE,GAAG;IACT,WAAW,EAAE,GAAG;IAChB,WAAW,EAAE,GAAG;CACjB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IAC7B,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IAC7B,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IAC9B,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IAChC,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IAC9B,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IAC5B,WAAW,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;IACnC,WAAW,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;CACpC,CAAC;AAEF,MAAM,CAAN,IAAY,QAOX;AAPD,WAAY,QAAQ;IAClB,6CAAW,CAAA;IACX,yDAAiB,CAAA;IACjB,2DAAkB,CAAA;IAClB,uDAAgB,CAAA;IAChB,+DAAoB,CAAA;IACpB,uDAAgB,CAAA;AAClB,CAAC,EAPW,QAAQ,KAAR,QAAQ,QAOnB"}
@@ -0,0 +1,15 @@
1
+ export interface VoiceProfile {
2
+ id: string;
3
+ name: string;
4
+ gender: "male" | "female" | "neutral";
5
+ style: string;
6
+ description: string;
7
+ piperModel: string;
8
+ }
9
+ export declare const VOICE_PROFILES: Record<string, VoiceProfile>;
10
+ export declare function getVoiceProfile(id: string): VoiceProfile | undefined;
11
+ export declare function listVoices(filter?: {
12
+ gender?: string;
13
+ style?: string;
14
+ }): VoiceProfile[];
15
+ //# sourceMappingURL=voices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voices.d.ts","sourceRoot":"","sources":["../../../src/config/voices.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAiEvD,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEpE;AAED,wBAAgB,UAAU,CACxB,MAAM,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,YAAY,EAAE,CAMhB"}
@@ -0,0 +1,79 @@
1
+ export const VOICE_PROFILES = {
2
+ "mia-default": {
3
+ id: "mia-default",
4
+ name: "Mia",
5
+ gender: "female",
6
+ style: "professional",
7
+ description: "Professional narrator for expert technical content",
8
+ piperModel: `${process.env.HOME}/.local/share/piper-tts/en_US-lessac-medium.onnx`,
9
+ },
10
+ "miette-default": {
11
+ id: "miette-default",
12
+ name: "Miette",
13
+ gender: "female",
14
+ style: "conversational",
15
+ description: "Friendly conversational narrator",
16
+ piperModel: "en_US-amy-medium",
17
+ },
18
+ "seraphine-default": {
19
+ id: "seraphine-default",
20
+ name: "Seraphine",
21
+ gender: "female",
22
+ style: "narrative",
23
+ description: "Expressive narrative and storytelling",
24
+ piperModel: "en_US-libritts-high",
25
+ },
26
+ "jeremy-default": {
27
+ id: "jeremy-default",
28
+ name: "Jeremy",
29
+ gender: "male",
30
+ style: "professional",
31
+ description: "Professional male narrator",
32
+ piperModel: "en_US-ryan-medium",
33
+ },
34
+ "resonova-default": {
35
+ id: "resonova-default",
36
+ name: "ResoNova",
37
+ gender: "neutral",
38
+ style: "expressive",
39
+ description: "Varied and experimental voice",
40
+ piperModel: "en_US-hfc-female",
41
+ },
42
+ "zephyr-default": {
43
+ id: "zephyr-default",
44
+ name: "Zephyr",
45
+ gender: "neutral",
46
+ style: "narrative",
47
+ description: "Contemplative nature and narrative voice",
48
+ piperModel: "en_US-kusal-medium",
49
+ },
50
+ "echo-default": {
51
+ id: "echo-default",
52
+ name: "Echo",
53
+ gender: "female",
54
+ style: "expressive",
55
+ description: "Expressive character and dialogue voice",
56
+ piperModel: "en_US-libritts-high",
57
+ },
58
+ "atlas-default": {
59
+ id: "atlas-default",
60
+ name: "Atlas",
61
+ gender: "male",
62
+ style: "conversational",
63
+ description: "Casual and approachable male voice",
64
+ piperModel: "en_US-ryan-medium",
65
+ },
66
+ };
67
+ export function getVoiceProfile(id) {
68
+ return VOICE_PROFILES[id];
69
+ }
70
+ export function listVoices(filter) {
71
+ return Object.values(VOICE_PROFILES).filter((voice) => {
72
+ if (filter?.gender && voice.gender !== filter.gender)
73
+ return false;
74
+ if (filter?.style && voice.style !== filter.style)
75
+ return false;
76
+ return true;
77
+ });
78
+ }
79
+ //# sourceMappingURL=voices.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voices.js","sourceRoot":"","sources":["../../../src/config/voices.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,cAAc,GAAiC;IAC1D,aAAa,EAAE;QACb,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,oDAAoD;QACjE,UAAU,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,kDAAkD;KAClF;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,gBAAgB;QACvB,WAAW,EAAE,kCAAkC;QAC/C,UAAU,EAAE,kBAAkB;KAC/B;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,mBAAmB;QACvB,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,WAAW;QAClB,WAAW,EAAE,uCAAuC;QACpD,UAAU,EAAE,qBAAqB;KAClC;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,4BAA4B;QACzC,UAAU,EAAE,mBAAmB;KAChC;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,kBAAkB;QACtB,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,+BAA+B;QAC5C,UAAU,EAAE,kBAAkB;KAC/B;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,WAAW;QAClB,WAAW,EAAE,0CAA0C;QACvD,UAAU,EAAE,oBAAoB;KACjC;IACD,cAAc,EAAE;QACd,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,yCAAyC;QACtD,UAAU,EAAE,qBAAqB;KAClC;IACD,eAAe,EAAE;QACf,EAAE,EAAE,eAAe;QACnB,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"}
@@ -0,0 +1,10 @@
1
+ import { TTSEngine, GenerateAudioOptions, Voice, TTSEngineConfig } from './base.js';
2
+ export declare class ElevenLabsEngine extends TTSEngine {
3
+ private client;
4
+ initialize(config: TTSEngineConfig): Promise<void>;
5
+ generateAudio(options: GenerateAudioOptions): Promise<Buffer>;
6
+ getVoices(): Promise<Voice[]>;
7
+ isAvailable(): Promise<boolean>;
8
+ getName(): string;
9
+ }
10
+ //# sourceMappingURL=ElevenLabsEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsEngine.d.ts","sourceRoot":"","sources":["../../../src/engines/ElevenLabsEngine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAIpF,qBAAa,gBAAiB,SAAQ,SAAS;IAC7C,OAAO,CAAC,MAAM,CAA+B;IAEvC,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlD,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IA2C7D,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAc7B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC,OAAO,IAAI,MAAM;CAGlB"}
@@ -0,0 +1,78 @@
1
+ import { ElevenLabsClient } from '@elevenlabs/elevenlabs-js';
2
+ import { TTSEngine } from './base.js';
3
+ import { Readable } from 'stream';
4
+ export class ElevenLabsEngine extends TTSEngine {
5
+ async initialize(config) {
6
+ const apiKey = config.apiKey || process.env.ELEVENLABS_API_KEY;
7
+ if (!apiKey) {
8
+ throw new Error('ElevenLabs API key not provided. Please set the ELEVENLABS_API_KEY environment variable or provide it in the config.');
9
+ }
10
+ this.client = new ElevenLabsClient({ apiKey });
11
+ }
12
+ async generateAudio(options) {
13
+ if (!this.client) {
14
+ throw new Error('ElevenLabs engine not initialized.');
15
+ }
16
+ const { text, voiceId } = options;
17
+ const audioStream = await this.client.textToSpeech.convert(voiceId, {
18
+ text,
19
+ modelId: 'eleven_multilingual_v2',
20
+ });
21
+ // Handle multiple response types from ElevenLabs API
22
+ try {
23
+ if (audioStream instanceof Readable) {
24
+ const chunks = [];
25
+ for await (const chunk of audioStream) {
26
+ chunks.push(Buffer.from(chunk));
27
+ }
28
+ return Buffer.concat(chunks);
29
+ }
30
+ else if (Buffer.isBuffer(audioStream)) {
31
+ return audioStream;
32
+ }
33
+ else if (audioStream && typeof audioStream === 'object' && Symbol.asyncIterator in audioStream) {
34
+ // Handle async iterable streams
35
+ const chunks = [];
36
+ for await (const chunk of audioStream) {
37
+ if (Buffer.isBuffer(chunk)) {
38
+ chunks.push(chunk);
39
+ }
40
+ else if (chunk instanceof Uint8Array) {
41
+ chunks.push(Buffer.from(chunk));
42
+ }
43
+ else {
44
+ chunks.push(Buffer.from(chunk));
45
+ }
46
+ }
47
+ return Buffer.concat(chunks);
48
+ }
49
+ else {
50
+ // Fallback: try to convert to Buffer
51
+ return Buffer.from(audioStream);
52
+ }
53
+ }
54
+ catch (error) {
55
+ throw new Error(`Failed to process ElevenLabs audio response: ${error instanceof Error ? error.message : String(error)}`);
56
+ }
57
+ }
58
+ async getVoices() {
59
+ if (!this.client) {
60
+ throw new Error('ElevenLabs engine not initialized.');
61
+ }
62
+ const availableVoices = await this.client.voices.getAll();
63
+ return availableVoices.voices.map((v) => {
64
+ const voiceId = v.voice_id || v.voiceId || v.id;
65
+ return {
66
+ id: voiceId,
67
+ name: `${v.name}`,
68
+ };
69
+ });
70
+ }
71
+ async isAvailable() {
72
+ return !!(process.env.ELEVENLABS_API_KEY);
73
+ }
74
+ getName() {
75
+ return 'elevenlabs';
76
+ }
77
+ }
78
+ //# sourceMappingURL=ElevenLabsEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevenLabsEngine.js","sourceRoot":"","sources":["../../../src/engines/ElevenLabsEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { TTSEngine, GenerateAudioOptions, Voice, TTSEngineConfig } from './base.js';
2
+ export declare class SystemTtsEngine extends TTSEngine {
3
+ initialize(config: TTSEngineConfig): Promise<void>;
4
+ generateAudio(options: GenerateAudioOptions): Promise<Buffer>;
5
+ getVoices(): Promise<Voice[]>;
6
+ isAvailable(): Promise<boolean>;
7
+ getName(): string;
8
+ }
9
+ //# sourceMappingURL=SystemTtsEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SystemTtsEngine.d.ts","sourceRoot":"","sources":["../../../src/engines/SystemTtsEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AASpF,qBAAa,eAAgB,SAAQ,SAAS;IACtC,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IA0B7D,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAW7B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAMrC,OAAO,IAAI,MAAM;CAGlB"}
@@ -0,0 +1,56 @@
1
+ import { TTSEngine } from './base.js';
2
+ import say from 'say';
3
+ import { tmpdir } from 'os';
4
+ import { join } from 'path';
5
+ import { randomUUID } from 'crypto';
6
+ import { unlinkSync, readFileSync } from 'fs';
7
+ import { Logger } from '../utils/logger.js';
8
+ export class SystemTtsEngine extends TTSEngine {
9
+ async initialize(config) {
10
+ // No initialization needed for system TTS
11
+ }
12
+ async generateAudio(options) {
13
+ const { text, voiceId, parameters } = options;
14
+ const tempDir = tmpdir();
15
+ const uid = randomUUID();
16
+ const audioFile = join(tempDir, `mia-narrative-output-${uid}.wav`);
17
+ return new Promise((resolve, reject) => {
18
+ say.export(text, voiceId, parameters.speed, audioFile, (err) => {
19
+ if (err) {
20
+ Logger.error(`System TTS error: ${err}`);
21
+ return reject(new Error(err));
22
+ }
23
+ try {
24
+ const audioBuffer = readFileSync(audioFile);
25
+ unlinkSync(audioFile); // Clean up the temp file
26
+ resolve(audioBuffer);
27
+ }
28
+ catch (readErr) {
29
+ if (readErr instanceof Error) {
30
+ Logger.error(`Error processing system TTS audio file: ${readErr.message}`);
31
+ }
32
+ reject(readErr);
33
+ }
34
+ });
35
+ });
36
+ }
37
+ async getVoices() {
38
+ return new Promise((resolve, reject) => {
39
+ say.getInstalledVoices(((err, voices) => {
40
+ if (err) {
41
+ return reject(new Error(err || 'Failed to get voices'));
42
+ }
43
+ resolve((voices || []).map((v) => ({ id: v, name: v })));
44
+ }));
45
+ });
46
+ }
47
+ async isAvailable() {
48
+ // The 'say' package should work on most systems with built-in TTS.
49
+ // A more robust check could be added here if needed.
50
+ return true;
51
+ }
52
+ getName() {
53
+ return 'system';
54
+ }
55
+ }
56
+ //# sourceMappingURL=SystemTtsEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SystemTtsEngine.js","sourceRoot":"","sources":["../../../src/engines/SystemTtsEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgD,MAAM,WAAW,CAAC;AAEpF,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC5C,KAAK,CAAC,UAAU,CAAC,MAAuB;QACtC,0CAA0C;IAC5C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAA6B;QAC/C,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;QAC9C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAAC,CAAC;QAEnE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC7D,IAAI,GAAG,EAAE,CAAC;oBACR,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;oBACzC,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChC,CAAC;gBACD,IAAI,CAAC;oBACH,MAAM,WAAW,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;oBAC5C,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,yBAAyB;oBAChD,OAAO,CAAC,WAAW,CAAC,CAAC;gBACvB,CAAC;gBAAC,OAAO,OAAgB,EAAE,CAAC;oBAC1B,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;wBAC7B,MAAM,CAAC,KAAK,CAAC,2CAA2C,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;oBAC7E,CAAC;oBACD,MAAM,CAAC,OAAO,CAAC,CAAC;gBAClB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAkB,EAAE,MAAgB,EAAE,EAAE;gBAC/D,IAAI,GAAG,EAAE,CAAC;oBACR,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,sBAAsB,CAAC,CAAC,CAAC;gBAC1D,CAAC;gBACD,OAAO,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACnE,CAAC,CAAQ,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW;QACf,mEAAmE;QACnE,qDAAqD;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,23 @@
1
+ import { AudioParameters } from '../config/defaults.js';
2
+ export interface TTSEngineConfig {
3
+ apiKey?: string;
4
+ piperPath?: string;
5
+ modelPath?: string;
6
+ }
7
+ export interface Voice {
8
+ id: string;
9
+ name: string;
10
+ }
11
+ export interface GenerateAudioOptions {
12
+ text: string;
13
+ voiceId: string;
14
+ parameters: AudioParameters;
15
+ }
16
+ export declare abstract class TTSEngine {
17
+ abstract initialize(config: TTSEngineConfig): Promise<void>;
18
+ abstract generateAudio(options: GenerateAudioOptions): Promise<Buffer>;
19
+ abstract getVoices(): Promise<Voice[]>;
20
+ abstract isAvailable(): Promise<boolean>;
21
+ abstract getName(): string;
22
+ }
23
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +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;CACd;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"}
@@ -0,0 +1,3 @@
1
+ export class TTSEngine {
2
+ }
3
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/engines/base.ts"],"names":[],"mappings":"AAmBA,MAAM,OAAgB,SAAS;CAM9B"}
@@ -0,0 +1,6 @@
1
+ import { TTSEngine, TTSEngineConfig } from './base.js';
2
+ export type EngineType = 'piper' | 'system' | 'elevenlabs';
3
+ export declare class EngineFactory {
4
+ static create(engineType: EngineType, config?: TTSEngineConfig): Promise<TTSEngine>;
5
+ }
6
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/engines/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAKvD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,CAAC;AAQ3D,qBAAa,aAAa;WACX,MAAM,CACjB,UAAU,EAAE,UAAU,EACtB,MAAM,GAAE,eAAoB,GAC3B,OAAO,CAAC,SAAS,CAAC;CAUtB"}
@@ -0,0 +1,20 @@
1
+ import { PiperEngine } from './piper.js';
2
+ import { SystemTtsEngine } from './SystemTtsEngine.js';
3
+ import { ElevenLabsEngine } from './ElevenLabsEngine.js';
4
+ const engineMap = {
5
+ piper: PiperEngine,
6
+ system: SystemTtsEngine,
7
+ elevenlabs: ElevenLabsEngine,
8
+ };
9
+ export class EngineFactory {
10
+ static async create(engineType, config = {}) {
11
+ const EngineClass = engineMap[engineType];
12
+ if (!EngineClass) {
13
+ throw new Error(`Unknown engine type: ${engineType}`);
14
+ }
15
+ const engine = new EngineClass();
16
+ await engine.initialize(config);
17
+ return engine;
18
+ }
19
+ }
20
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/engines/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAIzD,MAAM,SAAS,GAA4C;IACzD,KAAK,EAAE,WAAW;IAClB,MAAM,EAAE,eAAe;IACvB,UAAU,EAAE,gBAAgB;CAC7B,CAAC;AAEF,MAAM,OAAO,aAAa;IACxB,MAAM,CAAC,KAAK,CAAC,MAAM,CACjB,UAAsB,EACtB,SAA0B,EAAE;QAE5B,MAAM,WAAW,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import { TTSEngine, TTSEngineConfig, GenerateAudioOptions, Voice } from './base.js';
2
+ export declare class PiperEngine extends TTSEngine {
3
+ private piperPath;
4
+ private modelPath;
5
+ initialize(config: TTSEngineConfig): Promise<void>;
6
+ generateAudio(options: GenerateAudioOptions): Promise<Buffer>;
7
+ getVoices(): Promise<Voice[]>;
8
+ isAvailable(): Promise<boolean>;
9
+ getName(): string;
10
+ private runPiper;
11
+ }
12
+ //# sourceMappingURL=piper.d.ts.map
@@ -0,0 +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;IAsC7D,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAI7B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBrC,OAAO,IAAI,MAAM;IAIjB,OAAO,CAAC,QAAQ;CA4CjB"}
@@ -0,0 +1,118 @@
1
+ import { spawn, execSync } from 'child_process';
2
+ import { writeFileSync, unlinkSync, readFileSync } from 'fs';
3
+ import { tmpdir } from 'os';
4
+ import { join } from 'path';
5
+ import { randomUUID } from 'crypto';
6
+ import { Logger } from '../utils/logger.js';
7
+ import { TTSEngine } from './base.js';
8
+ import { getVoiceProfile, VOICE_PROFILES } from '../config/voices.js';
9
+ export class PiperEngine extends TTSEngine {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.piperPath = 'piper';
13
+ this.modelPath = '';
14
+ }
15
+ async initialize(config) {
16
+ if (config.piperPath) {
17
+ this.piperPath = config.piperPath;
18
+ }
19
+ if (config.modelPath) {
20
+ this.modelPath = config.modelPath;
21
+ }
22
+ else {
23
+ this.modelPath = process.env.MIA_NARRATIVE_PIPER_MODEL || '';
24
+ }
25
+ Logger.debug(`Piper engine initialized with model path: ${this.modelPath}`);
26
+ }
27
+ async generateAudio(options) {
28
+ const { text, voiceId } = options;
29
+ const voiceProfile = getVoiceProfile(voiceId);
30
+ if (!voiceProfile) {
31
+ throw new Error(`Piper voice '${voiceId}' not found.`);
32
+ }
33
+ if (!text || text.trim().length === 0) {
34
+ throw new Error('Text cannot be empty');
35
+ }
36
+ const tempDir = tmpdir();
37
+ const uid = randomUUID();
38
+ const textFile = join(tempDir, `piper-input-${uid}.txt`);
39
+ const audioFile = join(tempDir, `piper-output-${uid}.wav`);
40
+ try {
41
+ writeFileSync(textFile, text, 'utf-8');
42
+ await this.runPiper(textFile, audioFile, voiceProfile.piperModel);
43
+ const audioBuffer = readFileSync(audioFile);
44
+ return audioBuffer;
45
+ }
46
+ finally {
47
+ try {
48
+ unlinkSync(textFile);
49
+ Logger.debug(`Cleaned up: ${textFile}`);
50
+ }
51
+ catch (err) {
52
+ // ignore
53
+ }
54
+ try {
55
+ unlinkSync(audioFile);
56
+ Logger.debug(`Cleaned up: ${audioFile}`);
57
+ }
58
+ catch (err) {
59
+ // ignore
60
+ }
61
+ }
62
+ }
63
+ async getVoices() {
64
+ return Object.values(VOICE_PROFILES).map(v => ({ id: v.id, name: `${v.name} (${v.style})` }));
65
+ }
66
+ async isAvailable() {
67
+ try {
68
+ if (this.piperPath === 'piper') {
69
+ execSync('which piper', { stdio: 'pipe' });
70
+ }
71
+ else {
72
+ const { existsSync } = await import('fs');
73
+ if (!existsSync(this.piperPath)) {
74
+ return false;
75
+ }
76
+ }
77
+ return true;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ getName() {
84
+ return 'piper';
85
+ }
86
+ runPiper(textFile, outputFile, model) {
87
+ return new Promise((resolve, reject) => {
88
+ const args = [
89
+ '--model',
90
+ model,
91
+ '--output-file',
92
+ outputFile,
93
+ ];
94
+ const piper = spawn(this.piperPath, args, { stdio: ['pipe', 'ignore', 'pipe'] });
95
+ const textContent = readFileSync(textFile, 'utf-8');
96
+ piper.stdin.write(textContent);
97
+ piper.stdin.end();
98
+ let stderr = '';
99
+ const MAX_STDERR_SIZE = 2048;
100
+ piper.stderr.on('data', (data) => {
101
+ const chunk = data.toString();
102
+ stderr = (stderr + chunk).slice(-MAX_STDERR_SIZE);
103
+ });
104
+ piper.on('close', (code) => {
105
+ if (code === 0) {
106
+ resolve();
107
+ }
108
+ else {
109
+ reject(new Error(`Piper failed (exit code ${code}): ${stderr}`));
110
+ }
111
+ });
112
+ piper.on('error', (error) => {
113
+ reject(new Error(`Failed to start Piper: ${error.message}. Ensure Piper is installed and in your PATH.`));
114
+ });
115
+ });
116
+ }
117
+ }
118
+ //# sourceMappingURL=piper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piper.js","sourceRoot":"","sources":["../../../src/engines/piper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare class FileReader {
2
+ static readTextFile(filePath: string): string;
3
+ static fileExists(filePath: string): boolean;
4
+ }
5
+ //# sourceMappingURL=file-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-reader.d.ts","sourceRoot":"","sources":["../../../src/utils/file-reader.ts"],"names":[],"mappings":"AAIA,qBAAa,UAAU;IACrB,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAY7C,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAO7C"}
@@ -0,0 +1,26 @@
1
+ import { readFileSync, existsSync } from "fs";
2
+ import { resolve } from "path";
3
+ import { Logger } from "./logger.js";
4
+ export class FileReader {
5
+ static readTextFile(filePath) {
6
+ try {
7
+ const absolutePath = resolve(filePath);
8
+ return readFileSync(absolutePath, "utf-8");
9
+ }
10
+ catch (error) {
11
+ if (error instanceof Error) {
12
+ Logger.error(`Failed to read file: ${error.message}`);
13
+ }
14
+ throw error;
15
+ }
16
+ }
17
+ static fileExists(filePath) {
18
+ try {
19
+ return existsSync(filePath);
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ }
26
+ //# sourceMappingURL=file-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-reader.js","sourceRoot":"","sources":["../../../src/utils/file-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,OAAO,UAAU;IACrB,MAAM,CAAC,YAAY,CAAC,QAAgB;QAClC,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YACvC,OAAO,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,MAAM,CAAC,KAAK,CAAC,wBAAwB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACxD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,QAAgB;QAChC,IAAI,CAAC;YACH,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ export declare class Logger {
2
+ static info(message: string): void;
3
+ static success(message: string): void;
4
+ static error(message: string): void;
5
+ static warn(message: string): void;
6
+ static debug(message: string): void;
7
+ static log(message: string): void;
8
+ static clear(): void;
9
+ }
10
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,qBAAa,MAAM;IACjB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIrC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAInC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAMnC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIjC,MAAM,CAAC,KAAK,IAAI,IAAI;CAGrB"}
@@ -0,0 +1,27 @@
1
+ import chalk from "chalk";
2
+ export class Logger {
3
+ static info(message) {
4
+ console.log(chalk.blue("ℹ"), message);
5
+ }
6
+ static success(message) {
7
+ console.log(chalk.green("✓"), message);
8
+ }
9
+ static error(message) {
10
+ console.error(chalk.red("✗"), message);
11
+ }
12
+ static warn(message) {
13
+ console.log(chalk.yellow("⚠"), message);
14
+ }
15
+ static debug(message) {
16
+ if (process.env.DEBUG) {
17
+ console.log(chalk.gray("→"), message);
18
+ }
19
+ }
20
+ static log(message) {
21
+ console.log(message);
22
+ }
23
+ static clear() {
24
+ console.clear();
25
+ }
26
+ }
27
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,MAAM;IACjB,MAAM,CAAC,IAAI,CAAC,OAAe;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,OAAe;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAe;QAC1B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,OAAe;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAe;QAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,OAAe;QACxB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK;QACV,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}