71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import fs from "fs";
|
|
import path from "path";
|
|
|
|
// VOICEVOX APIの設定
|
|
const VOICEVOX_HOST = import.meta.env["VOICEVOX_HOST"];
|
|
const VOICEVOX_STYLE_ID = parseInt(import.meta.env["VOICEVOX_STYLE_ID"] ?? "0");
|
|
|
|
interface VoiceStyle {
|
|
styleId: number;
|
|
}
|
|
|
|
// 環境変数からデフォルトの声設定を取得
|
|
const defaultVoiceStyle: VoiceStyle = {
|
|
styleId: VOICEVOX_STYLE_ID,
|
|
};
|
|
|
|
export async function generateTTS(
|
|
itemId: string,
|
|
scriptText: string,
|
|
): Promise<string> {
|
|
console.log(`TTS生成開始: ${itemId}`);
|
|
const encodedText = encodeURIComponent(scriptText);
|
|
|
|
const queryUrl = `${VOICEVOX_HOST}/audio_query?text=${encodedText}&speaker=${defaultVoiceStyle.styleId}`;
|
|
const synthesisUrl = `${VOICEVOX_HOST}/synthesis?speaker=${defaultVoiceStyle.styleId}`;
|
|
|
|
const queryResponse = await fetch(queryUrl, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Accept: "application/json",
|
|
},
|
|
});
|
|
|
|
if (!queryResponse.ok) {
|
|
throw new Error("VOICEVOX 音声合成クエリ生成に失敗しました");
|
|
}
|
|
|
|
const audioQuery = await queryResponse.json();
|
|
|
|
console.log(`音声合成開始: ${itemId}`);
|
|
const audioResponse = await fetch(synthesisUrl, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify(audioQuery),
|
|
});
|
|
|
|
if (!audioResponse.ok) {
|
|
console.error(`音声合成失敗: ${itemId}`);
|
|
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); // Use the provided filename directly
|
|
console.log(`音声ファイル保存開始: ${filePath}`);
|
|
fs.writeFileSync(`${filePath}.wav`, audioBuffer);
|
|
console.log(`音声ファイル保存完了: ${filePath}`);
|
|
|
|
return path.basename(filePath);
|
|
}
|