Kokoro-82M:82Mパラメータの軽量TTSモデルを実行してみた

AI

Kokoro-82M:82Mパラメータの軽量TTSモデルを実行してみた


超軽量 テキスト・トゥ・スピーチ(TTS)モデル Kokoro-82M の実力は?

AIのテキスト・トゥ・スピーチ(TTS)モデルは、日常的に使えるようになってきている。でも、多くのモデルは「無償ではロボットボイス感が強い」「日本語対応が不十分」といった課題を抱えています。そんな中で、82M パラメータの超軽量モデル Kokoro-82M (出典:hexgrad / Hugging Face https://huggingface.co/hexgrad/Kokoro-82M ) が登場。注目すべきは、既存のTTSモデル1/5〜1/10程の超軽量サイズ。

Hugging Faceでの2026年1月のダウンロード回数は、880万回程と強い人気を集めているようですね。でも「音がどうなるのか」は、実際に試してみないと分からないので試してみました。


実際に試してみた

実行環境

  • OS:Windows 11 Pro
  • CPU:Ryzen 9 8945HS(8コア)
  • DRAM:64GB
  • GPU:RTX 5070 Ti VRAM 16GB(eGPUで接続)
  • Python:3.11

実行手順(コード) エラーが出たらすいません。

# 日本語利用時は pyopenjtalk, fugashi, unidic-lite, jaconv, mojimoji が必要です。
# 未導入なら: pip install pyopenjtalk fugashi unidic-lite jaconv mojimoji

import sys
import os
from datetime import datetime
import soundfile as sf

# 使用モデル
MODEL_NAME = "hexgrad/Kokoro-82M"

# デフォルト設定(Kokoro)
# lang_code: a=アメリカ英語, b=イギリス英語, c=中国語, j=日本語 など(要: kokoro の仕様確認)
DEFAULT_LANG_CODE = "j"   # 日本語
DEFAULT_VOICE = "af_heart"  # 声の種類
# 複数パターンを一回で出す場合は VOICE_LIST を使う(空なら DEFAULT_VOICE)
VOICE_LIST = [
    #"af_heart", "af_alloy", "af_aoede", "af_jessica", "af_kore", "af_nicole", "af_nova", "af_river", "af_sarah", "af_sky",
    # "bf_alice", "bf_emma", "bf_isabella", "bf_lily",
    # "am_adam", "am_echo", "am_eric", "am_fenrir", "am_liam", "am_michael", "am_onyx", "am_puck", "am_santa",
    "jf_alpha", "jm_kumo"
]

# -------------------------------------------------------------------
# テキスト読み込み(MB/テキストファイル対応)
# -------------------------------------------------------------------
def load_text(mb_path: str) -> str:
    lines = []
    try:
        with open(mb_path, "r", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if not line or line.upper().startswith("REM"):
                    continue
                lines.append(line)
    except Exception as e:
        print(f"[WARN] テキスト読込失敗: {e}")
    return "\n".join(lines)

# -------------------------------------------------------------------
# TTS 生成
# -------------------------------------------------------------------
def generate_tts(text: str, pipeline, out_base: str,
                 voice: str = DEFAULT_VOICE,
                 lang_code: str = DEFAULT_LANG_CODE,
                 sample_rate: int = 24000,
                 formats: tuple = (".flac",)):
    """out_base: 拡張子なしの出力パス。formats で指定した形式で保存する。"""
    try:
        if not text or not text.strip():
            print("[WARN] 読み上げるテキストがありません")
            return

        print(f"[INFO] TTS 生成中 (voice={voice}, lang_code={lang_code})...")
        chunks = []
        # lang_code は KPipeline 初期化時に指定するので __call__ には渡さない
        for _i, (_gs, _ps, audio) in enumerate(pipeline(text.strip(), voice=voice)):
            chunks.append(audio)
        if not chunks:
            print("[WARN] 音声が生成されませんでした")
            return
        import numpy as np
        audio = np.concatenate(chunks, axis=0)
        for ext in formats:
            out_path = out_base + ext
            sf.write(out_path, audio, sample_rate)
            print(f"[OK] 生成完了: {out_path}")

    except Exception as e:
        print(f"[ERROR] 生成失敗: {e}")

# -------------------------------------------------------------------
# メイン処理(引数 = TTS 対象の .txt / .mb、n 個指定で順番に処理)
# -------------------------------------------------------------------
def main():
    if len(sys.argv) < 2:
        print("テキストファイル(.txt / .mb)をこの py にドラッグ&ドロップしてください。複数指定可。")
        return

    txt_paths = [p for p in sys.argv[1:] if os.path.exists(p)]
    if not txt_paths:
        print("[ERROR] 存在するファイルが一つもありません。")
        return

    print(f"[INFO] モデル読み込み中: {MODEL_NAME}")
    from kokoro import KPipeline
    pipeline = KPipeline(lang_code=DEFAULT_LANG_CODE)                 # GPU動作用
    # pipeline = KPipeline(lang_code=DEFAULT_LANG_CODE, device="cpu") # CPU動作用

    voices = VOICE_LIST if VOICE_LIST else [DEFAULT_VOICE]

    print(f"\n=== TTS: {MODEL_NAME} ===")
    for file_idx, txt_path in enumerate(txt_paths, start=1):
        print(f"\n--- [{file_idx}/{len(txt_paths)}] {os.path.basename(txt_path)} ---")
        text = load_text(txt_path)
        if not text:
            print("[WARN] 有効なテキストがありません(スキップ)")
            continue

        input_base = os.path.splitext(os.path.basename(txt_path))[0]
        out_dir = os.path.join(os.path.dirname(os.path.abspath(txt_path)), "result")
        os.makedirs(out_dir, exist_ok=True)

        for idx, voice in enumerate(voices, start=1):
            voice_slug = voice.replace(" ", "_")
            # VOICE_LIST で複数ボイスのときはファイル名にボイス名を含める
            if len(voices) > 1:
                out_name_base = f"{input_base}_Kokoro_{voice_slug}"
            else:
                out_name_base = f"{input_base}_Kokoro"
            out_base = os.path.join(out_dir, out_name_base)
            print(f"[INFO] パターン {idx}/{len(voices)}: {voice}")
            generate_tts(text, pipeline, out_base,
                         voice=voice,
                         lang_code=DEFAULT_LANG_CODE,
                         formats=(".flac",))

    print("\n完了")

# -----------------------------
if __name__ == "__main__":
    main()

使用方法

  1. 上記のコードを kokoro_tts.py として保存。
  2. 任意のテキストファイル(.txt または .mb)をそのファイルにドラッグ&ドロップ。
  3. ファイルが読み込まれると、result/ フォルダに .flac 形式の音声が出力される。

結果

  • 推論時間1000文字TTSGPU処理で、わずか15秒!!  CPU処理でも40秒でした。
     
  • 音質
     - 日本語用ボイスで、日本語をしゃべらせして、一番ロボットボイス感が少ないのは、”jf_alpha” と “jm_kumo”。これでも、時折、変なイントネーションはでてきます。
     - 英語用ボイスで、日本語をしゃべらせると、英語ネイティブのイントネーションで話す日本語。ある意味、こちらの方が本物らしい。どこに需要があるのかは不明。
     - 英語用ボイスで、英語をしゃべらせると、日本人の私には本物のように聞こえました。Youtubeの英語吹き替えよりも、本物らしい声です。
  • 他に気づいたこと: 
     - 日本語でのTTSでは、アルファベット文字はカタカナにしてあげないと読み飛ばす動作をしていました。

技術的整理

  • 実用性
     - 英語では商用利用でも、違和感がなさそうな品質と思われます。
     - 英語の声の質感はかなり良いので、英語学習で使えると思います。長時間聞いても飽きなさそう。
  • ローカル運用
     - 実行時のVRAM使用量は3GB程度。CPUでもサクッと動きます。


まとめ

Kokoro-82Mは、軽量ながらも超自然な TTSモデル。
Google Colab や ローカルGPUで動かして、個人用の音声生成に使うには、非常に優れた選択肢。


B級エンジニアのライフログ
好奇心でゆるく最適化するテックライフ