MioTTS のローカルマシンへのインストール

デアルン
質問: MioTTSってどんな感じ?
MioTTSってどんな感じですか?インストールがかなり面倒そうなので、がんばって導入する価値がありますか?


MioTTS をローカルマシンにインストールする手順を紹介します。

事前準備

Pythonのインストール

Pythonをインストールします。バージョン 3.12 が推奨されているようです。
インストール手順はこちらの記事を参照してください。

Gitのインストール

Gitをインストールします。インストール手順はこちらの記事を参照してください。

Ollamaのインストール

Ollamaをインストールします。インストール手順はこちらの記事を参照してください。

GitHubからのダウンロード

MioTTS のプログラムをGitHubから取得します。次のコマンドを実行します。

cd (MioTTSを配置するディレクトリ)
git clone https://github.com/Aratako/MioTTS-Inference.git

仮想環境の作成

今回はvenvを利用して仮想環境を作成します。

cd MioTTS-Inference
python -m venv .venv

または

cd MioTTS-Inference
(Pythonの配置パス)\python.exe -m venv .venv

ライブラリのインストール

以下のコマンドを実行して、ライブラリをインストールします。

.venv\Scripts\Activate.bat
python.exe -m pip install --upgrade pip
pip install uv

Git,Ollamaにパスが通っていない環境の場合には、Activate.batを編集します。

Activate.bat SET PATH部分 変更前
set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%"

Activate.bat SET PATH部分 変更後
set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%;(Git.exeが配置されているパス);(Ollama.exeが配置されているパス)"


変更後に再度Activate.bat を実行し、venv環境で以下のコマンドを実行します。

uv sync


syncの実行結果は下図です。
MioTTS のローカルマシンへのインストール:画像1

コマンドの動作確認

以下のコマンドを実行し、起動できるかを確認します。

ollama serve

エラーが表示されていますが、こちらはすでに起動済みの状態です。
MioTTS のローカルマシンへのインストール:画像2

ollama run hf.co/Aratako/MioTTS-GGUF:MioTTS-2.6B-BF16.gguf

初回起動時にはモデルのダウンロードが実行されます。今回は2.6Bのモデルを利用しています。
MioTTS のローカルマシンへのインストール:画像3


uv run run_server.py --llm-base-url http://localhost:11434/v1

MioTTS のローカルマシンへのインストール:画像4


python run_gradio.py

MioTTS のローカルマシンへのインストール:画像5

起動バッチファイルの作成

サーバーとWebUIをまとめて起動できるように、以下のバッチファイルをMioTTSの配置ディレクトリ(run_gradio.pyのあるディレクトリ)に作成します。
いったんCPUモードで起動します。

run.bat
call .venv\Scripts\activate.bat

start "OLLAMA SERVER" cmd /k ollama serve
timeout /t 3 /nobreak > nul

start "OLLAMA MODEL" cmd /k ^
ollama run hf.co/Aratako/MioTTS-GGUF:MioTTS-2.6B-BF16.gguf
timeout /t 5 /nobreak > nul

start "MIOTTS SERVER" cmd /k ^
uv run run_server.py --llm-base-url http://localhost:11434/v1 --device cpu
timeout /t 5 /nobreak > nul

start "MIOTTS WEBUI" cmd /k python run_gradio.py

実行

作成したバッチファイルを実行します。
MioTTS のローカルマシンへのインストール:画像6

