📑
VOICEVOX エンジンを Docker で立ち上げて、音声をダウンロードする
はじめに
VOICEVOX は、商用・非商用問わず無料で利用できるテキスト読み上げソフトです。VOICEVOX エンジンを Docker で簡単に立ち上げ、TypeScript を使って音声ファイルをダウンロードする方法を紹介します。
Docker Compose で VOICEVOX を起動する
まず、以下の docker-compose.yml
ファイルを準備します。
docker-compose.yml
version: '3.8'
services:
voicevox_engine:
image: voicevox/voicevox_engine:cpu-ubuntu20.04-latest
ports:
- '50021:50021'
restart: unless-stopped
次に、以下のコマンドを実行して VOICEVOX エンジンを起動します。
docker compose up
これで、VOICEVOX エンジンが localhost:50021 で起動します。
TypeScript で音声をダウンロードする
bun init
で作成したプロジェクトで動作させることを想定しています。以下の TypeScript コードを使用して、指定したテキストを音声ファイルとしてダウンロードします。
import * as fs from 'node:fs/promises';
import { resolve } from 'node:path';
const VOICEVOX_URL = 'http://localhost:50021';
const logSuccess = (message: string) => console.log(`✅ ${message}`);
const logError = (message: string, error: unknown) => console.error(`❌ ${message}:`, error);
const createAudioQuery = async (text: string, speaker: number) => {
const queryResponse = await fetch(
`${VOICEVOX_URL}/audio_query?speaker=${speaker}&text=${encodeURIComponent(text)}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
}
);
if (!queryResponse.ok) {
throw new Error(`Failed to create audio query: ${queryResponse.statusText}`);
}
return queryResponse.json();
};
const synthesizeAudio = async (query: any, speaker: number) => {
const synthesisResponse = await fetch(
`${VOICEVOX_URL}/synthesis?speaker=${speaker}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(query),
}
);
if (!synthesisResponse.ok) {
throw new Error(`Failed to synthesize audio: ${synthesisResponse.statusText}`);
}
return synthesisResponse.arrayBuffer();
};
const saveAudioToFile = async (arrayBuffer: ArrayBuffer, outputPath: string) => {
const buffer = Buffer.from(arrayBuffer);
const absoluteOutputPath = resolve(outputPath);
await fs.writeFile(absoluteOutputPath, new Uint8Array(buffer));
return absoluteOutputPath;
};
const downloadAudio = async (text: string, speaker: number, outputPath: string) => {
try {
const query = await createAudioQuery(text, speaker);
const arrayBuffer = await synthesizeAudio(query, speaker);
const absoluteOutputPath = await saveAudioToFile(arrayBuffer, outputPath);
logSuccess(`音声ファイルをダウンロードしました: ${absoluteOutputPath}`);
} catch (e) {
logError('音声ファイルのダウンロード中にエラーが発生しました', e);
}
};
const ensureOutputDirExists = async (outputDir: string) => {
try {
await fs.mkdir(outputDir, { recursive: true });
} catch (e) {
logError(`出力フォルダ (${outputDir}) の作成に失敗しました`, e);
process.exit(1);
}
};
const main = async () => {
const outputDir = 'output';
const filename = 'long_voice.wav';
const outputPath = resolve(outputDir, filename);
await ensureOutputDirExists(outputDir);
const longText = `
皆さん、こんにちは!今日も元気に動画を見てくれてありがとうございます。
今日はですね、最近私がハマっている趣味について、ちょっとお話してみようかなと思っています。
それは何かと言いますと、実は最近、自宅でコーヒーを焙煎することに挑戦しているんです。
`;
await downloadAudio(longText, 1, outputPath); // スピーカーID 1 で音声をダウンロード
};
main();
このコードを実行すると、指定したテキストが音声ファイルとして output/long_voice.wav に保存されます。
スピーカーIDについて
VOICEVOX では、複数のキャラクター(スピーカー)が用意されています。スピーカーIDを変更することで、異なるキャラクターの音声を生成できます。例えば、スピーカーID 1 は「ずんだもん」に対応しています。
キャラクターの id は API ドキュメントの /speakers
を実行すると取得することができます。
http://localhost:50021/docs#/%E3%81%9D%E3%81%AE%E4%BB%96/speakers_speakers_get
公式ドキュメント
詳細な情報や最新のアップデートについては、以下の公式ドキュメントを参照してください。
その他の音声読み上げ
今後検証したい音声読み上げツールは以下です。
Discussion