@kajidog/mcp-tts-voicevox
Version:
VOICEVOX integration for MCP - Text-to-Speech server using VOICEVOX engine
145 lines (144 loc) • 5.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.VoicevoxPlayer = void 0;
const queue_1 = require("./queue");
const error_1 = require("./error");
const api_1 = require("./api");
/**
* エラーハンドラープロキシ
* メソッドをエラーハンドリングで包む高階関数
*/
function withErrorHandling(method, errorMessage) {
return method().catch((error) => {
throw (0, error_1.handleError)(errorMessage, error);
});
}
/**
* VOICEVOX音声プレイヤークラス
* キュー管理システムを使用して音声の合成と再生を行う
*/
class VoicevoxPlayer {
/**
* コンストラクタ
* @param voicevoxUrl VOICEVOX Engine API URL
* @param prefetchSize 事前生成するアイテム数
*/
constructor(voicevoxUrl = "http://localhost:50021", prefetchSize = 2) {
// APIインスタンスを作成
const api = new api_1.VoicevoxApi(voicevoxUrl);
// キューマネージャーにAPIインスタンスを注入
this.queueManager = new queue_1.VoicevoxQueueManager(api, prefetchSize);
// デフォルトで再生を開始
this.queueManager.startPlayback();
// エラーイベントのログ記録
this.queueManager.addEventListener(queue_1.QueueEventType.ERROR, (_, item) => {
if (item) {
console.error(`音声合成エラー: ${item.text} (${item.error?.message || "不明なエラー"})`);
}
});
}
/**
* テキストをキューに追加
* @param text 合成するテキスト
* @param speaker 話者ID
*/
async enqueue(text, speaker = 1) {
return withErrorHandling(async () => {
await this.queueManager.enqueueText(text, speaker);
}, "テキストのキュー追加中にエラーが発生しました");
}
/**
* クエリを使ってキューに追加
* @param query 音声合成用クエリ
* @param speaker 話者ID
*/
async enqueueWithQuery(query, speaker = 1) {
return withErrorHandling(async () => {
await this.queueManager.enqueueQuery(query, speaker);
}, "クエリのキュー追加中にエラーが発生しました");
}
/**
* テキストから音声合成用クエリを生成
* キューマネージャーの内部機能を使用
* @param text 合成するテキスト
* @param speaker 話者ID
*/
async generateQuery(text, speaker = 1) {
return withErrorHandling(async () => {
// AudioGeneratorのgenerateQueryを直接呼び出す
return await this.queueManager
.getAudioGenerator()
.generateQuery(text, speaker);
}, "音声合成クエリの生成中にエラーが発生しました");
}
/**
* 音声合成用クエリから音声ファイルを生成
* 重複を避けるためにQueueManagerの機能に委譲
*
* @param query 音声合成用クエリ
* @param output 出力ファイルパスまたは出力ディレクトリ(省略時は一時ディレクトリに生成)
* @param speaker 話者ID
*/
async synthesizeToFile(query, output, speaker = 1) {
return withErrorHandling(async () => {
// クエリから音声を合成
const api = this.queueManager.getApi();
const audioData = await api.synthesize(query, speaker);
// ファイル保存処理をFileManagerに完全に委譲
const fileManager = this.queueManager.getFileManager();
// 出力パスが指定されていない場合は一時ファイル、指定されている場合は指定パスに保存
if (!output) {
return await fileManager.saveTempAudioFile(audioData);
}
else {
return await fileManager.saveAudioFile(audioData, output);
}
}, "音声ファイル生成中にエラーが発生しました");
}
/**
* 再生を開始
*/
startPlayback() {
this.queueManager.startPlayback();
}
/**
* 再生を一時停止
*/
pausePlayback() {
this.queueManager.pausePlayback();
}
/**
* 再生を再開
*/
resumePlayback() {
this.queueManager.resumePlayback();
}
/**
* キュー内のアイテム数を取得
*/
getQueueLength() {
return this.queueManager.getQueue().length;
}
/**
* キューが空かどうかを確認
*/
isQueueEmpty() {
return this.queueManager.getQueue().length === 0;
}
/**
* キューが再生中かどうかを確認
*/
isPlaying() {
return this.queueManager
.getQueue()
.some((item) => item.status === queue_1.QueueItemStatus.PLAYING);
}
/**
* キューマネージャーインスタンスを取得
* 高度な操作のため公開
*/
getQueueManager() {
return this.queueManager;
}
}
exports.VoicevoxPlayer = VoicevoxPlayer;