前回の音声出力のVOICEVOX版プログラムです。Docker Desktopを使った記事ばかりしか見つからなかったのでDocker Desktopを使わないバージョンを作りました。pcパワーが結構いりますね。あとグラフィクスボードによっては入力中にエラーでます。なにが悪いのかわかる人がいたら教えてください。モデルと音声は自分の環境に合わせて書き換えてください。やっぱりgui版が一番安定しますね。

 

 

 

 

import requests
import subprocess
import speech_recognition as sr
import os
import time
import uuid
from datetime import datetime
from playsound import playsound

# ===== 設定 =====
VOSK_MODEL_PATH = r"C:\models\vosk-model-small-ja-0.22"
VOICEVOX_API = "http://127.0.0.1:50021"
SPEAKER_ID = 1
OLLAMA_COMMAND = (
    'ollama run hf.co/lightblue/suzume-llama-3-8B-japanese-gguf:Q4_K_M "{prompt}"'
)
AUDIO_SAVE_DIR = os.path.join(os.getcwd(), "audio_logs")

# ===== 音声保存フォルダの作成 =====
os.makedirs(AUDIO_SAVE_DIR, exist_ok=True)

# ===== VOICEVOXで読み上げ =====
def speak_voicevox(text: str):
    try:
        res1 = requests.post(
            f"{VOICEVOX_API}/audio_query",
            params={"text": text, "speaker": SPEAKER_ID}
        )
        res1.raise_for_status()
        query = res1.json()

        res2 = requests.post(
            f"{VOICEVOX_API}/synthesis",
            params={"speaker": SPEAKER_ID},
            json=query
        )
        res2.raise_for_status()

        # タイムスタンプ付きファイル名
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        unique_id = str(uuid.uuid4())[:8]
        filename = f"voicevox_{timestamp}_{unique_id}.wav"
        audio_path = os.path.join(AUDIO_SAVE_DIR, filename)

        with open(audio_path, "wb") as f:
            f.write(res2.content)

        playsound(audio_path)
        print(f"✅ 音声ファイル保存: {audio_path}")

    except Exception as e:
        print(f"[VOICEVOX error] {e}")

# ===== LLM応答生成 =====
def ask_llm(prompt: str) -> str:
    try:
        cmd = OLLAMA_COMMAND.format(prompt=prompt.replace('"', '\\"'))
        result = subprocess.run(
            cmd,
            shell=True,
            encoding="utf-8",
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        return (result.stdout or "").strip()
    except Exception as e:
        print(f"[LLM error] {e}")
        return "(エラーが発生しました)"

# ===== 音声認識(Vosk) =====
def transcribe():
    recognizer = sr.Recognizer()
    mic = sr.Microphone()
    with mic as source:
        print("🎤 話しかけてください...")
        recognizer.adjust_for_ambient_noise(source)
        audio = recognizer.listen(source, phrase_time_limit=10)
    try:
        return recognizer.recognize_vosk(audio, model=VOSK_MODEL_PATH)
    except Exception as e:
        print(f"[音声認識エラー] {e}")
        return ""

# ===== メインループ =====
def main():
    print("🟢 VOICEVOX対話開始")
    print("モードを選択してください:")
    print("1. 🎙 音声入力")
    print("2. ⌨️ キーボード入力")
    mode = input("番号を入力(1または2): ").strip()

    if mode == "1":
        while True:
            key = input("\n[Enter]で録音 / [q]で終了: ").strip().lower()
            if key == "q":
                break
            user_text = transcribe()
            if not user_text:
                print("(聞き取れませんでした)")
                continue
            print(f"🧑 あなた: {user_text}")
            reply = ask_llm(user_text)
            print(f"🤖 すずめ: {reply}")
            speak_voicevox(reply)

    elif mode == "2":
        while True:
            user_text = input("\n🧑 あなた(qで終了): ").strip()
            if user_text.lower() == "q":
                break
            reply = ask_llm(user_text)
            print(f"🤖 すずめ: {reply}")
            speak_voicevox(reply)

    else:
        print("⚠️ 無効な選択です。1または2を入力してください。")

if __name__ == "__main__":
    main()

 

お好きに改良してください。不具合起きても一切の責任を負いかねます。