@coeiro-operator/audio 1.0.1 → 1.0.3
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/LICENSE +21 -0
- package/dist/audio-player.d.ts +134 -0
- package/dist/audio-player.d.ts.map +1 -0
- package/dist/audio-player.js +707 -0
- package/dist/audio-player.js.map +1 -0
- package/dist/audio-stream-controller.d.ts +52 -0
- package/dist/audio-stream-controller.d.ts.map +1 -0
- package/dist/audio-stream-controller.js +121 -0
- package/dist/audio-stream-controller.js.map +1 -0
- package/dist/audio-synthesizer.d.ts +86 -0
- package/dist/audio-synthesizer.d.ts.map +1 -0
- package/dist/audio-synthesizer.js +437 -0
- package/dist/audio-synthesizer.js.map +1 -0
- package/dist/chunk-generation-manager.d.ts +77 -0
- package/dist/chunk-generation-manager.d.ts.map +1 -0
- package/dist/chunk-generation-manager.js +178 -0
- package/dist/chunk-generation-manager.js.map +1 -0
- package/dist/constants.d.ts +180 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +219 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +194 -0
- package/dist/index.js.map +1 -0
- package/dist/speech-queue.d.ts +52 -0
- package/dist/speech-queue.d.ts.map +1 -0
- package/dist/speech-queue.js +143 -0
- package/dist/speech-queue.js.map +1 -0
- package/dist/synthesis-processor.d.ts +39 -0
- package/dist/synthesis-processor.d.ts.map +1 -0
- package/dist/synthesis-processor.js +131 -0
- package/dist/synthesis-processor.js.map +1 -0
- package/dist/test-helpers.d.ts +19 -0
- package/dist/test-helpers.d.ts.map +1 -0
- package/dist/test-helpers.js +167 -0
- package/dist/test-helpers.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/voice-resolver.d.ts +25 -0
- package/dist/voice-resolver.d.ts.map +1 -0
- package/dist/voice-resolver.js +141 -0
- package/dist/voice-resolver.js.map +1 -0
- package/package.json +16 -13
package/dist/index.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index-new.ts: 簡素化されたSayCoeiroinkクラス
|
|
3
|
+
* 音声合成ライブラリのファサード
|
|
4
|
+
*/
|
|
5
|
+
import { OperatorManager } from '@coeiro-operator/core';
|
|
6
|
+
import { SpeechQueue } from './speech-queue.js';
|
|
7
|
+
import { AudioPlayer } from './audio-player.js';
|
|
8
|
+
import { AudioSynthesizer } from './audio-synthesizer.js';
|
|
9
|
+
import { VoiceResolver } from './voice-resolver.js';
|
|
10
|
+
import { SynthesisProcessor } from './synthesis-processor.js';
|
|
11
|
+
import { logger } from '@coeiro-operator/common';
|
|
12
|
+
export class SayCoeiroink {
|
|
13
|
+
configManager;
|
|
14
|
+
config;
|
|
15
|
+
operatorManager;
|
|
16
|
+
speechQueue = null;
|
|
17
|
+
audioPlayer = null;
|
|
18
|
+
audioSynthesizer = null;
|
|
19
|
+
voiceResolver = null;
|
|
20
|
+
synthesisProcessor = null;
|
|
21
|
+
constructor(configManager) {
|
|
22
|
+
this.configManager = configManager;
|
|
23
|
+
this.config = {};
|
|
24
|
+
this.operatorManager = new OperatorManager();
|
|
25
|
+
}
|
|
26
|
+
async initialize() {
|
|
27
|
+
try {
|
|
28
|
+
// ConfigManagerから完全な設定を取得
|
|
29
|
+
this.config = await this.configManager.getFullConfig();
|
|
30
|
+
// 基本コンポーネントを初期化
|
|
31
|
+
this.audioPlayer = new AudioPlayer(this.config);
|
|
32
|
+
this.audioSynthesizer = new AudioSynthesizer(this.config);
|
|
33
|
+
// 音声解決と合成処理を初期化
|
|
34
|
+
this.voiceResolver = new VoiceResolver(this.configManager, this.operatorManager, this.audioSynthesizer);
|
|
35
|
+
this.synthesisProcessor = new SynthesisProcessor(this.config, this.audioPlayer, this.audioSynthesizer, this.voiceResolver);
|
|
36
|
+
// SpeechQueueを初期化
|
|
37
|
+
this.speechQueue = new SpeechQueue(async (task) => {
|
|
38
|
+
await this.synthesisProcessor.process(task.text, task.options);
|
|
39
|
+
});
|
|
40
|
+
await this.operatorManager.initialize();
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
throw new Error(`SayCoeiroink initialization failed: ${err.message}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async buildDynamicConfig() {
|
|
47
|
+
try {
|
|
48
|
+
await this.configManager.buildDynamicConfig();
|
|
49
|
+
await this.operatorManager.buildDynamicConfig();
|
|
50
|
+
// 設定を再取得して更新
|
|
51
|
+
this.config = await this.configManager.getFullConfig();
|
|
52
|
+
// 依存コンポーネントも更新
|
|
53
|
+
if (this.synthesisProcessor) {
|
|
54
|
+
this.synthesisProcessor.config = this.config;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
throw new Error(`buildDynamicConfig failed: ${err.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ========================================================================
|
|
62
|
+
// 主要API
|
|
63
|
+
// ========================================================================
|
|
64
|
+
/**
|
|
65
|
+
* オーディオドライバーのウォームアップ
|
|
66
|
+
*/
|
|
67
|
+
async warmup() {
|
|
68
|
+
if (!this.audioPlayer) {
|
|
69
|
+
throw new Error('AudioPlayer is not initialized. Call initialize() first.');
|
|
70
|
+
}
|
|
71
|
+
await this.audioPlayer.warmupAudioDriver();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* 音声合成タスクをキューに追加
|
|
75
|
+
*/
|
|
76
|
+
synthesize(text, options = {}) {
|
|
77
|
+
if (!this.speechQueue) {
|
|
78
|
+
throw new Error('SpeechQueue is not initialized. Call initialize() first.');
|
|
79
|
+
}
|
|
80
|
+
return this.speechQueue.enqueue(text, options);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* キューに入っているすべてのタスクの完了を待つ
|
|
84
|
+
* エラーが発生した場合は最初のエラーを投げる
|
|
85
|
+
*/
|
|
86
|
+
async waitCompletion() {
|
|
87
|
+
if (!this.speechQueue) {
|
|
88
|
+
throw new Error('SpeechQueue is not initialized. Call initialize() first.');
|
|
89
|
+
}
|
|
90
|
+
const result = await this.speechQueue.waitForAllTasks();
|
|
91
|
+
// エラーがある場合は最初のエラーを投げる
|
|
92
|
+
if (result.errors.length > 0) {
|
|
93
|
+
const firstError = result.errors[0];
|
|
94
|
+
logger.warn(`音声処理中に${result.errors.length}件のエラーが発生しました`);
|
|
95
|
+
throw firstError.error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// ========================================================================
|
|
99
|
+
// ユーティリティメソッド
|
|
100
|
+
// ========================================================================
|
|
101
|
+
/**
|
|
102
|
+
* 利用可能な音声をリスト表示
|
|
103
|
+
*/
|
|
104
|
+
async listVoices() {
|
|
105
|
+
if (!this.audioSynthesizer) {
|
|
106
|
+
throw new Error('AudioSynthesizer is not initialized. Call initialize() first.');
|
|
107
|
+
}
|
|
108
|
+
await this.audioSynthesizer.listVoices();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* キューの状態を取得
|
|
112
|
+
*/
|
|
113
|
+
getSpeechQueueStatus() {
|
|
114
|
+
if (!this.speechQueue) {
|
|
115
|
+
throw new Error('SpeechQueue is not initialized. Call initialize() first.');
|
|
116
|
+
}
|
|
117
|
+
return this.speechQueue.getStatus();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* キューをクリア
|
|
121
|
+
*/
|
|
122
|
+
clearSpeechQueue() {
|
|
123
|
+
if (!this.speechQueue) {
|
|
124
|
+
throw new Error('SpeechQueue is not initialized. Call initialize() first.');
|
|
125
|
+
}
|
|
126
|
+
this.speechQueue.clear();
|
|
127
|
+
}
|
|
128
|
+
// ========================================================================
|
|
129
|
+
// 並行生成制御
|
|
130
|
+
// ========================================================================
|
|
131
|
+
/**
|
|
132
|
+
* 並行生成の有効/無効を設定
|
|
133
|
+
*/
|
|
134
|
+
setParallelGenerationEnabled(enabled) {
|
|
135
|
+
if (!this.audioSynthesizer) {
|
|
136
|
+
throw new Error('AudioSynthesizer is not initialized. Call initialize() first.');
|
|
137
|
+
}
|
|
138
|
+
this.audioSynthesizer.setParallelGenerationEnabled(enabled);
|
|
139
|
+
logger.info(`並行生成設定変更: ${enabled ? '有効' : '無効'}`);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* AudioStreamControllerのオプションを更新
|
|
143
|
+
*/
|
|
144
|
+
updateStreamControllerOptions(options) {
|
|
145
|
+
if (!this.audioSynthesizer) {
|
|
146
|
+
throw new Error('AudioSynthesizer is not initialized. Call initialize() first.');
|
|
147
|
+
}
|
|
148
|
+
this.audioSynthesizer.updateStreamControllerOptions(options);
|
|
149
|
+
logger.info('AudioStreamController設定更新', options);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 並行生成の統計情報を取得
|
|
153
|
+
*/
|
|
154
|
+
getGenerationStats() {
|
|
155
|
+
if (!this.audioSynthesizer) {
|
|
156
|
+
throw new Error('AudioSynthesizer is not initialized. Call initialize() first.');
|
|
157
|
+
}
|
|
158
|
+
return this.audioSynthesizer.getGenerationStats();
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* ストリーム制御オプションを取得
|
|
162
|
+
*/
|
|
163
|
+
getStreamControllerOptions() {
|
|
164
|
+
if (!this.audioSynthesizer) {
|
|
165
|
+
throw new Error('AudioSynthesizer is not initialized. Call initialize() first.');
|
|
166
|
+
}
|
|
167
|
+
return this.audioSynthesizer.getStreamControllerOptions();
|
|
168
|
+
}
|
|
169
|
+
// ========================================================================
|
|
170
|
+
// リソース管理
|
|
171
|
+
// ========================================================================
|
|
172
|
+
/**
|
|
173
|
+
* リソースのクリーンアップ
|
|
174
|
+
*/
|
|
175
|
+
async cleanup() {
|
|
176
|
+
logger.debug('SayCoeiroink cleanup開始');
|
|
177
|
+
try {
|
|
178
|
+
if (this.speechQueue) {
|
|
179
|
+
this.speechQueue.clear();
|
|
180
|
+
}
|
|
181
|
+
if (this.audioPlayer) {
|
|
182
|
+
await this.audioPlayer.cleanup();
|
|
183
|
+
}
|
|
184
|
+
logger.info('SayCoeiroink cleanup完了');
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
logger.warn(`SayCoeiroink cleanup warning: ${error.message}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// デフォルトエクスポート
|
|
192
|
+
export default SayCoeiroink;
|
|
193
|
+
export { BUFFER_SIZES } from './constants.js';
|
|
194
|
+
//# 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,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/say/speech-queue.ts: 音声合成キュー管理
|
|
3
|
+
* 非同期音声タスクのキューイングと順次処理を担当
|
|
4
|
+
*/
|
|
5
|
+
import type { SpeechTask, SynthesizeOptions, SynthesizeResult } from './types.js';
|
|
6
|
+
export declare class SpeechQueue {
|
|
7
|
+
private processCallback;
|
|
8
|
+
private speechQueue;
|
|
9
|
+
private isProcessing;
|
|
10
|
+
private taskIdCounter;
|
|
11
|
+
private errors;
|
|
12
|
+
constructor(processCallback: (task: SpeechTask) => Promise<void>);
|
|
13
|
+
/**
|
|
14
|
+
* 音声タスクをキューに追加(同期的)
|
|
15
|
+
*/
|
|
16
|
+
enqueue(text: string, options?: SynthesizeOptions): SynthesizeResult;
|
|
17
|
+
/**
|
|
18
|
+
* 音声タスクをキューに追加して完了を待つ
|
|
19
|
+
*/
|
|
20
|
+
enqueueAndWait(text: string, options?: SynthesizeOptions): Promise<SynthesizeResult>;
|
|
21
|
+
/**
|
|
22
|
+
* キューに入っているすべてのタスクの完了を待つ
|
|
23
|
+
* @returns エラーが発生した場合はエラーリストを含む結果を返す
|
|
24
|
+
*/
|
|
25
|
+
waitForAllTasks(): Promise<{
|
|
26
|
+
errors: Array<{
|
|
27
|
+
taskId: number;
|
|
28
|
+
error: Error;
|
|
29
|
+
}>;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* キューの処理を開始
|
|
33
|
+
*/
|
|
34
|
+
private processQueue;
|
|
35
|
+
/**
|
|
36
|
+
* タスクの処理を実行
|
|
37
|
+
*/
|
|
38
|
+
private processTask;
|
|
39
|
+
/**
|
|
40
|
+
* キューの状態を取得
|
|
41
|
+
*/
|
|
42
|
+
getStatus(): {
|
|
43
|
+
queueLength: number;
|
|
44
|
+
isProcessing: boolean;
|
|
45
|
+
nextTaskId: number | null;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* キューをクリア
|
|
49
|
+
*/
|
|
50
|
+
clear(): void;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=speech-queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speech-queue.d.ts","sourceRoot":"","sources":["../src/speech-queue.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAkB,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGlG,qBAAa,WAAW;IAOpB,OAAO,CAAC,eAAe;IANzB,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,MAAM,CAA6C;gBAGjD,eAAe,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC;IAG9D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB;IAuBxE;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0B9F;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,KAAK,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,KAAK,CAAA;SAAC,CAAC,CAAA;KAAE,CAAC;IAiBnF;;OAEG;YACW,YAAY;IA0C1B;;OAEG;YACW,WAAW;IAKzB;;OAEG;IACH,SAAS;;;;;IAQT;;OAEG;IACH,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/say/speech-queue.ts: 音声合成キュー管理
|
|
3
|
+
* 非同期音声タスクのキューイングと順次処理を担当
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from '@coeiro-operator/common';
|
|
6
|
+
export class SpeechQueue {
|
|
7
|
+
processCallback;
|
|
8
|
+
speechQueue = [];
|
|
9
|
+
isProcessing = false;
|
|
10
|
+
taskIdCounter = Date.now();
|
|
11
|
+
errors = [];
|
|
12
|
+
constructor(processCallback) {
|
|
13
|
+
this.processCallback = processCallback;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 音声タスクをキューに追加(同期的)
|
|
17
|
+
*/
|
|
18
|
+
enqueue(text, options = {}) {
|
|
19
|
+
const taskId = this.taskIdCounter++;
|
|
20
|
+
const task = {
|
|
21
|
+
id: taskId,
|
|
22
|
+
type: 'speech',
|
|
23
|
+
text,
|
|
24
|
+
options,
|
|
25
|
+
timestamp: Date.now(),
|
|
26
|
+
};
|
|
27
|
+
this.speechQueue.push(task);
|
|
28
|
+
// キュー処理を開始
|
|
29
|
+
setTimeout(() => this.processQueue(), 0);
|
|
30
|
+
return {
|
|
31
|
+
success: true,
|
|
32
|
+
taskId,
|
|
33
|
+
queueLength: this.speechQueue.length,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 音声タスクをキューに追加して完了を待つ
|
|
38
|
+
*/
|
|
39
|
+
async enqueueAndWait(text, options = {}) {
|
|
40
|
+
const taskId = this.taskIdCounter++;
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const task = {
|
|
43
|
+
id: taskId,
|
|
44
|
+
type: 'speech',
|
|
45
|
+
text,
|
|
46
|
+
options,
|
|
47
|
+
timestamp: Date.now(),
|
|
48
|
+
resolve: () => resolve({
|
|
49
|
+
success: true,
|
|
50
|
+
taskId,
|
|
51
|
+
queueLength: this.speechQueue.length,
|
|
52
|
+
}),
|
|
53
|
+
reject,
|
|
54
|
+
};
|
|
55
|
+
this.speechQueue.push(task);
|
|
56
|
+
// キュー処理を開始
|
|
57
|
+
setTimeout(() => this.processQueue(), 0);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* キューに入っているすべてのタスクの完了を待つ
|
|
62
|
+
* @returns エラーが発生した場合はエラーリストを含む結果を返す
|
|
63
|
+
*/
|
|
64
|
+
async waitForAllTasks() {
|
|
65
|
+
return new Promise((resolve) => {
|
|
66
|
+
const checkQueue = () => {
|
|
67
|
+
if (this.speechQueue.length === 0 && !this.isProcessing) {
|
|
68
|
+
// エラーリストを返してクリア
|
|
69
|
+
const errors = [...this.errors];
|
|
70
|
+
this.errors = [];
|
|
71
|
+
resolve({ errors });
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
setTimeout(checkQueue, 100);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
checkQueue();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* キューの処理を開始
|
|
82
|
+
*/
|
|
83
|
+
async processQueue() {
|
|
84
|
+
if (this.isProcessing) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (this.speechQueue.length === 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.isProcessing = true;
|
|
91
|
+
while (this.speechQueue.length > 0) {
|
|
92
|
+
const task = this.speechQueue.shift();
|
|
93
|
+
if (!task)
|
|
94
|
+
break;
|
|
95
|
+
try {
|
|
96
|
+
await this.processTask(task);
|
|
97
|
+
logger.verbose(`音声タスク完了: ${task.id} (${task.type})`);
|
|
98
|
+
// CLI用完了通知
|
|
99
|
+
if (task.resolve) {
|
|
100
|
+
task.resolve();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
logger.error(`音声タスクエラー: ${task.id} (${task.type}), ${error.message}`);
|
|
105
|
+
// エラーを保存
|
|
106
|
+
this.errors.push({
|
|
107
|
+
taskId: task.id,
|
|
108
|
+
error: error
|
|
109
|
+
});
|
|
110
|
+
// CLI用エラー通知
|
|
111
|
+
if (task.reject) {
|
|
112
|
+
task.reject(error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
this.isProcessing = false;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* タスクの処理を実行
|
|
120
|
+
*/
|
|
121
|
+
async processTask(task) {
|
|
122
|
+
// 音声合成タスクの処理
|
|
123
|
+
await this.processCallback(task);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* キューの状態を取得
|
|
127
|
+
*/
|
|
128
|
+
getStatus() {
|
|
129
|
+
return {
|
|
130
|
+
queueLength: this.speechQueue.length,
|
|
131
|
+
isProcessing: this.isProcessing,
|
|
132
|
+
nextTaskId: this.speechQueue[0]?.id || null,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* キューをクリア
|
|
137
|
+
*/
|
|
138
|
+
clear() {
|
|
139
|
+
this.speechQueue = [];
|
|
140
|
+
this.isProcessing = false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=speech-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speech-queue.js","sourceRoot":"","sources":["../src/speech-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* synthesis-processor.ts: 音声合成処理を担当
|
|
3
|
+
*/
|
|
4
|
+
import { AudioPlayer } from './audio-player.js';
|
|
5
|
+
import { AudioSynthesizer } from './audio-synthesizer.js';
|
|
6
|
+
import { VoiceResolver } from './voice-resolver.js';
|
|
7
|
+
import type { Config, SynthesizeOptions, SynthesizeResult } from './types.js';
|
|
8
|
+
export declare class SynthesisProcessor {
|
|
9
|
+
private config;
|
|
10
|
+
private audioPlayer;
|
|
11
|
+
private audioSynthesizer;
|
|
12
|
+
private voiceResolver;
|
|
13
|
+
constructor(config: Config, audioPlayer: AudioPlayer, audioSynthesizer: AudioSynthesizer, voiceResolver: VoiceResolver);
|
|
14
|
+
/**
|
|
15
|
+
* AudioPlayerの初期化と設定
|
|
16
|
+
*/
|
|
17
|
+
initializeAudioPlayer(): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* 音声合成処理のメインメソッド
|
|
20
|
+
*/
|
|
21
|
+
process(text: string, options?: SynthesizeOptions): Promise<SynthesizeResult>;
|
|
22
|
+
/**
|
|
23
|
+
* オプション解析
|
|
24
|
+
*/
|
|
25
|
+
private resolveOptions;
|
|
26
|
+
/**
|
|
27
|
+
* サーバー接続確認
|
|
28
|
+
*/
|
|
29
|
+
private validateServerConnection;
|
|
30
|
+
/**
|
|
31
|
+
* ファイル出力処理
|
|
32
|
+
*/
|
|
33
|
+
private processFileOutput;
|
|
34
|
+
/**
|
|
35
|
+
* ストリーミング再生処理
|
|
36
|
+
*/
|
|
37
|
+
private processStreamingOutput;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=synthesis-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synthesis-processor.d.ts","sourceRoot":"","sources":["../src/synthesis-processor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,KAAK,EACV,MAAM,EAEN,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,aAAa;gBAHb,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,aAAa,EAAE,aAAa;IAGtC;;OAEG;IACG,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC;IAyB/C;;OAEG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;IAwC5B;;OAEG;IACH,OAAO,CAAC,cAAc;IA+BtB;;OAEG;YACW,wBAAwB;IAStC;;OAEG;YACW,iBAAiB;IAmC/B;;OAEG;YACW,sBAAsB;CA2BrC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* synthesis-processor.ts: 音声合成処理を担当
|
|
3
|
+
*/
|
|
4
|
+
import { logger } from '@coeiro-operator/common';
|
|
5
|
+
import { BUFFER_SIZES, FILTER_SETTINGS } from './constants.js';
|
|
6
|
+
export class SynthesisProcessor {
|
|
7
|
+
config;
|
|
8
|
+
audioPlayer;
|
|
9
|
+
audioSynthesizer;
|
|
10
|
+
voiceResolver;
|
|
11
|
+
constructor(config, audioPlayer, audioSynthesizer, voiceResolver) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.audioPlayer = audioPlayer;
|
|
14
|
+
this.audioSynthesizer = audioSynthesizer;
|
|
15
|
+
this.voiceResolver = voiceResolver;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* AudioPlayerの初期化と設定
|
|
19
|
+
*/
|
|
20
|
+
async initializeAudioPlayer() {
|
|
21
|
+
// プリセットベースの設定がaudio-player.ts内で適用されるため、
|
|
22
|
+
// 個別設定の上書きのみここで行う
|
|
23
|
+
const audioConfig = this.config.audio;
|
|
24
|
+
if (audioConfig?.processing?.synthesisRate) {
|
|
25
|
+
this.audioPlayer.setSynthesisRate(audioConfig.processing.synthesisRate);
|
|
26
|
+
}
|
|
27
|
+
if (audioConfig?.processing?.playbackRate) {
|
|
28
|
+
this.audioPlayer.setPlaybackRate(audioConfig.processing.playbackRate);
|
|
29
|
+
}
|
|
30
|
+
if (audioConfig?.processing?.noiseReduction !== undefined) {
|
|
31
|
+
this.audioPlayer.setNoiseReduction(audioConfig.processing.noiseReduction);
|
|
32
|
+
}
|
|
33
|
+
if (audioConfig?.processing?.lowpassFilter !== undefined) {
|
|
34
|
+
const cutoff = audioConfig.processing.lowpassCutoff || FILTER_SETTINGS.LOWPASS_CUTOFF;
|
|
35
|
+
this.audioPlayer.setLowpassFilter(audioConfig.processing.lowpassFilter, cutoff);
|
|
36
|
+
}
|
|
37
|
+
return await this.audioPlayer.initialize();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 音声合成処理のメインメソッド
|
|
41
|
+
*/
|
|
42
|
+
async process(text, options = {}) {
|
|
43
|
+
logger.info(`音声合成開始: テキスト="${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"`);
|
|
44
|
+
// オプション解析
|
|
45
|
+
const resolvedOptions = this.resolveOptions(options);
|
|
46
|
+
// サーバー接続確認を最初に行う
|
|
47
|
+
await this.validateServerConnection();
|
|
48
|
+
// 音声設定の解決
|
|
49
|
+
const voiceConfig = await this.voiceResolver.resolveVoiceConfig(resolvedOptions.voice, resolvedOptions.style || undefined, resolvedOptions.allowFallback);
|
|
50
|
+
const speed = this.audioSynthesizer.convertRateToSpeed(resolvedOptions.rate);
|
|
51
|
+
// 出力モードに応じた処理
|
|
52
|
+
if (resolvedOptions.outputFile) {
|
|
53
|
+
return await this.processFileOutput(text, voiceConfig, speed, resolvedOptions.chunkMode, resolvedOptions.outputFile);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return await this.processStreamingOutput(text, voiceConfig, speed, resolvedOptions.chunkMode, resolvedOptions.bufferSize);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* オプション解析
|
|
61
|
+
*/
|
|
62
|
+
resolveOptions(options) {
|
|
63
|
+
const resolved = {
|
|
64
|
+
voice: options.voice || null,
|
|
65
|
+
rate: options.rate || this.config.operator.rate,
|
|
66
|
+
outputFile: options.outputFile || null,
|
|
67
|
+
style: options.style || null,
|
|
68
|
+
chunkMode: options.chunkMode || this.config.audio?.splitMode || 'punctuation',
|
|
69
|
+
bufferSize: options.bufferSize || this.config.audio?.bufferSize || BUFFER_SIZES.DEFAULT,
|
|
70
|
+
allowFallback: options.allowFallback ?? true,
|
|
71
|
+
};
|
|
72
|
+
logger.debug('=== SYNTHESIZE_TEXT_INTERNAL DEBUG ===');
|
|
73
|
+
logger.debug(`Resolved options:`);
|
|
74
|
+
logger.debug(` chunkMode: ${resolved.chunkMode} (from: ${options.chunkMode ? 'options' : 'config.audio.splitMode fallback'})`);
|
|
75
|
+
logger.debug(` config.audio.splitMode: ${this.config.audio?.splitMode || 'undefined'}`);
|
|
76
|
+
logger.debug(` bufferSize: ${resolved.bufferSize}`);
|
|
77
|
+
logger.debug(` allowFallback: ${resolved.allowFallback}`);
|
|
78
|
+
return resolved;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* サーバー接続確認
|
|
82
|
+
*/
|
|
83
|
+
async validateServerConnection() {
|
|
84
|
+
if (!(await this.audioSynthesizer.checkServerConnection())) {
|
|
85
|
+
const host = this.config.connection?.host || 'localhost';
|
|
86
|
+
const port = this.config.connection?.port || '50032';
|
|
87
|
+
logger.error(`COEIROINKサーバーに接続できません: http://${host}:${port}`);
|
|
88
|
+
throw new Error(`Cannot connect to COEIROINK server (http://${host}:${port})`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* ファイル出力処理
|
|
93
|
+
*/
|
|
94
|
+
async processFileOutput(text, voiceConfig, speed, chunkMode, outputFile) {
|
|
95
|
+
logger.info(`ファイル出力モード: ${outputFile}`);
|
|
96
|
+
// ストリーミング合成してファイルに保存
|
|
97
|
+
const audioChunks = [];
|
|
98
|
+
for await (const audioResult of this.audioSynthesizer.synthesizeStream(text, voiceConfig, speed, chunkMode)) {
|
|
99
|
+
audioChunks.push(audioResult.audioBuffer);
|
|
100
|
+
}
|
|
101
|
+
// 全チャンクを結合
|
|
102
|
+
const totalLength = audioChunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
|
|
103
|
+
const combinedBuffer = new ArrayBuffer(totalLength);
|
|
104
|
+
const view = new Uint8Array(combinedBuffer);
|
|
105
|
+
let offset = 0;
|
|
106
|
+
for (const chunk of audioChunks) {
|
|
107
|
+
view.set(new Uint8Array(chunk), offset);
|
|
108
|
+
offset += chunk.byteLength;
|
|
109
|
+
}
|
|
110
|
+
await this.audioPlayer.saveAudio(combinedBuffer, outputFile);
|
|
111
|
+
return { success: true, outputFile, mode: 'file' };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* ストリーミング再生処理
|
|
115
|
+
*/
|
|
116
|
+
async processStreamingOutput(text, voiceConfig, speed, chunkMode, bufferSize) {
|
|
117
|
+
logger.info('ストリーミング再生モード');
|
|
118
|
+
// 統一されたストリーミング再生
|
|
119
|
+
if (!(await this.initializeAudioPlayer())) {
|
|
120
|
+
logger.error('音声プレーヤーの初期化に失敗');
|
|
121
|
+
throw new Error('音声プレーヤーの初期化に失敗しました');
|
|
122
|
+
}
|
|
123
|
+
logger.info('音声ストリーミング再生開始...');
|
|
124
|
+
logger.debug(`About to call streamSynthesizeAndPlay with chunkMode: ${chunkMode}`);
|
|
125
|
+
// 真のストリーミング再生:ジェネレータを直接AudioPlayerに渡す
|
|
126
|
+
await this.audioPlayer.playStreamingAudio(this.audioSynthesizer.synthesizeStream(text, voiceConfig, speed, chunkMode), bufferSize);
|
|
127
|
+
logger.info('音声ストリーミング再生完了');
|
|
128
|
+
return { success: true, mode: 'streaming' };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=synthesis-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synthesis-processor.js","sourceRoot":"","sources":["../src/synthesis-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* テスト用ヘルパー関数とモックファクトリ
|
|
3
|
+
*/
|
|
4
|
+
import { ConfigManager } from '@coeiro-operator/core';
|
|
5
|
+
import type { Config } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Speakerモックインスタンスを作成
|
|
8
|
+
* Node.js StreamのWritableインターフェースを完全に実装
|
|
9
|
+
*/
|
|
10
|
+
export declare function createMockSpeakerInstance(): any;
|
|
11
|
+
/**
|
|
12
|
+
* エラーを発生させるSpeakerモックインスタンスを作成
|
|
13
|
+
*/
|
|
14
|
+
export declare function createErrorMockSpeakerInstance(): any;
|
|
15
|
+
/**
|
|
16
|
+
* テスト用のConfigManagerモックを作成
|
|
17
|
+
*/
|
|
18
|
+
export declare function createMockConfigManager(overrides?: Partial<Config>): ConfigManager;
|
|
19
|
+
//# sourceMappingURL=test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../src/test-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,yBAAyB,QAkDxC;AAED;;GAEG;AACH,wBAAgB,8BAA8B,QAkB7C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,OAAO,CAAC,MAAM,CAAM,GAAG,aAAa,CAoEtF"}
|