@zhoujinandrew/fish-audio-mcp-server 0.7.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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +430 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +72 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/services/fishAudioSDK.d.ts +29 -0
  8. package/dist/services/fishAudioSDK.d.ts.map +1 -0
  9. package/dist/services/fishAudioSDK.js +185 -0
  10. package/dist/services/fishAudioSDK.js.map +1 -0
  11. package/dist/tools/listReferences.d.ts +22 -0
  12. package/dist/tools/listReferences.d.ts.map +1 -0
  13. package/dist/tools/listReferences.js +40 -0
  14. package/dist/tools/listReferences.js.map +1 -0
  15. package/dist/tools/tts.d.ts +100 -0
  16. package/dist/tools/tts.d.ts.map +1 -0
  17. package/dist/tools/tts.js +328 -0
  18. package/dist/tools/tts.js.map +1 -0
  19. package/dist/types/index.d.ts +98 -0
  20. package/dist/types/index.d.ts.map +1 -0
  21. package/dist/types/index.js +20 -0
  22. package/dist/types/index.js.map +1 -0
  23. package/dist/utils/audioPlayer.d.ts +3 -0
  24. package/dist/utils/audioPlayer.d.ts.map +1 -0
  25. package/dist/utils/audioPlayer.js +35 -0
  26. package/dist/utils/audioPlayer.js.map +1 -0
  27. package/dist/utils/config.d.ts +4 -0
  28. package/dist/utils/config.d.ts.map +1 -0
  29. package/dist/utils/config.js +119 -0
  30. package/dist/utils/config.js.map +1 -0
  31. package/dist/utils/logger.d.ts +11 -0
  32. package/dist/utils/logger.d.ts.map +1 -0
  33. package/dist/utils/logger.js +27 -0
  34. package/dist/utils/logger.js.map +1 -0
  35. package/dist/utils/realTimePlayer.d.ts +13 -0
  36. package/dist/utils/realTimePlayer.d.ts.map +1 -0
  37. package/dist/utils/realTimePlayer.js +92 -0
  38. package/dist/utils/realTimePlayer.js.map +1 -0
  39. package/dist/utils/referenceSelector.d.ts +35 -0
  40. package/dist/utils/referenceSelector.d.ts.map +1 -0
  41. package/dist/utils/referenceSelector.js +72 -0
  42. package/dist/utils/referenceSelector.js.map +1 -0
  43. package/package.json +68 -0
