@mingxy/ocosay 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 (126) hide show
  1. package/README.md +556 -0
  2. package/TECH_PLAN.md +352 -0
  3. package/__mocks__/@opencode-ai/plugin.ts +32 -0
  4. package/dist/config.d.ts +26 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +95 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/core/backends/afplay-backend.d.ts +33 -0
  9. package/dist/core/backends/afplay-backend.d.ts.map +1 -0
  10. package/dist/core/backends/afplay-backend.js +144 -0
  11. package/dist/core/backends/afplay-backend.js.map +1 -0
  12. package/dist/core/backends/aplay-backend.d.ts +33 -0
  13. package/dist/core/backends/aplay-backend.d.ts.map +1 -0
  14. package/dist/core/backends/aplay-backend.js +142 -0
  15. package/dist/core/backends/aplay-backend.js.map +1 -0
  16. package/dist/core/backends/base.d.ts +94 -0
  17. package/dist/core/backends/base.d.ts.map +1 -0
  18. package/dist/core/backends/base.js +6 -0
  19. package/dist/core/backends/base.js.map +1 -0
  20. package/dist/core/backends/index.d.ts +29 -0
  21. package/dist/core/backends/index.d.ts.map +1 -0
  22. package/dist/core/backends/index.js +114 -0
  23. package/dist/core/backends/index.js.map +1 -0
  24. package/dist/core/backends/naudiodon-backend.d.ts +52 -0
  25. package/dist/core/backends/naudiodon-backend.d.ts.map +1 -0
  26. package/dist/core/backends/naudiodon-backend.js +123 -0
  27. package/dist/core/backends/naudiodon-backend.js.map +1 -0
  28. package/dist/core/backends/powershell-backend.d.ts +34 -0
  29. package/dist/core/backends/powershell-backend.d.ts.map +1 -0
  30. package/dist/core/backends/powershell-backend.js +154 -0
  31. package/dist/core/backends/powershell-backend.js.map +1 -0
  32. package/dist/core/player.d.ts +97 -0
  33. package/dist/core/player.d.ts.map +1 -0
  34. package/dist/core/player.js +268 -0
  35. package/dist/core/player.js.map +1 -0
  36. package/dist/core/speaker.d.ts +97 -0
  37. package/dist/core/speaker.d.ts.map +1 -0
  38. package/dist/core/speaker.js +218 -0
  39. package/dist/core/speaker.js.map +1 -0
  40. package/dist/core/stream-player.d.ts +107 -0
  41. package/dist/core/stream-player.d.ts.map +1 -0
  42. package/dist/core/stream-player.js +272 -0
  43. package/dist/core/stream-player.js.map +1 -0
  44. package/dist/core/stream-reader.d.ts +86 -0
  45. package/dist/core/stream-reader.d.ts.map +1 -0
  46. package/dist/core/stream-reader.js +172 -0
  47. package/dist/core/stream-reader.js.map +1 -0
  48. package/dist/core/streaming-synthesizer.d.ts +51 -0
  49. package/dist/core/streaming-synthesizer.d.ts.map +1 -0
  50. package/dist/core/streaming-synthesizer.js +103 -0
  51. package/dist/core/streaming-synthesizer.js.map +1 -0
  52. package/dist/core/types.d.ts +141 -0
  53. package/dist/core/types.d.ts.map +1 -0
  54. package/dist/core/types.js +37 -0
  55. package/dist/core/types.js.map +1 -0
  56. package/dist/index.d.ts +40 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +179 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/plugin.d.ts +4 -0
  61. package/dist/plugin.d.ts.map +1 -0
  62. package/dist/plugin.js +151 -0
  63. package/dist/plugin.js.map +1 -0
  64. package/dist/providers/base.d.ts +55 -0
  65. package/dist/providers/base.d.ts.map +1 -0
  66. package/dist/providers/base.js +95 -0
  67. package/dist/providers/base.js.map +1 -0
  68. package/dist/providers/minimax.d.ts +84 -0
  69. package/dist/providers/minimax.d.ts.map +1 -0
  70. package/dist/providers/minimax.js +387 -0
  71. package/dist/providers/minimax.js.map +1 -0
  72. package/dist/tools/tts.d.ts +147 -0
  73. package/dist/tools/tts.d.ts.map +1 -0
  74. package/dist/tools/tts.js +232 -0
  75. package/dist/tools/tts.js.map +1 -0
  76. package/jest.config.js +15 -0
  77. package/package.json +49 -0
  78. package/src/config.ts +121 -0
  79. package/src/core/backends/afplay-backend.ts +162 -0
  80. package/src/core/backends/aplay-backend.ts +160 -0
  81. package/src/core/backends/base.ts +117 -0
  82. package/src/core/backends/index.ts +128 -0
  83. package/src/core/backends/naudiodon-backend.ts +164 -0
  84. package/src/core/backends/powershell-backend.ts +173 -0
  85. package/src/core/player.ts +322 -0
  86. package/src/core/speaker.ts +283 -0
  87. package/src/core/stream-player.ts +326 -0
  88. package/src/core/stream-reader.ts +190 -0
  89. package/src/core/streaming-synthesizer.ts +123 -0
  90. package/src/core/types.ts +185 -0
  91. package/src/index.ts +233 -0
  92. package/src/plugin.ts +166 -0
  93. package/src/providers/base.ts +150 -0
  94. package/src/providers/minimax.ts +515 -0
  95. package/src/tools/tts.ts +277 -0
  96. package/src/types/naudiodon.d.ts +19 -0
  97. package/tests/__mocks__/@opencode-ai/plugin.ts +32 -0
  98. package/tests/backends.test.ts +831 -0
  99. package/tests/index.test.ts +201 -0
  100. package/tests/integration-test.d.ts +6 -0
  101. package/tests/integration-test.d.ts.map +1 -0
  102. package/tests/integration-test.js +84 -0
  103. package/tests/integration-test.js.map +1 -0
  104. package/tests/integration-test.ts +93 -0
  105. package/tests/p1-fixes.test.ts +160 -0
  106. package/tests/plugin.test.ts +311 -0
  107. package/tests/provider.test.d.ts +2 -0
  108. package/tests/provider.test.d.ts.map +1 -0
  109. package/tests/provider.test.js +69 -0
  110. package/tests/provider.test.js.map +1 -0
  111. package/tests/provider.test.ts +87 -0
  112. package/tests/speaker.test.d.ts +2 -0
  113. package/tests/speaker.test.d.ts.map +1 -0
  114. package/tests/speaker.test.js +63 -0
  115. package/tests/speaker.test.js.map +1 -0
  116. package/tests/speaker.test.ts +232 -0
  117. package/tests/stream-player.test.ts +303 -0
  118. package/tests/stream-reader.test.ts +269 -0
  119. package/tests/streaming-synthesizer.test.ts +225 -0
  120. package/tests/tts-tools.test.ts +270 -0
  121. package/tests/types.test.d.ts +2 -0
  122. package/tests/types.test.d.ts.map +1 -0
  123. package/tests/types.test.js +61 -0
  124. package/tests/types.test.js.map +1 -0
  125. package/tests/types.test.ts +63 -0
  126. package/tsconfig.json +22 -0
