1. 概要
以前、「ぱ行で会話するための変換プログラムを作成」という記事を書きました。
今回は、その変換プログラムで生成されたテキストをずんだもんで読み上げる機能を実施します。
2. 環境・技術スタック
- OS: Windows11
- 開発言語: Go 1.23
- Webフレームワーク:Echo v4
- 音声合成:エンジンVOICEVOX Engine
3. 構成図
今回はWindows環境で動作するのを目的としています。
4. VOICEVOXのセットアップ
VOICEVOXは無料で使える高品質な音声合成エンジンです。ずんだもん、四国めたんなど、様々なキャラクターの声で音声を生成できます。
① VOICEVOX公式サイトからダウンロード
環境に合わせてダウンロードしてください。私はこのままの設定でダウンロードしました。
② インストールして起動
アプリが立ち上がりますが、今回は GUI ではなく API の利用が目的なので、この画面は使いません。
③ 起動確認
ブラウザで確認
開発で使用するVOICEVOXのAPIが正常に起動しているか確認します。
http://localhost:50021/docsにアクセスすると、APIのドキュメントが見えると思います。
CURLで確認
curl http://localhost:50021/speakers
以下のようなJSONが返ってくればOKです:
[
{
"name": "四国めたん",
"speaker_uuid": "...",
"styles": [...]
},
{
"name": "ずんだもん",
"speaker_uuid": "...",
"styles": [...]
},
...
]
5. GOプログラム実装
以下がGoで書いたコードです。ざっくりとコメントで処理の内容を記載しました。
package handlers
import (
"bytes"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strconv"
"github.com/labstack/echo/v4"
)
// VOICEVOX APIのベースURL取得
func getVoicevoxBaseURL() string {
if url := os.Getenv("VOICEVOX_URL"); url != "" {
return url
}
return "http://localhost:50021"
}
// リクエストボディの構造体
type VoiceRequest struct {
Text string `json:"text"`
}
// 音声生成ハンドラ
func GenerateVoiceHandler(c echo.Context) error {
// 1. VOICEVOX サーバーの URL を取得
baseURL := getVoicevoxBaseURL()
// 2. リクエストから text を取得
var req VoiceRequest
if err := c.Bind(&req); err != nil || req.Text == "" {
req.Text = c.QueryParam("text")
}
if req.Text == "" {
return c.JSON(http.StatusBadRequest, map[string]string{
"error": "textが指定されていません",
})
}
speakerID := 3 // ずんだもんを指定
// 3. VOICEVOX に audio_query を投げる
params := url.Values{}
params.Set("text", req.Text)
params.Set("speaker", strconv.Itoa(speakerID))
audioQueryURL := fmt.Sprintf("%s/audio_query?%s", baseURL, params.Encode())
resp, err := http.Post(audioQueryURL, "application/json", nil)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"error": "audio_queryに失敗しました",
})
}
defer resp.Body.Close()
audioQuery, err := io.ReadAll(resp.Body)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"error": "audio_queryの応答取得に失敗しました",
})
}
// 4. クエリをもとに実際の音声(WAV)を生成
synthesisURL := fmt.Sprintf("%s/synthesis?speaker=%d", baseURL, speakerID)
resp2, err := http.Post(synthesisURL, "application/json", bytes.NewReader(audioQuery))
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"error": "synthesisに失敗しました",
})
}
defer resp2.Body.Close()
wavData, err := io.ReadAll(resp2.Body)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"error": "音声データの読み取りに失敗しました",
})
}
// 5. WAVを返す
c.Response().Header().Set("Content-Type", "audio/wav")
return c.Blob(http.StatusOK, "audio/wav", wavData)
}
6. 実際にできたもの
以下は実際に動かしたときの画面(GIF)です。
残念ながら、音声は載せられませんでしたが、ずんだもんを感じ取ってください。
7. おわりに
Go と VOICEVOX を組み合わせることで、手軽に音声合成 API を構築できました。
このクオリティを無料で提供してくださっている VOICEVOX の開発者の皆さんには感謝しかありません。
ソースコードは以下のリポジトリで公開しています。
興味のある方はぜひチェックしてみてください。
ここまで読んで頂きありがとうございました。