GradioのURL(デフォルトの場合は、http://127.0.0.1:7860/)にアクセスします。
下図のページが表示されます。
MioTTS のローカルマシンへのインストール:画像7

Textのエリアに音声合成したいセリフのテキストを入力します。今回は「こんにちは」を入力しています。
[Preset ID]を"jp_female"に設定し、[Synthesize]ボタンをクリックします。
MioTTS のローカルマシンへのインストール:画像8

音声が合成されると、ページ下部に生成された音声の波形が表示され、再生できる状態になります。
MioTTS のローカルマシンへのインストール:画像9

参照音声を指定する場合は、[Reference Mode]の"upload"ラジオボタンをクリックして選択します。 [音声をここにドロップ]のエリアに参照したい音声ファイルをドロップするか、枠をクリックしてファイルを選択してアップロードします。
MioTTS のローカルマシンへのインストール:画像10

Textのエリアに音声合成したいセリフのテキストを入力し、[Synthesize]ボタンをクリックします。
MioTTS のローカルマシンへのインストール:画像11

音声が合成されると、ページ下部に生成された音声の波形が表示され、再生できる状態になります。
MioTTS のローカルマシンへのインストール:画像12

WindowsでCUDAで動作させる場合

メモ
最新版では不要です。
WindowsでCUDAのモードで実行した場合、reference_waveform が CPU 上(torch.FloatTensor)にあるのに対し、 コーデックモデルは CUDA 上(torch.cuda.FloatTensor)にあるため、デバイス不一致が発生しています。という状況になり、 参照音声を利用した場合に400エラーが発生する場合があります。
その場合は、コードを変更すると改善できる場合があります。

synthesizeメソッドの変更
miotts_server\codec.py (変更前)
    def synthesize(
        self,
        tokens: list[int] | torch.Tensor,
        reference_waveform: torch.Tensor | None = None,
        global_embedding: torch.Tensor | None = None,
        target_audio_length: int | None = None,
    ) -> torch.Tensor:
        if reference_waveform is None and global_embedding is None:
            raise ValueError("Either reference_waveform or global_embedding is required.")

        # Extract global embedding from reference waveform if provided
        if reference_waveform is not None:
            ref_features = self.codec.encode(reference_waveform, return_content=False, return_global=True)
            global_embedding = ref_features.global_embedding

        if isinstance(tokens, list):
            tokens = torch.tensor(tokens, dtype=torch.long, device=_codec_device(self.codec))
        elif isinstance(tokens, torch.Tensor) and tokens.dtype != torch.long:
            tokens = tokens.long()
        return self.codec.decode(
            global_embedding=global_embedding,
            content_token_indices=tokens,
            target_audio_length=target_audio_length,
        )
miotts_server\codec.py (変更後)
    def synthesize(
        self,
        tokens: list[int] | torch.Tensor,
        reference_waveform: torch.Tensor | None = None,
        global_embedding: torch.Tensor | None = None,
        target_audio_length: int | None = None,
    ) -> torch.Tensor:
        if reference_waveform is None and global_embedding is None:
            raise ValueError("Either reference_waveform or global_embedding is required.")

        device = _codec_device(self.codec)

        # Extract global embedding from reference waveform if provided
        if reference_waveform is not None:
            reference_waveform = reference_waveform.to(device=device, dtype=torch.float32)
            ref_features = self.codec.encode(reference_waveform, return_content=False, return_global=True)
            global_embedding = ref_features.global_embedding

        if isinstance(tokens, list):
            tokens = torch.tensor(tokens, dtype=torch.long, device=device)
        elif isinstance(tokens, torch.Tensor) and tokens.dtype != torch.long:
            tokens = tokens.long()
        return self.codec.decode(
            global_embedding=global_embedding,
            content_token_indices=tokens,
            target_audio_length=target_audio_length,
        )

synthesize_batchメソッドの変更
miotts_server\codec.py (変更前)
    def synthesize_batch(
        self,
        tokens_list: list[list[int]] | list[torch.Tensor],
        reference_waveform: torch.Tensor | None = None,
        global_embedding: torch.Tensor | None = None,
        target_audio_lengths: list[int] | None = None,
        padding_token_idx: int = 0,
    ) -> tuple[torch.Tensor, torch.Tensor]:
        if reference_waveform is None and global_embedding is None:
            raise ValueError("Either reference_waveform or global_embedding is required.")
        logger.debug("Synthesize batch: items=%d", len(tokens_list))

        device = _codec_device(self.codec)

        # Extract global embedding from reference waveform if provided
        if reference_waveform is not None:
            ref_features = self.codec.encode(reference_waveform, return_content=False, return_global=True)
            global_embedding = ref_features.global_embedding

miotts_server\codec.py (変更後)
    def synthesize_batch(
        self,
        tokens_list: list[list[int]] | list[torch.Tensor],
        reference_waveform: torch.Tensor | None = None,
        global_embedding: torch.Tensor | None = None,
        target_audio_lengths: list[int] | None = None,
        padding_token_idx: int = 0,
    ) -> tuple[torch.Tensor, torch.Tensor]:
        if reference_waveform is None and global_embedding is None:
            raise ValueError("Either reference_waveform or global_embedding is required.")
        logger.debug("Synthesize batch: items=%d", len(tokens_list))

        device = _codec_device(self.codec)

        # Extract global embedding from reference waveform if provided
        if reference_waveform is not None:
            reference_waveform = reference_waveform.to(device=device, dtype=torch.float32)
            ref_features = self.codec.encode(reference_waveform, return_content=False, return_global=True)
            global_embedding = ref_features.global_embedding

起動用のバッチファイルのデバイス指定を --device cuda に変更します。
run.bat
call .venv\Scripts\activate.bat

start "OLLAMA SERVER" cmd /k ollama serve
timeout /t 3 /nobreak > nul

start "OLLAMA MODEL" cmd /k ^
ollama run hf.co/Aratako/MioTTS-GGUF:MioTTS-2.6B-BF16.gguf
timeout /t 5 /nobreak > nul

start "MIOTTS SERVER" cmd /k ^
uv run run_server.py --llm-base-url http://localhost:11434/v1 --device cuda
timeout /t 5 /nobreak > nul

start "MIOTTS WEBUI" cmd /k python run_gradio.py


この修正で改善できる場合があります。

Best-of-N を利用する場合

Best-of-Nを利用する場合は、run_server.py のオプションに --best-of-n-enabled を追加します。
初回実行時にモデルのダウンロードが実行されるため、初回の実行には失敗する場合があります。モデルのダウンロード完了後に再度実行します。

run.bat
call .venv\Scripts\activate.bat

start "OLLAMA SERVER" cmd /k ollama serve
timeout /t 3 /nobreak > nul

start "OLLAMA MODEL" cmd /k ^
ollama run hf.co/Aratako/MioTTS-GGUF:MioTTS-2.6B-BF16.gguf
timeout /t 5 /nobreak > nul

start "MIOTTS SERVER" cmd /k ^
uv run run_server.py --llm-base-url http://localhost:11434/v1  --best-of-n-enabled --device cuda
timeout /t 5 /nobreak > nul

start "MIOTTS WEBUI" cmd /k python run_gradio.py

生成結果

生成結果は以下の動画で紹介しています。

仕様面

  • 感情表現をパラメーターではできないため、感情表現したい場合はセリフを感情に合わせたものにするか、リファレンスの音声に感情が入っているものを利用する必要がありそう
  • 生成のたびにイントネーションがそれなりに変化するため、何度も生成しなおすことでイメージ通りのイントネーションが得られる場合があります。
  • セリフの内容で感情がある程度乗るため、感情に合ったセリフにすることである程度のトーンをコントロールできそうです。

良い部分

  • 生成のたびにイントネーションがそれなりに変化するため、何度も生成しなおすと希望のイントネーションが得られることがある
  • セリフの文面である程度感情が乗る
  • イントネーションはとても自然

微妙な部分

  • ノイズが乗る場合がある
  • 擬音系のセリフにやや弱い (変な擬音をセリフに入れると呻き声だけが生成されることも。)
  • 速度の調整がしにくい。ややゆっくりしゃべってしまう印象あり
  • 男性の参照音声(低音の声質)の生成音声への反映が弱い印象がある


調整をしていない生成結果そのままの音声です。

コーデック更新版

当初版

T5Gemma-TTS, Qwen3-TTS, Style-Bert-VITS2 との比較

MioTTSと T5Gemma-TTS, Style-Bert-VITS2, Qwen3-TTS で比較してみます。比較結果は以下の動画です。

コーデック更新版

当初版

MioTTSの良い点

  • 読みの正しさ (セントモルガン島(トウ))
  • イントネーションがとても自然

MioTTSの微妙な点

  • 息継ぎがやや苦しそう
  • 音質がわずかに、こもりがちな気がします
  • 男性の参照音声があまり反映されない印象


AuthorPortraitAlt
著者
iPentecのプログラマー、最近はAIの積極的な活用にも取り組み中。
とっても恥ずかしがり。
作成日: 2026-02-11