package/dist/index.js ADDED
@@ -0,0 +1,179 @@
1
+ import { handleToolCall } from './tools/tts';
2
+ import { registerProvider, getProvider, listProviders } from './providers/base';
3
+ import { MiniMaxProvider } from './providers/minimax';
4
+ import { Speaker } from './core/speaker';
5
+ import { TTSError, TTSErrorCode } from './core/types';
6
+ import { StreamReader } from './core/stream-reader';
7
+ import { StreamingSynthesizer } from './core/streaming-synthesizer';
8
+ import { StreamPlayer } from './core/stream-player';
9
+ export const pluginInfo = {
10
+ name: 'ocosay',
11
+ version: '1.0.0',
12
+ description: 'OpenCode TTS 播放插件 - 支持 MiniMax TTS',
13
+ author: '',
14
+ license: 'MIT'
15
+ };
16
+ let speaker;
17
+ let streamReader;
18
+ let streamingSynthesizer;
19
+ let streamPlayer;
20
+ let initialized = false;
21
+ let autoReadEnabled = false;
22
+ export async function initialize(config) {
23
+ if (initialized) {
24
+ return;
25
+ }
26
+ if (config?.providers?.minimax) {
27
+ const minimaxProvider = new MiniMaxProvider(config.providers.minimax);
28
+ registerProvider('minimax', minimaxProvider);
29
+ await minimaxProvider.initialize();
30
+ }
31
+ const speakerOptions = {
32
+ defaultProvider: config?.defaultProvider || 'minimax',
33
+ defaultModel: config?.defaultModel || 'stream',
34
+ defaultVoice: config?.defaultVoice
35
+ };
36
+ speaker = new Speaker(speakerOptions);
37
+ if (config?.autoRead) {
38
+ autoReadEnabled = true;
39
+ initializeStreamComponents(config);
40
+ }
41
+ initialized = true;
42
+ }
43
+ function initializeStreamComponents(config) {
44
+ const provider = getProvider(config?.defaultProvider || 'minimax');
45
+ streamReader = new StreamReader(config?.streamBufferSize || 30, config?.streamBufferTimeout || 2000);
46
+ streamingSynthesizer = new StreamingSynthesizer({
47
+ provider,
48
+ voice: config?.defaultVoice,
49
+ speed: 1.0,
50
+ volume: 1.0,
51
+ pitch: 1.0
52
+ });
53
+ const playerEvents = {
54
+ onStart: () => { },
55
+ onEnd: () => { },
56
+ onProgress: (bytesWritten) => { },
57
+ onError: (error) => console.error('Stream player error:', error),
58
+ onStop: () => { }
59
+ };
60
+ streamPlayer = new StreamPlayer({ events: playerEvents });
61
+ const synthesisQueue = [];
62
+ let isSynthesizing = false;
63
+ async function processQueue() {
64
+ while (synthesisQueue.length > 0) {
65
+ const text = synthesisQueue.shift();
66
+ isSynthesizing = true;
67
+ try {
68
+ await streamingSynthesizer?.synthesize(text);
69
+ }
70
+ catch (error) {
71
+ console.error('Synthesize error:', error);
72
+ }
73
+ }
74
+ isSynthesizing = false;
75
+ }
76
+ streamReader.on('textReady', (text) => {
77
+ synthesisQueue.push(text);
78
+ if (!isSynthesizing) {
79
+ processQueue();
80
+ }
81
+ });
82
+ streamingSynthesizer.on('chunk', (chunk) => {
83
+ if (streamPlayer) {
84
+ streamPlayer.write(chunk);
85
+ }
86
+ });
87
+ streamingSynthesizer.on('done', () => {
88
+ if (streamPlayer) {
89
+ streamPlayer.end();
90
+ }
91
+ });
92
+ const TuiEventBus = global.__opencode_tuieventbus__;
93
+ if (TuiEventBus) {
94
+ const eventBus = new TuiEventBus();
95
+ let messagePartDeltaHandler;
96
+ let messagePartEndHandler;
97
+ messagePartDeltaHandler = (event) => {
98
+ if (event?.properties) {
99
+ streamReader?.handleDelta(event.sessionId || '', event.messageId || '', event.partId || '', event.properties.delta || '');
100
+ }
101
+ };
102
+ messagePartEndHandler = () => {
103
+ streamReader?.handleEnd();
104
+ };
105
+ eventBus.on('message.part.delta', messagePartDeltaHandler);
106
+ eventBus.on('message.part.end', messagePartEndHandler);
107
+ }
108
+ }
109
+ export function getSpeaker() {
110
+ if (!speaker) {
111
+ throw new TTSError('Plugin not initialized. Call initialize() first.', TTSErrorCode.UNKNOWN, 'ocosay');
112
+ }
113
+ return speaker;
114
+ }
115
+ export function isStreamEnabled() {
116
+ return streamReader !== undefined && streamingSynthesizer !== undefined && streamPlayer !== undefined;
117
+ }
118
+ export function isAutoReadEnabled() {
119
+ return autoReadEnabled;
120
+ }
121
+ export function getStreamStatus() {
122
+ if (!streamReader) {
123
+ return { isActive: false, bytesWritten: 0, state: 'not_initialized' };
124
+ }
125
+ return {
126
+ isActive: streamReader.isActive(),
127
+ bytesWritten: streamPlayer?.getBytesWritten() ?? 0,
128
+ state: streamReader.getState()
129
+ };
130
+ }
131
+ export function getStreamReader() {
132
+ return streamReader;
133
+ }
134
+ export function getStreamingSynthesizer() {
135
+ return streamingSynthesizer;
136
+ }
137
+ export function getStreamPlayer() {
138
+ return streamPlayer;
139
+ }
140
+ export async function destroy() {
141
+ if (streamReader) {
142
+ streamReader.reset();
143
+ streamReader = undefined;
144
+ }
145
+ if (streamingSynthesizer) {
146
+ streamingSynthesizer.reset();
147
+ streamingSynthesizer = undefined;
148
+ }
149
+ if (streamPlayer) {
150
+ await streamPlayer.stop();
151
+ streamPlayer = undefined;
152
+ }
153
+ if (speaker) {
154
+ await speaker.destroy();
155
+ speaker = undefined;
156
+ }
157
+ for (const providerName of listProviders()) {
158
+ try {
159
+ getProvider(providerName)?.destroy();
160
+ }
161
+ catch (e) { }
162
+ }
163
+ initialized = false;
164
+ autoReadEnabled = false;
165
+ }
166
+ export { handleToolCall };
167
+ export const toolNames = [
168
+ 'tts_speak',
169
+ 'tts_stop',
170
+ 'tts_pause',
171
+ 'tts_resume',
172
+ 'tts_list_voices',
173
+ 'tts_list_providers',
174
+ 'tts_status',
175
+ 'tts_stream_speak',
176
+ 'tts_stream_stop',
177
+ 'tts_stream_status'
178
+ ];
179
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from '@opencode-ai/plugin';
2
+ declare const OcosayPlugin: Plugin;
3
+ export default OcosayPlugin;
4
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAA8B,MAAM,qBAAqB,CAAA;AA4I7E,QAAA,MAAM,YAAY,EAAE,MAsBnB,CAAA;AAED,eAAe,YAAY,CAAA"}
package/dist/plugin.js ADDED
@@ -0,0 +1,151 @@
1
+ import { tool } from '@opencode-ai/plugin';
2
+ import { handleToolCall } from './index';
3
+ import { initialize } from './index';
4
+ const pluginName = 'ocosay';
5
+ const ttsSpeakTool = tool({
6
+ description: '将文本转换为语音并播放',
7
+ args: {
8
+ text: tool.schema.string().describe('要转换的文本内容'),
9
+ provider: tool.schema.string().optional().describe('TTS 提供商名称'),
10
+ voice: tool.schema.string().optional().describe('音色 ID'),
11
+ model: tool.schema.enum(['sync', 'async', 'stream']).optional().describe('合成模式'),
12
+ speed: tool.schema.number().optional().describe('语速 0.5-2.0'),
13
+ volume: tool.schema.number().optional().describe('音量 0-100'),
14
+ pitch: tool.schema.number().optional().describe('音调 0.5-2.0')
15
+ },
16
+ execute: async (args) => {
17
+ const result = await handleToolCall('tts_speak', args);
18
+ if (result.success === false) {
19
+ throw new Error(result.error || 'Unknown error');
20
+ }
21
+ return result;
22
+ }
23
+ });
24
+ const ttsStopTool = tool({
25
+ description: '停止当前 TTS 播放',
26
+ args: {},
27
+ execute: async () => {
28
+ const result = await handleToolCall('tts_stop');
29
+ if (result.success === false) {
30
+ throw new Error(result.error || 'Unknown error');
31
+ }
32
+ return result;
33
+ }
34
+ });
35
+ const ttsPauseTool = tool({
36
+ description: '暂停当前 TTS 播放',
37
+ args: {},
38
+ execute: async () => {
39
+ const result = await handleToolCall('tts_pause');
40
+ if (result.success === false) {
41
+ throw new Error(result.error || 'Unknown error');
42
+ }
43
+ return result;
44
+ }
45
+ });
46
+ const ttsResumeTool = tool({
47
+ description: '恢复暂停的 TTS 播放',
48
+ args: {},
49
+ execute: async () => {
50
+ const result = await handleToolCall('tts_resume');
51
+ if (result.success === false) {
52
+ throw new Error(result.error || 'Unknown error');
53
+ }
54
+ return result;
55
+ }
56
+ });
57
+ const ttsListVoicesTool = tool({
58
+ description: '列出可用的音色',
59
+ args: {
60
+ provider: tool.schema.string().optional().describe('TTS 提供商名称')
61
+ },
62
+ execute: async (args) => {
63
+ const result = await handleToolCall('tts_list_voices', args);
64
+ if (result.success === false) {
65
+ throw new Error(result.error || 'Unknown error');
66
+ }
67
+ return result;
68
+ }
69
+ });
70
+ const ttsListProvidersTool = tool({
71
+ description: '列出所有已注册的 TTS 提供商',
72
+ args: {},
73
+ execute: async () => {
74
+ const result = await handleToolCall('tts_list_providers');
75
+ if (result.success === false) {
76
+ throw new Error(result.error || 'Unknown error');
77
+ }
78
+ return result;
79
+ }
80
+ });
81
+ const ttsStatusTool = tool({
82
+ description: '获取当前 TTS 播放状态',
83
+ args: {},
84
+ execute: async () => {
85
+ const result = await handleToolCall('tts_status');
86
+ if (result.success === false) {
87
+ throw new Error(result.error || 'Unknown error');
88
+ }
89
+ return result;
90
+ }
91
+ });
92
+ const ttsStreamSpeakTool = tool({
93
+ description: '启动流式朗读(豆包模式),订阅AI回复并边生成边朗读',
94
+ args: {
95
+ text: tool.schema.string().optional().describe('初始文本(可选)'),
96
+ voice: tool.schema.string().optional().describe('音色ID'),
97
+ model: tool.schema.enum(['sync', 'async', 'stream']).optional().describe('合成模式')
98
+ },
99
+ execute: async (args) => {
100
+ const result = await handleToolCall('tts_stream_speak', args);
101
+ if (result.success === false) {
102
+ throw new Error(result.error || 'Unknown error');
103
+ }
104
+ return result;
105
+ }
106
+ });
107
+ const ttsStreamStopTool = tool({
108
+ description: '停止当前流式朗读',
109
+ args: {},
110
+ execute: async () => {
111
+ const result = await handleToolCall('tts_stream_stop');
112
+ if (result.success === false) {
113
+ throw new Error(result.error || 'Unknown error');
114
+ }
115
+ return result;
116
+ }
117
+ });
118
+ const ttsStreamStatusTool = tool({
119
+ description: '获取当前流式朗读状态',
120
+ args: {},
121
+ execute: async () => {
122
+ const result = await handleToolCall('tts_stream_status');
123
+ if (result.success === false) {
124
+ throw new Error(result.error || 'Unknown error');
125
+ }
126
+ return typeof result === 'string' ? result : JSON.stringify(result);
127
+ }
128
+ });
129
+ const OcosayPlugin = async (_input, _options) => {
130
+ console.info(`${pluginName}: initializing...`);
131
+ await initialize({
132
+ autoRead: false
133
+ });
134
+ return {
135
+ tool: {
136
+ tts_speak: ttsSpeakTool,
137
+ tts_stop: ttsStopTool,
138
+ tts_pause: ttsPauseTool,
139
+ tts_resume: ttsResumeTool,
140
+ tts_list_voices: ttsListVoicesTool,
141
+ tts_list_providers: ttsListProvidersTool,
142
+ tts_status: ttsStatusTool,
143
+ tts_stream_speak: ttsStreamSpeakTool,
144
+ tts_stream_stop: ttsStreamStopTool,
145
+ tts_stream_status: ttsStreamStatusTool
146
+ },
147
+ config: async () => { }
148
+ };
149
+ };
150
+ export default OcosayPlugin;
151
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * TTS Provider Base Class and Registry
3
+ * Provider 基类和注册机制
4
+ */
5
+ import { TTSProvider, Voice, TTSCapabilities, SpeakOptions, AudioResult } from '../core/types';
6
+ /**
7
+ * 注册 TTS Provider
8
+ */
9
+ export declare function registerProvider(name: string, provider: TTSProvider): void;
10
+ /**
11
+ * 获取 TTS Provider
12
+ */
13
+ export declare function getProvider(name: string): TTSProvider;
14
+ /**
15
+ * 获取所有已注册的 Provider 名称
16
+ */
17
+ export declare function listProviders(): string[];
18
+ /**
19
+ * 检查 Provider 是否已注册
20
+ */
21
+ export declare function hasProvider(name: string): boolean;
22
+ /**
23
+ * 注销 Provider
24
+ */
25
+ export declare function unregisterProvider(name: string): boolean;
26
+ /**
27
+ * Provider 抽象基类,提供通用实现
28
+ */
29
+ export declare abstract class BaseTTSProvider implements TTSProvider {
30
+ abstract name: string;
31
+ abstract capabilities: TTSCapabilities;
32
+ protected apiKey?: string;
33
+ protected defaultVoice?: string;
34
+ protected defaultModel: 'sync' | 'async' | 'stream';
35
+ initialize(): Promise<void>;
36
+ destroy(): Promise<void>;
37
+ /**
38
+ * 通用 speak 实现,处理通用逻辑
39
+ */
40
+ speak(text: string, options?: SpeakOptions): Promise<AudioResult>;
41
+ /**
42
+ * 子类实现的实际 speak 逻辑
43
+ */
44
+ protected abstract doSpeak(text: string, voice: string | undefined, model: 'sync' | 'async' | 'stream', options?: SpeakOptions): Promise<AudioResult>;
45
+ pause(): Promise<void>;
46
+ resume(): Promise<void>;
47
+ stop(): Promise<void>;
48
+ listVoices(): Promise<Voice[]>;
49
+ getCapabilities(): TTSCapabilities;
50
+ /**
51
+ * 验证 API Key
52
+ */
53
+ protected validateApiKey(): void;
54
+ }
55
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAA0B,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAKtH;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,IAAI,CAS1E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAUrD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;GAEG;AACH,8BAAsB,eAAgB,YAAW,WAAW;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAA;IAEtC,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC/B,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAW;IAExD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;OAEG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAevE;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,OAAO,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,EAClC,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC;IAEvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAQvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKf,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAKpC,eAAe,IAAI,eAAe;IAIlC;;OAEG;IACH,SAAS,CAAC,cAAc,IAAI,IAAI;CASjC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * TTS Provider Base Class and Registry
3
+ * Provider 基类和注册机制
4
+ */
5
+ import { TTSError, TTSErrorCode } from '../core/types';
6
+ // Provider 注册表
7
+ const providers = new Map();
8
+ /**
9
+ * 注册 TTS Provider
10
+ */
11
+ export function registerProvider(name, provider) {
12
+ if (providers.has(name)) {
13
+ throw new TTSError(`Provider "${name}" is already registered`, TTSErrorCode.UNKNOWN, 'system');
14
+ }
15
+ providers.set(name, provider);
16
+ }
17
+ /**
18
+ * 获取 TTS Provider
19
+ */
20
+ export function getProvider(name) {
21
+ const provider = providers.get(name);
22
+ if (!provider) {
23
+ throw new TTSError(`TTS Provider "${name}" not found`, TTSErrorCode.UNKNOWN, 'system');
24
+ }
25
+ return provider;
26
+ }
27
+ /**
28
+ * 获取所有已注册的 Provider 名称
29
+ */
30
+ export function listProviders() {
31
+ return Array.from(providers.keys());
32
+ }
33
+ /**
34
+ * 检查 Provider 是否已注册
35
+ */
36
+ export function hasProvider(name) {
37
+ return providers.has(name);
38
+ }
39
+ /**
40
+ * 注销 Provider
41
+ */
42
+ export function unregisterProvider(name) {
43
+ return providers.delete(name);
44
+ }
45
+ /**
46
+ * Provider 抽象基类,提供通用实现
47
+ */
48
+ export class BaseTTSProvider {
49
+ apiKey;
50
+ defaultVoice;
51
+ defaultModel = 'stream';
52
+ async initialize() {
53
+ // 子类可override
54
+ }
55
+ async destroy() {
56
+ // 子类可override
57
+ }
58
+ /**
59
+ * 通用 speak 实现,处理通用逻辑
60
+ */
61
+ async speak(text, options) {
62
+ if (!text || text.trim().length === 0) {
63
+ throw new TTSError('Text cannot be empty', TTSErrorCode.INVALID_PARAMS, this.name);
64
+ }
65
+ const voice = options?.voice || this.defaultVoice;
66
+ const model = options?.model || this.defaultModel;
67
+ return this.doSpeak(text, voice, model, options);
68
+ }
69
+ pause() {
70
+ throw new TTSError('Pause is not supported by this provider', TTSErrorCode.UNKNOWN, this.name);
71
+ }
72
+ resume() {
73
+ throw new TTSError('Resume is not supported by this provider', TTSErrorCode.UNKNOWN, this.name);
74
+ }
75
+ stop() {
76
+ // 默认空实现
77
+ return Promise.resolve();
78
+ }
79
+ async listVoices() {
80
+ // 默认返回空数组,子类可override
81
+ return [];
82
+ }
83
+ getCapabilities() {
84
+ return this.capabilities;
85
+ }
86
+ /**
87
+ * 验证 API Key
88
+ */
89
+ validateApiKey() {
90
+ if (!this.apiKey) {
91
+ throw new TTSError(`API key is required for provider "${this.name}"`, TTSErrorCode.AUTH, this.name);
92
+ }
93
+ }
94
+ }
95
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/providers/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * MiniMax TTS Provider
3
+ * 支持 T2A v2 (同步/流式HTTP)、T2A Async v2 (异步HTTP轮询)
4
+ * 端点可配置: baseURL (默认 https://api.minimaxi.com)
5
+ */
6
+ import { BaseTTSProvider } from './base';
7
+ import { AudioResult, Voice, SpeakOptions } from '../core/types';
8
+ export interface MiniMaxConfig {
9
+ apiKey: string;
10
+ baseURL?: string;
11
+ voiceId?: string;
12
+ model?: 'sync' | 'async' | 'stream';
13
+ ttsModel?: string;
14
+ audioFormat?: 'mp3' | 'wav' | 'flac';
15
+ speed?: number;
16
+ volume?: number;
17
+ pitch?: number;
18
+ groupId?: string;
19
+ }
20
+ /**
21
+ * MiniMax TTS Provider
22
+ * 官网: https://www.minimax.io/
23
+ * API文档: https://www.minimaxi.com/document/T2A
24
+ */
25
+ export declare class MiniMaxProvider extends BaseTTSProvider {
26
+ name: string;
27
+ capabilities: {
28
+ readonly speak: true;
29
+ readonly stream: true;
30
+ readonly sync: true;
31
+ readonly async: true;
32
+ readonly voiceList: true;
33
+ readonly voiceClone: true;
34
+ };
35
+ private config;
36
+ private httpClient;
37
+ private wsConnection?;
38
+ private currentAudioData;
39
+ private audioFormat;
40
+ constructor(config: MiniMaxConfig);
41
+ initialize(): Promise<void>;
42
+ destroy(): Promise<void>;
43
+ protected doSpeak(text: string, voice: string | undefined, model: 'sync' | 'async' | 'stream', options?: SpeakOptions): Promise<AudioResult>;
44
+ /**
45
+ * 流式合成 (HTTP) - T2A v2 with stream: true
46
+ */
47
+ private streamingSpeak;
48
+ /**
49
+ * 同步合成 (HTTP) - T2A v2
50
+ * API: POST https://api.minimax.io/v1/t2a_v2
51
+ */
52
+ private syncSpeak;
53
+ /**
54
+ * 异步合成 (轮询) - T2A Async v2
55
+ */
56
+ private asyncSpeak;
57
+ /**
58
+ * 音色克隆 - 使用参考音频克隆声音
59
+ */
60
+ voiceClone(audioUrl: string, text: string, voice?: string): Promise<AudioResult>;
61
+ /**
62
+ * 获取音色列表
63
+ */
64
+ listVoices(): Promise<Voice[]>;
65
+ /**
66
+ * 错误映射
67
+ */
68
+ private mapError;
69
+ /**
70
+ * 延迟辅助函数
71
+ */
72
+ private delay;
73
+ /**
74
+ * 估算音频时长
75
+ * 基于 32kbps MP3 估算
76
+ */
77
+ private estimateDuration;
78
+ }
79
+ /**
80
+ * MiniMax 预定义音色列表
81
+ * 官方音色ID参考
82
+ */
83
+ export declare const MINIMAX_VOICES: Voice[];
84
+ //# sourceMappingURL=minimax.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimax.d.ts","sourceRoot":"","sources":["../../src/providers/minimax.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAGL,WAAW,EACX,KAAK,EACL,YAAY,EACb,MAAM,eAAe,CAAA;AAItB,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAA;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,eAAe;IAClD,IAAI,SAAY;IAChB,YAAY;;;;;;;MAOF;IAEV,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAAe;IACjC,OAAO,CAAC,YAAY,CAAC,CAAW;IAChC,OAAO,CAAC,gBAAgB,CAAe;IACvC,OAAO,CAAC,WAAW,CAAgC;gBAEvC,MAAM,EAAE,aAAa;IAkB3B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;cAOd,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,EAClC,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,WAAW,CAAC;IAevB;;OAEG;YACW,cAAc;IA2F5B;;;OAGG;YACW,SAAS;IAqEvB;;OAEG;YACW,UAAU;IA8GxB;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA2BtF;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAsBpC;;OAEG;IACH,OAAO,CAAC,QAAQ;IAkChB;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;;OAGG;IACH,OAAO,CAAC,gBAAgB;CAGzB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,EAqBjC,CAAA"}