import fs from "fs"; import path from "path"; // VOICEVOX APIの設定 const VOICEVOX_HOST = process.env.VOICEVOX_HOST ?? "http://localhost:50021"; const VOICEVOX_SPEAKER_ID = parseInt(process.env.VOICEVOX_SPEAKER_ID ?? "3"); const VOICEVOX_STYLE_ID = parseInt(process.env.VOICEVOX_STYLE_ID ?? "2"); interface VoiceStyle { speakerId: number; styleId: number; } // 環境変数からデフォルトの声設定を取得 const defaultVoiceStyle: VoiceStyle = { speakerId: VOICEVOX_SPEAKER_ID, styleId: VOICEVOX_STYLE_ID, }; export async function generateTTS( itemId: string, scriptText: string, ): Promise { // 音声合成クエリの生成 const queryResponse = await fetch(`${VOICEVOX_HOST}/audio_query`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ text: scriptText, speaker: defaultVoiceStyle.speakerId, }), }); if (!queryResponse.ok) { throw new Error("VOICEVOX 音声合成クエリ生成に失敗しました"); } const audioQuery = await queryResponse.json(); // 音声合成 const audioResponse = await fetch(`${VOICEVOX_HOST}/synthesis`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ audio_query: audioQuery, speaker: defaultVoiceStyle.speakerId, }), }); if (!audioResponse.ok) { throw new Error("VOICEVOX 音声合成に失敗しました"); } const audioArrayBuffer = await audioResponse.arrayBuffer(); const audioBuffer = Buffer.from(audioArrayBuffer); // 出力ディレクトリの準備 const outputDir = path.join(__dirname, "../public/podcast_audio"); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } const filePath = path.resolve(outputDir, `${itemId}.mp3`); fs.writeFileSync(filePath, audioBuffer); return filePath; }