当サイトにはアフィリエイト広告が含まれます。なおレビューは私の感想を書いており、内容を指示するご依頼はお断りしています

ChatGPT × VOICEPEAKで感情ボイスを自動生成!Pythonで喋るAIアバターを作る第一歩

VOICEPEAKをPythonから操作して、ChatGPTの返答を「感情つきの音声」に変換するスクリプトを作りました。
SAPI連携ではなく、コマンドライン引数を使った直接制御で動かしています。


🎯 やりたいこと

  • ChatGPTに発言させたい
  • その返答をVOICEPEAKで喋らせたい
  • 感情パラメータも自動で入れたい
  • 音声を自動再生したい
  • 最終的には3Dアバターにリップシンクさせたい(→VoiceMeeter Bananaで明日以降実装予定)

📦 使用ツール

  • VOICEPEAK(Minase Kou)
  • ChatGPT(OpenAI API)
  • Python 3.x
  • winsound(標準モジュール)
  • subprocess(標準モジュール)

📁 ファイル構成

  • chatgpt_3d/
    • output/
      • reply.txt # ChatGPTの返答テキスト
    • scripts/
      • chatgpt_speaks.py # 今回作った音声合成スクリプト

🐍 chatgpt_speaks.py の中身

import subprocess
import tempfile
import os
import winsound
import re
import random
import time

# === 設定 ===
VOICEPEAK_PATH = r"C:\Program Files\VOICEPEAK\voicepeak.exe"
NARRATOR = "Minase Kou"
SPEED = 135
PITCH = -75
DEFAULT_EMOTIONS = {
    'genki': 100,
    'happy': 100,
    'angry': 75,
    'sad': 5,
    'sasayaki': 0,
}

def random_emotions():
    return {
        'genki': random.randint(-10, 0),
        'happy': random.randint(-10, 0),
        'angry': random.randint(-10, 10),
        'sad': random.randint(-5, 10),
        'sasayaki': random.randint(0, 10),
    }

def build_emotion_string():
    delta = random_emotions()
    combined = {
        k: max(0, DEFAULT_EMOTIONS[k] + delta[k])
        for k in DEFAULT_EMOTIONS
    }
    return ",".join(f"{k}={v}" for k, v in combined.items() if v > 0)

def split_sentences(text, max_len=140):
    raw_sentences = re.split(r'(?<=[。!?])', text)
    chunks = []
    current = ''
    for sentence in raw_sentences:
        if len(current) + len(sentence) <= max_len:
            current += sentence
        else:
            if current:
                chunks.append(current.strip())
            current = sentence
    if current:
        chunks.append(current.strip())
    return [c for c in chunks if c]

def speak(text):
    emotion = build_emotion_string()
    with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_wav:
        wav_path = tmp_wav.name

    cmd = [
        VOICEPEAK_PATH,
        "-s", text,
        "-n", NARRATOR,
        "-e", emotion,
        "-o", wav_path,
        "--speed", str(SPEED),
        "--pitch", str(PITCH)
    ]
    subprocess.run(cmd)
    return wav_path

# === 実行 ===
with open("chatgpt_3d/output/reply.txt", encoding="utf-8") as f:
    full_text = f.read()

sentences = split_sentences(full_text)

wav_files = []
for s in sentences:
    print(f"🗣️ {s}")
    wav_files.append(speak(s))
    time.sleep(0.3)

for wav_path in wav_files:
    winsound.PlaySound(wav_path, winsound.SND_FILENAME)
    os.remove(wav_path)

👣 今後の展望

  • VoiceMeeter Bananaを導入して、音声出力をVB-CABLE経由で3teneに送信
  • 3teneのリップシンクでキャラが「喋ってるように」見せる
  • ChatGPTのAPIと連携し、完全に自動応答するアバターへ進化予定

📝 おわりに

CLI連携に切り替えたことで、VOICEPEAKの柔軟なコントロールが可能になりました。 Pythonの中で感情パラメータも制御できるので、音声の“表情”を作るのが楽しくなります。

次は「キャラが口を動かす」段階へ。 物語の“声”が、いよいよ“存在”になっていきます。

💬 おまけ:キャラAIの感情制御について興味がある人へ

感情パラメータの扱いは、人間らしさと制御性のバランスが大事。 今回はランダム生成でしたが、「入力内容に応じた感情制御」も今後試したいですね。