@@ -0,0 +1,328 @@
1
+ import { FishAudioSDKService } from '../services/fishAudioSDK.js';
2
+ import { FishAudioError } from '../types/index.js';
3
+ import { loadConfig, getOutputPath } from '../utils/config.js';
4
+ import { writeFileSync, createWriteStream } from 'fs';
5
+ import { playAudio, isAudioPlaybackSupported } from '../utils/audioPlayer.js';
6
+ import { RealTimeAudioPlayer } from '../utils/realTimePlayer.js';
7
+ import { ReferenceSelector } from '../utils/referenceSelector.js';
8
+ import { logger } from '../utils/logger.js';
9
+ export class TTSTool {
10
+ name = 'fish_audio_tts';
11
+ description = 'Generate speech from text using Fish Audio TTS API';
12
+ inputSchema = {
13
+ type: 'object',
14
+ properties: {
15
+ text: {
16
+ type: 'string',
17
+ description: 'Text to convert to speech',
18
+ maxLength: 10000
19
+ },
20
+ reference_id: {
21
+ type: 'string',
22
+ description: 'Voice model reference ID (optional)'
23
+ },
24
+ reference_name: {
25
+ type: 'string',
26
+ description: 'Voice model name to search for (optional)'
27
+ },
28
+ reference_tag: {
29
+ type: 'string',
30
+ description: 'Voice model tag to search for (optional)'
31
+ },
32
+ streaming: {
33
+ type: 'boolean',
34
+ description: 'Enable HTTP streaming mode (optional)',
35
+ default: false
36
+ },
37
+ websocket_streaming: {
38
+ type: 'boolean',
39
+ description: 'Enable WebSocket streaming mode (optional)',
40
+ default: false
41
+ },
42
+ realtime_play: {
43
+ type: 'boolean',
44
+ description: 'Enable real-time audio playback during streaming (optional)',
45
+ default: false
46
+ },
47
+ format: {
48
+ type: 'string',
49
+ enum: ['mp3', 'wav', 'pcm', 'opus'],
50
+ description: 'Output audio format (optional)',
51
+ default: 'mp3'
52
+ },
53
+ mp3_bitrate: {
54
+ type: 'number',
55
+ enum: [64, 128, 192],
56
+ description: 'MP3 bitrate in kbps (optional)',
57
+ default: 128
58
+ },
59
+ normalize: {
60
+ type: 'boolean',
61
+ description: 'Enable text normalization (optional)',
62
+ default: true
63
+ },
64
+ latency: {
65
+ type: 'string',
66
+ enum: ['normal', 'balanced'],
67
+ description: 'Latency mode (optional)',
68
+ default: 'balanced'
69
+ },
70
+ output_path: {
71
+ type: 'string',
72
+ description: 'Custom output file path (optional)'
73
+ },
74
+ auto_play: {
75
+ type: 'boolean',
76
+ description: 'Automatically play the generated audio (optional)',
77
+ default: false
78
+ },
79
+ speed: {
80
+ type: 'number',
81
+ description: 'Speaking rate multiplier (0.5=half speed, 1.0=normal, 2.0=double speed)',
82
+ minimum: 0.5,
83
+ maximum: 2.0,
84
+ default: 1.0
85
+ },
86
+ volume: {
87
+ type: 'number',
88
+ description: 'Volume adjustment in dB (0=no change, positive=louder, negative=quieter)',
89
+ default: 0
90
+ },
91
+ temperature: {
92
+ type: 'number',
93
+ description: 'Expressiveness/emotion control (0=consistent and calm, 1=varied and emotional)',
94
+ minimum: 0,
95
+ maximum: 1,
96
+ default: 0.7
97
+ }
98
+ },
99
+ required: ['text']
100
+ };
101
+ service;
102
+ constructor() {
103
+ this.service = new FishAudioSDKService();
104
+ }
105
+ async run(input) {
106
+ try {
107
+ // Validate input
108
+ if (!input.text || input.text.trim().length === 0) {
109
+ return {
110
+ success: false,
111
+ error: 'Text input is required'
112
+ };
113
+ }
114
+ if (input.text.length > 10000) {
115
+ return {
116
+ success: false,
117
+ error: 'Text length exceeds maximum limit of 10,000 characters'
118
+ };
119
+ }
120
+ const config = loadConfig();
121
+ // Select reference ID based on input parameters
122
+ let selectedReferenceId;
123
+ if (input.reference_id || input.reference_name || input.reference_tag) {
124
+ // Use reference selector if references are configured
125
+ if (config.references && config.references.length > 0) {
126
+ const selector = new ReferenceSelector(config.references, config.defaultReference);
127
+ selectedReferenceId = selector.selectReference({
128
+ id: input.reference_id,
129
+ name: input.reference_name,
130
+ tag: input.reference_tag
131
+ });
132
+ if (!selectedReferenceId && (input.reference_name || input.reference_tag)) {
133
+ return {
134
+ success: false,
135
+ error: `No reference found matching: ${input.reference_name || input.reference_tag}`
136
+ };
137
+ }
138
+ }
139
+ else {
140
+ // Fallback to direct ID if no references configured
141
+ selectedReferenceId = input.reference_id;
142
+ }
143
+ }
144
+ else {
145
+ // Use default reference or backward compatible referenceId
146
+ selectedReferenceId = config.defaultReference || config.referenceId;
147
+ }
148
+ // Prepare parameters
149
+ const ttsParams = {
150
+ text: input.text,
151
+ referenceId: selectedReferenceId,
152
+ format: (input.format || config.outputFormat),
153
+ mp3Bitrate: (input.mp3_bitrate || config.mp3Bitrate),
154
+ normalize: input.normalize !== false,
155
+ latency: (input.latency || 'balanced'),
156
+ streaming: input.streaming ?? config.streaming,
157
+ speed: input.speed,
158
+ volume: input.volume,
159
+ temperature: input.temperature,
160
+ };
161
+ // Determine output path
162
+ const outputPath = input.output_path || getOutputPath(ttsParams.format || 'mp3');
163
+ // Determine if auto-play is enabled
164
+ const shouldAutoPlay = input.auto_play ?? config.autoPlay;
165
+ // Determine if WebSocket streaming is enabled
166
+ const useWebSocketStreaming = input.websocket_streaming ?? config.websocketStreaming;
167
+ // WebSocket streaming mode with real-time playback
168
+ if (useWebSocketStreaming) {
169
+ return await this.handleWebSocketStreaming(input, ttsParams, outputPath, shouldAutoPlay || false);
170
+ }
171
+ if (ttsParams.streaming) {
172
+ // HTTP Streaming mode
173
+ const totalBytes = await this.service.generateSpeechStream(ttsParams, outputPath);
174
+ // Auto-play if requested
175
+ if (shouldAutoPlay && isAudioPlaybackSupported()) {
176
+ try {
177
+ await playAudio(outputPath);
178
+ }
179
+ catch (playError) {
180
+ logger.error('Audio playback failed:', playError);
181
+ }
182
+ }
183
+ return {
184
+ success: true,
185
+ file_path: outputPath,
186
+ format: ttsParams.format,
187
+ played: shouldAutoPlay || false
188
+ };
189
+ }
190
+ else {
191
+ // Non-streaming mode
192
+ const response = await this.service.generateSpeech(ttsParams);
193
+ // Save to file if output path is specified
194
+ if (outputPath) {
195
+ writeFileSync(outputPath, response.audio);
196
+ // Auto-play if requested
197
+ if (shouldAutoPlay && isAudioPlaybackSupported()) {
198
+ try {
199
+ await playAudio(outputPath);
200
+ }
201
+ catch (playError) {
202
+ logger.error('Audio playback failed:', playError);
203
+ }
204
+ }
205
+ return {
206
+ success: true,
207
+ file_path: outputPath,
208
+ format: response.format,
209
+ played: shouldAutoPlay || false
210
+ };
211
+ }
212
+ else {
213
+ // Return base64 encoded audio
214
+ return {
215
+ success: true,
216
+ audio_data: response.audio.toString('base64'),
217
+ format: response.format
218
+ };
219
+ }
220
+ }
221
+ }
222
+ catch (error) {
223
+ if (error instanceof FishAudioError) {
224
+ return {
225
+ success: false,
226
+ error: `${error.message} (${error.code})`
227
+ };
228
+ }
229
+ return {
230
+ success: false,
231
+ error: error instanceof Error ? error.message : 'Unknown error occurred'
232
+ };
233
+ }
234
+ }
235
+ async handleWebSocketStreaming(input, ttsParams, outputPath, shouldAutoPlay) {
236
+ const writeStream = outputPath ? createWriteStream(outputPath) : null;
237
+ let realTimePlayer = null;
238
+ let totalBytes = 0;
239
+ const audioChunks = [];
240
+ try {
241
+ // Set up real-time player if requested
242
+ const config = loadConfig();
243
+ const shouldRealtimePlay = input.realtime_play ?? config.realtimePlay;
244
+ if (shouldRealtimePlay && isAudioPlaybackSupported()) {
245
+ realTimePlayer = new RealTimeAudioPlayer();
246
+ realTimePlayer.start(ttsParams.format || 'opus');
247
+ }
248
+ // Split text into chunks for streaming
249
+ const textChunks = this.splitTextIntoChunks(input.text);
250
+ // Stream via WebSocket
251
+ const audioStream = this.service.generateSpeechWebSocket(ttsParams, textChunks);
252
+ for await (const audioChunk of audioStream) {
253
+ totalBytes += audioChunk.length;
254
+ // Write to file if output path specified
255
+ if (writeStream) {
256
+ writeStream.write(audioChunk);
257
+ }
258
+ // Play in real-time if requested
259
+ if (realTimePlayer) {
260
+ realTimePlayer.write(audioChunk);
261
+ }
262
+ // Collect chunks for post-playback if auto-play is enabled
263
+ if (shouldAutoPlay && !shouldRealtimePlay) {
264
+ audioChunks.push(audioChunk);
265
+ }
266
+ }
267
+ // Close write stream
268
+ if (writeStream) {
269
+ writeStream.end();
270
+ }
271
+ // Stop real-time player
272
+ if (realTimePlayer) {
273
+ realTimePlayer.stop();
274
+ }
275
+ // Auto-play collected audio if requested (and not already played in real-time)
276
+ let played = false;
277
+ if (shouldAutoPlay && !shouldRealtimePlay && outputPath && isAudioPlaybackSupported()) {
278
+ try {
279
+ await playAudio(outputPath);
280
+ played = true;
281
+ }
282
+ catch (playError) {
283
+ logger.error('Audio playback failed:', playError);
284
+ }
285
+ }
286
+ else if (shouldRealtimePlay) {
287
+ played = true;
288
+ }
289
+ return {
290
+ success: true,
291
+ file_path: outputPath || undefined,
292
+ format: ttsParams.format,
293
+ played,
294
+ streaming_mode: 'websocket',
295
+ total_bytes: totalBytes
296
+ };
297
+ }
298
+ catch (error) {
299
+ // Clean up on error
300
+ if (writeStream) {
301
+ writeStream.end();
302
+ }
303
+ if (realTimePlayer) {
304
+ realTimePlayer.stop();
305
+ }
306
+ throw error;
307
+ }
308
+ }
309
+ splitTextIntoChunks(text, chunkSize = 100) {
310
+ const sentences = text.match(/[^.!?]+[.!?]+/g) || [text];
311
+ const chunks = [];
312
+ let currentChunk = '';
313
+ for (const sentence of sentences) {
314
+ if (currentChunk.length + sentence.length > chunkSize && currentChunk.length > 0) {
315
+ chunks.push(currentChunk.trim());
316
+ currentChunk = sentence;
317
+ }
318
+ else {
319
+ currentChunk += sentence;
320
+ }
321
+ }
322
+ if (currentChunk.trim()) {
323
+ chunks.push(currentChunk.trim());
324
+ }
325
+ return chunks;
326
+ }
327
+ }
328
+ //# sourceMappingURL=tts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tts.js","sourceRoot":"","sources":["../../src/tools/tts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ export interface ReferenceConfig {
2
+ id: string;
3
+ name?: string;
4
+ tags?: string[];
5
+ }
6
+ export interface Config {
7
+ apiKey: string;
8
+ modelId: string;
9
+ referenceId?: string;
10
+ references?: ReferenceConfig[];
11
+ defaultReference?: string;
12
+ outputFormat: AudioFormat;
13
+ streaming: boolean;
14
+ mp3Bitrate: Mp3Bitrate;
15
+ audioOutputDir: string;
16
+ autoPlay?: boolean;
17
+ websocketStreaming?: boolean;
18
+ realtimePlay?: boolean;
19
+ }
20
+ export type AudioFormat = 'mp3' | 'wav' | 'pcm' | 'opus';
21
+ export type Mp3Bitrate = 64 | 128 | 192;
22
+ export type LatencyMode = 'normal' | 'balanced';
23
+ export interface TTSParams {
24
+ text: string;
25
+ referenceId?: string;
26
+ format?: AudioFormat;
27
+ mp3Bitrate?: Mp3Bitrate;
28
+ normalize?: boolean;
29
+ latency?: LatencyMode;
30
+ chunkLength?: number;
31
+ streaming?: boolean;
32
+ websocketStreaming?: boolean;
33
+ speed?: number;
34
+ volume?: number;
35
+ temperature?: number;
36
+ }
37
+ export interface TTSResponse {
38
+ audio: Buffer;
39
+ format: string;
40
+ duration?: number;
41
+ }
42
+ export interface TTSToolParams {
43
+ text: string;
44
+ reference_id?: string;
45
+ reference_name?: string;
46
+ reference_tag?: string;
47
+ streaming?: boolean;
48
+ websocket_streaming?: boolean;
49
+ realtime_play?: boolean;
50
+ format?: AudioFormat;
51
+ mp3_bitrate?: Mp3Bitrate;
52
+ normalize?: boolean;
53
+ latency?: LatencyMode;
54
+ output_path?: string;
55
+ auto_play?: boolean;
56
+ speed?: number;
57
+ volume?: number;
58
+ temperature?: number;
59
+ }
60
+ export interface TTSToolResponse {
61
+ success: boolean;
62
+ audio_data?: string;
63
+ file_path?: string;
64
+ format?: string;
65
+ played?: boolean;
66
+ streaming_mode?: 'http' | 'websocket';
67
+ total_bytes?: number;
68
+ error?: string;
69
+ }
70
+ export interface FishAudioAPIRequest {
71
+ text: string;
72
+ reference_id?: string;
73
+ chunk_length?: number;
74
+ format?: string;
75
+ mp3_bitrate?: number;
76
+ normalize?: boolean;
77
+ latency?: string;
78
+ streaming?: boolean;
79
+ }
80
+ export interface FishAudioAPIResponse {
81
+ status: string;
82
+ data?: any;
83
+ error?: string;
84
+ }
85
+ export declare enum ErrorCode {
86
+ INVALID_API_KEY = "INVALID_API_KEY",
87
+ NETWORK_ERROR = "NETWORK_ERROR",
88
+ INVALID_PARAMS = "INVALID_PARAMS",
89
+ QUOTA_EXCEEDED = "QUOTA_EXCEEDED",
90
+ SERVER_ERROR = "SERVER_ERROR",
91
+ UNKNOWN_ERROR = "UNKNOWN_ERROR"
92
+ }
93
+ export declare class FishAudioError extends Error {
94
+ code: ErrorCode;
95
+ details?: any | undefined;
96
+ constructor(message: string, code: ErrorCode, details?: any | undefined);
97
+ }
98
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ export var ErrorCode;
2
+ (function (ErrorCode) {
3
+ ErrorCode["INVALID_API_KEY"] = "INVALID_API_KEY";
4
+ ErrorCode["NETWORK_ERROR"] = "NETWORK_ERROR";
5
+ ErrorCode["INVALID_PARAMS"] = "INVALID_PARAMS";
6
+ ErrorCode["QUOTA_EXCEEDED"] = "QUOTA_EXCEEDED";
7
+ ErrorCode["SERVER_ERROR"] = "SERVER_ERROR";
8
+ ErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
9
+ })(ErrorCode || (ErrorCode = {}));
10
+ export class FishAudioError extends Error {
11
+ code;
12
+ details;
13
+ constructor(message, code, details) {
14
+ super(message);
15
+ this.code = code;
16
+ this.details = details;
17
+ this.name = 'FishAudioError';
18
+ }
19
+ }
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AA6FA,MAAM,CAAN,IAAY,SAOX;AAPD,WAAY,SAAS;IACnB,gDAAmC,CAAA;IACnC,4CAA+B,CAAA;IAC/B,8CAAiC,CAAA;IACjC,8CAAiC,CAAA;IACjC,0CAA6B,CAAA;IAC7B,4CAA+B,CAAA;AACjC,CAAC,EAPW,SAAS,KAAT,SAAS,QAOpB;AAED,MAAM,OAAO,cAAe,SAAQ,KAAK;IAG9B;IACA;IAHT,YACE,OAAe,EACR,IAAe,EACf,OAAa;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAAW;QACf,YAAO,GAAP,OAAO,CAAM;QAGpB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export declare function playAudio(filePath: string): Promise<void>;
2
+ export declare function isAudioPlaybackSupported(): boolean;
3
+ //# sourceMappingURL=audioPlayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioPlayer.d.ts","sourceRoot":"","sources":["../../src/utils/audioPlayer.ts"],"names":[],"mappings":"AAOA,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB/D;AAED,wBAAgB,wBAAwB,IAAI,OAAO,CAGlD"}
@@ -0,0 +1,35 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import { platform } from 'os';
4
+ import { logger } from './logger.js';
5
+ const execAsync = promisify(exec);
6
+ export async function playAudio(filePath) {
7
+ const os = platform();
8
+ let command;
9
+ switch (os) {
10
+ case 'darwin': // macOS
11
+ command = `afplay "${filePath}"`;
12
+ break;
13
+ case 'win32': // Windows
14
+ command = `powershell -c "(New-Object Media.SoundPlayer '${filePath}').PlaySync()"`;
15
+ break;
16
+ case 'linux':
17
+ // Try multiple players in order of preference
18
+ command = `which aplay >/dev/null 2>&1 && aplay "${filePath}" || which mpg123 >/dev/null 2>&1 && mpg123 "${filePath}" || which ffplay >/dev/null 2>&1 && ffplay -nodisp -autoexit "${filePath}" || echo "No audio player found"`;
19
+ break;
20
+ default:
21
+ throw new Error(`Unsupported platform: ${os}`);
22
+ }
23
+ try {
24
+ await execAsync(command);
25
+ }
26
+ catch (error) {
27
+ logger.error('Failed to play audio:', error);
28
+ throw new Error(`Audio playback failed: ${error}`);
29
+ }
30
+ }
31
+ export function isAudioPlaybackSupported() {
32
+ const os = platform();
33
+ return ['darwin', 'win32', 'linux'].includes(os);
34
+ }
35
+ //# sourceMappingURL=audioPlayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioPlayer.js","sourceRoot":"","sources":["../../src/utils/audioPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB;IAC9C,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,IAAI,OAAe,CAAC;IAEpB,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,QAAQ,EAAE,QAAQ;YACrB,OAAO,GAAG,WAAW,QAAQ,GAAG,CAAC;YACjC,MAAM;QACR,KAAK,OAAO,EAAE,UAAU;YACtB,OAAO,GAAG,iDAAiD,QAAQ,gBAAgB,CAAC;YACpF,MAAM;QACR,KAAK,OAAO;YACV,8CAA8C;YAC9C,OAAO,GAAG,yCAAyC,QAAQ,gDAAgD,QAAQ,kEAAkE,QAAQ,mCAAmC,CAAC;YACjO,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Config } from '../types/index.js';
2
+ export declare function loadConfig(): Config;
3
+ export declare function getOutputPath(format: string): string;
4
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAA4C,MAAM,mBAAmB,CAAC;AAuErF,wBAAgB,UAAU,IAAI,MAAM,CAsDnC;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpD"}
@@ -0,0 +1,119 @@
1
+ import { config as dotenvConfig } from 'dotenv';
2
+ import { existsSync, mkdirSync } from 'fs';
3
+ import { join, resolve } from 'path';
4
+ import { homedir } from 'os';
5
+ import { logger } from './logger.js';
6
+ dotenvConfig();
7
+ function parseBoolean(value, defaultValue) {
8
+ if (!value)
9
+ return defaultValue;
10
+ return value.toLowerCase() === 'true';
11
+ }
12
+ function parseAudioFormat(value, defaultValue) {
13
+ if (!value)
14
+ return defaultValue;
15
+ const validFormats = ['mp3', 'wav', 'pcm', 'opus'];
16
+ const format = value.toLowerCase();
17
+ return validFormats.includes(format) ? format : defaultValue;
18
+ }
19
+ function parseMp3Bitrate(value, defaultValue) {
20
+ if (!value)
21
+ return defaultValue;
22
+ const bitrate = parseInt(value);
23
+ const validBitrates = [64, 128, 192];
24
+ return validBitrates.includes(bitrate) ? bitrate : defaultValue;
25
+ }
26
+ let configCache = null;
27
+ function parseReferences() {
28
+ const references = [];
29
+ // Parse FISH_REFERENCES as JSON array
30
+ const referencesStr = process.env.FISH_REFERENCES;
31
+ if (referencesStr) {
32
+ try {
33
+ const parsedRefs = JSON.parse(referencesStr);
34
+ if (Array.isArray(parsedRefs)) {
35
+ for (const ref of parsedRefs) {
36
+ if (ref.reference_id || ref.id) {
37
+ references.push({
38
+ id: ref.reference_id || ref.id,
39
+ name: ref.name,
40
+ tags: ref.tags
41
+ });
42
+ }
43
+ }
44
+ }
45
+ }
46
+ catch (error) {
47
+ logger.error('Failed to parse FISH_REFERENCES as JSON:', error);
48
+ logger.error('Please use JSON array format: [{"reference_id":"id1","name":"Alice","tags":["female","english"]}]');
49
+ }
50
+ }
51
+ // Fallback: support individual reference configs for backward compatibility
52
+ if (references.length === 0) {
53
+ for (let i = 1; i <= 10; i++) {
54
+ const id = process.env[`FISH_REFERENCE_${i}_ID`];
55
+ if (id) {
56
+ references.push({
57
+ id,
58
+ name: process.env[`FISH_REFERENCE_${i}_NAME`],
59
+ tags: process.env[`FISH_REFERENCE_${i}_TAGS`]?.split(',').map(t => t.trim())
60
+ });
61
+ }
62
+ }
63
+ }
64
+ return references;
65
+ }
66
+ export function loadConfig() {
67
+ if (configCache) {
68
+ return configCache;
69
+ }
70
+ const apiKey = process.env.FISH_API_KEY;
71
+ if (!apiKey) {
72
+ throw new Error('FISH_API_KEY environment variable is required');
73
+ }
74
+ // Default to user's home directory for audio output
75
+ const defaultOutputDir = join(homedir(), '.fish-audio-mcp', 'audio_output');
76
+ let audioOutputDir = process.env.AUDIO_OUTPUT_DIR || defaultOutputDir;
77
+ // Expand ~ to home directory if present
78
+ if (audioOutputDir.startsWith('~/')) {
79
+ audioOutputDir = join(homedir(), audioOutputDir.slice(2));
80
+ }
81
+ const resolvedOutputDir = resolve(audioOutputDir);
82
+ // Create output directory if it doesn't exist
83
+ try {
84
+ if (!existsSync(resolvedOutputDir)) {
85
+ mkdirSync(resolvedOutputDir, { recursive: true });
86
+ }
87
+ }
88
+ catch (error) {
89
+ logger.error(`Warning: Could not create audio output directory at ${resolvedOutputDir}. Audio files will be saved to memory only.`);
90
+ }
91
+ const streaming = parseBoolean(process.env.FISH_STREAMING, false);
92
+ const autoPlay = parseBoolean(process.env.FISH_AUTO_PLAY, false);
93
+ // Parse references
94
+ const references = parseReferences();
95
+ const defaultReference = process.env.FISH_DEFAULT_REFERENCE || process.env.FISH_REFERENCE_ID;
96
+ const config = {
97
+ apiKey,
98
+ modelId: process.env.FISH_MODEL_ID || 's1',
99
+ referenceId: process.env.FISH_REFERENCE_ID, // Keep for backward compatibility
100
+ references,
101
+ defaultReference,
102
+ outputFormat: parseAudioFormat(process.env.FISH_OUTPUT_FORMAT, 'mp3'),
103
+ streaming: streaming,
104
+ mp3Bitrate: parseMp3Bitrate(process.env.FISH_MP3_BITRATE, 128),
105
+ audioOutputDir: resolvedOutputDir,
106
+ autoPlay: autoPlay,
107
+ websocketStreaming: false, // Default to false for HTTP streaming
108
+ realtimePlay: false // Default to false for standard playback
109
+ };
110
+ configCache = config;
111
+ return config;
112
+ }
113
+ export function getOutputPath(format) {
114
+ const config = loadConfig();
115
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
116
+ const filename = `tts_${timestamp}.${format}`;
117
+ return join(config.audioOutputDir, filename);
118
+ }
119
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}