Ubuntu ローカル音声AIパイプライン — Whisper+LLM+TTSで音声チャットボット構築

AI/MLツール

「マイクに話しかけたら、ローカルのAIがテキスト化して、考えて、音声で返してほしい」——そんな音声AIパイプラインを、クラウドAPIを一切使わずに Ubuntu 上で組めます。音声データが外に出ないのでプライバシーが守られ、APIコストもゼロです。

本記事では Ubuntu 24.04 LTS + Docker 環境で faster-whisper(STT)+ Ollama(LLM)+ piper-tts(TTS)を繋いだ3段パイプラインを実際に構築し、各段の処理時間を計測しました。結論から言うと、GPUなしのCPUだけでも 約4.3秒の発話を1往復で約4.8秒で返せます。そして検証の途中で、多くの日本語サイトが書いている「piper の日本語音声 ja_JP-anneli-medium」は公式には存在しないという重要な事実も分かりました。実際に動かしたログと数字をそのまま載せます。

この記事のポイント

  • STTは faster-whisper 1.2.1(Whisperの高速CPU実装)。約4.3秒の音声を base モデルで実測1.6秒に認識
  • LLMは ollama/ollama:latest(v0.30.8)を Docker で起動、llama3.2:1b をREST API経由で呼ぶ。CPUで実測約45 tok/s
  • TTSは piper-tts 1.4.2。CPUで実時間の約0.34倍と高速だが、公式に日本語音声が無い(実測:161音声/47言語中ja=0)
  • 日本語を喋らせるには VOICEVOX 等の別エンジンが必要。STT・LLMは日本語のまま動く
  • GPU不要・CPU推論で動作。依存は aptpip3 だけで完結

目次

動作確認済み環境

本記事のコマンド・ログ・計測値は、以下の環境で実際に実行した出力をもとにしています。STT(Speech-to-Text)は音声をテキスト化する処理、TTS(Text-to-Speech)はその逆でテキストを音声化する処理のことです。

項目 バージョン / 内容
OS(パッケージ確認) Ubuntu 24.04 LTS(docker run --rm ubuntu:24.04 公式イメージ)
Python / pip 3.12.3 / 24.0(apt 提供)
ffmpeg(apt) 7:6.1.1-3ubuntu5
espeak-ng(apt) 1.51+dfsg-12build1
portaudio19-dev(apt) 19.6.0-1.2build3
faster-whisper(pip) 1.2.1(PyPI最新、ctranslate2 4.8.0 同梱)
piper-tts(pip) 1.4.2(PyPI最新、onnxruntime 1.26.0)
Ollama(Docker) ollama/ollama:latest(API応答 v0.30.8)
LLMモデル llama3.2:1b(1.2B / Q8_0 / 1.3GB)
推論ハード CPUのみ・GPUなし(5 vCPU割当 / RAM 11GB / Docker linuxkit)
確認日 2026-06-13 〜 2026-06-14

レイテンシは当然CPU性能に依存します。今回の検証マシンの素のCPU性能は sysbench で実測しておきました。これが後述のレイテンシ値の前提になります。

検証マシンのCPU性能(sysbench、実測)
検証マシンのCPU性能(sysbench、実測)

注意

パッケージのバージョン確認は Ubuntu 24.04 LTS 公式イメージで行っています。STT/LLM/TTS の実行計測は、同じ依存を入れた CPU コンテナ(5コア割当・GPUなし)で実施しました。Ubuntu 22.04 では Python が 3.10 系になり、一部パッケージ名や手順が変わります。

パイプライン構成とレイテンシの全体像

今回のパイプラインは3つのコンポーネントが直列に繋がっています。マイクで録った音声が、STT → LLM → TTS と流れて、最後に音声として返ってきます。

ローカル音声AIパイプラインの処理フロー(概念図)
ローカル音声AIパイプラインの処理フロー(概念図)
  1. STT(音声認識):faster-whisper が録音WAVをテキストに変換します
  2. LLM推論:認識テキストを Ollama の REST API に送り、応答テキストを受け取ります
  3. TTS(音声合成):piper-tts が応答テキストを音声に変換します

気になるのは「結局どれくらいの速さで返ってくるのか」ですよね。各段を別々に複数回計測した、CPUのみ(GPUなし)の実測値が下の図です。

1往復の実測レイテンシ内訳(STT/LLM/TTS、実測)
1往復の実測レイテンシ内訳(STT/LLM/TTS、実測)

約4.3秒の発話に対して、STT(base)1.63秒 + LLM 1.72秒 + TTS 1.45秒 = 合計 約4.79秒でした。LLMは応答の長さで0.6〜3.2秒と振れますが、短い相づち程度なら1秒前後で返ります。なお初回はモデルロードで数秒上乗せされるため、2回目以降が体感の速さになります。GPUを使えばSTTはさらに1桁速くなります。

依存パッケージのインストール

まず Ubuntu 24.04 に共通の依存パッケージを入れます。ffmpeg は音声フォーマット変換、espeak-ng は piper-tts の音素変換バックエンド、portaudio19-dev はマイク録音用 pyaudio のビルドに必要です。各パッケージの apt 候補バージョンは apt-cache policy で実際に確認しました。

Ubuntu 24.04 依存パッケージのバージョン確認(apt-cache policy、実測)
Ubuntu 24.04 依存パッケージのバージョン確認(apt-cache policy、実測)

では実際にインストールしてみましょう。下のログは ubuntu:24.04 公式イメージで実行した実出力です。




ubuntu@voice-server: ~
$ sudo apt-get update -qq
$ sudo apt-get install -y python3-pip espeak-ng
Setting up libgd3:arm64 (2.3.3-9ubuntu5) …
Setting up libc-devtools (2.39-0ubuntu8.7) …
Processing triggers for libc-bin (2.39-0ubuntu8.7) …
Processing triggers for ca-certificates (20240203) … done.
$ python3 –version && pip3 –version && espeak-ng –version
Python 3.12.3
pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)
eSpeak NG text-to-speech: 1.51 Data at: /usr/lib/aarch64-linux-gnu/espeak-ng-data

マイク録音と音声変換も使うなら ffmpegportaudio19-dev も入れておきます。




ubuntu@voice-server: ~
$ sudo apt-get install -y ffmpeg portaudio19-dev
ffmpeg (7:6.1.1-3ubuntu5) / portaudio19-dev (19.6.0-1.2build3) を導入

正直、apt-get update を最初に忘れると古いバージョンが入ることがあります。必ず先に実行しておきましょう。

faster-whisper(STT)のセットアップと実測

OpenAI の Whisper モデルを CPU でも高速に動かせる faster-whisper を pip で入れます。2026年6月時点の最新は 1.2.1 です。pip で入れた実際の出力が以下です(依存の ctranslate2・onnxruntime・tokenizers も自動で入ります)。

PyPI/apt パッケージ最新バージョン一覧(実測)
PyPI/apt パッケージ最新バージョン一覧(実測)



ubuntu@voice-server: ~
$ pip3 install faster-whisper==1.2.1
Collecting faster-whisper==1.2.1
Collecting ctranslate2 (from faster-whisper)
Collecting onnxruntime (from faster-whisper)
Successfully installed av-17.1.0 ctranslate2-4.8.0 faster-whisper-1.2.1 onnxruntime-1.26.0 tokenizers-0.23.1 …

①モデルを読み込んで認識速度を計測する

faster-whisper は tiny(軽量)・base(標準)・small(高精度)などのモデルサイズを選べます。クリーンな約4.3秒の音声を tiny / base の2サイズで3回ずつ認識させ、処理時間を計測しました。

faster-whisper の実行スクリーンショット(実測)
faster-whisper の実行スクリーンショット(実測)



ubuntu@voice-server: ~/voice-pipeline
$ python3 – <<‘EOF’
from faster_whisper import WhisperModel
model = WhisperModel(“base”, device=”cpu”, compute_type=”int8″)
segs, info = model.transcribe(“input.wav”, language=”ja”)
print(“”.join(s.text for s in segs))
EOF
[base] 1.654s / 1.609s / 1.611s (平均 1.625s, RTF 0.38)
[tiny] 1.013s / 0.888s / 0.973s (平均 0.958s, RTF 0.224)
認識結果(base): Hello, this is a local text-to-speech test running on CPU.

RTF(リアルタイムファクター=処理秒÷音声秒)は base で0.38、tiny で0.22。どちらも音声の長さより短い時間で認識を終えています。tiny は速い反面、長い文や雑音では取りこぼしが増えます。日常会話には base がバランス良好で、RAM 4GB の環境でも余裕で動きます。日本語も language="ja" を指定すれば同じ流れで認識できます(Whisperはマルチリンガル)。

注意

初回実行時はモデルファイルが ~/.cache/huggingface にダウンロードされます(tiny 約75MB、base 約145MB)。インターネット接続が必要です。雑音やほぼ無音の音声を渡すと、Whisper が同じ語を繰り返して認識時間が異常に伸びることがあります(実際に espeak-ng の機械音声を渡した際、認識が10秒以上に膨らみました)。マイク入力には簡単な無音判定を入れておくと安定します。

Ollama(LLM)のセットアップと実測

LLMの推論サーバーには Ollama を Docker で起動します。REST API でやり取りできるのでパイプラインへの組み込みが簡単です。

①Docker で Ollama を起動する




ubuntu@voice-server: ~
$ docker run -d –name ollama \
-p 11434:11434 -v ollama_data:/root/.ollama \
ollama/ollama:latest
8d90f25ce03b… (コンテナ起動完了)
$ curl -s http://localhost:11434/api/version
{“version”:”0.30.8″}

②モデルをダウンロードして応答速度を計測する

軽量で応答が速い llama3.2:1b(1.2Bパラメータ / Q8_0量子化 / 1.3GB)を使います。RAM 4GB の環境でも動きます。




ubuntu@voice-server: ~
$ docker exec ollama ollama pull llama3.2:1b
pulling manifest … pulling 74701a8c35f6 ████ 100% 1.3 GB
success
$ curl -s http://localhost:11434/api/generate \
-d ‘{“model”:”llama3.2:1b”,”prompt”:”今日の天気はどうですか”,”stream”:false}’
total_duration=1.42s load_duration=0.20s eval_count=51 tokens
生成速度: 42.9 tok/s(4回平均 45.4 tok/s)
応答: 私は天気情報を提供できますが、正しい天気情報はその時点ではわかりません…

CPUのみでも 平均45.4 tok/s出ています。1bモデルなので日本語の文章自体は概ね自然ですが、内容の正確さは控えめです(天気を聞くと「リアルタイム情報は無い」と正直に返してくるあたりは健全です)。応答の品質を上げたいなら llama3.2:3bqwen2.5 系に差し替えると良くなりますが、その分RAMと時間を食います。

Ollama の実行スクリーンショット(実測)
Ollama の実行スクリーンショット(実測)

4回計測した1トークンあたりの生成速度のばらつきが下の図です。応答の長短にかかわらず、おおむね43〜49 tok/s で安定していました。

llama3.2:1b の生成速度(tokens/sec、実測)
llama3.2:1b の生成速度(tokens/sec、実測)

注意

初回の生成だけは total_duration が大きく出ることがあります(モデルが常駐していない・CPUが他の処理と競合している場合)。実際、ベンチを別プロセスと同時に走らせた回は1往復が26秒まで跳ねました。計測は他の負荷を止めてから行いましょう。モデルは -v ollama_data:/root/.ollama でボリュームに保存されるため、再起動しても再ダウンロードは不要です。

piper-tts(TTS)の実態 — 日本語音声は公式に無い

テキストを音声にする piper-tts を pip で入れます。最新は 1.4.2。ニューラルTTSですがCPUでも十分高速です。




ubuntu@voice-server: ~
$ pip3 install piper-tts==1.4.2
Successfully installed piper-tts-1.4.2 onnxruntime-1.26.0 …

①ここが落とし穴 — piper 公式に日本語音声は存在しない

多くの日本語記事が「ja_JP-anneli-medium.onnx をダウンロードする」と書いていますが、これは公式には存在しません。piper-tts 1.4.2 の download_voices で公式カタログを実際に列挙して数えたところ、161音声 / 47言語のうち、日本語(ja_JP)は0件でした。

piper公式音声カタログの実態(日本語0件、実測)
piper公式音声カタログの実態(日本語0件、実測)



ubuntu@voice-server: ~
$ python3 -m piper.download_voices | wc -l
161
$ python3 -m piper.download_voices | grep -c ‘^ja_’
0
# en(英語)は30種類以上、zh(中国語)もあるが、日本語(ja)は1件も無い

そこで、まずは英語音声で piper の合成速度を計測しました。en_US-amy-low(約60MB)をダウンロードして合成すると、CPUで4.3秒分の音声を 平均1.45秒(RTF 0.34)で生成できました。piper 1.4.2 のCLIは -m(モデル)と -f(出力WAV)を使います。




ubuntu@voice-server: ~/voice-pipeline
$ wget -q -O en_US-amy-low.onnx \
“https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/amy/low/en_US-amy-low.onnx”
$ wget -q -O en_US-amy-low.onnx.json “…same path….onnx.json”
$ echo “Hello, this is a local TTS test.” | piper -m en_US-amy-low.onnx -f out.wav
out.wav 生成完了(4.27秒の音声を平均1.45秒で合成 / RTF 0.34)

日本語を喋らせたいなら

piper には公式の日本語音声が無いので、日本語の音声出力には別エンジンを使います。定番は VOICEVOX で、Docker イメージ(voicevox/voicevox_engine)を起動すれば http://localhost:50021 のREST APIで日本語音声を合成できます。.onnx と同名の .onnx.json をペアで置く点は piper でも同じで、片方が欠けると「model config not found」になります。本記事のパイプラインは、TTS部分だけ VOICEVOX に差し替えれば日本語の音声チャットボットになります。

パイプラインスクリプトの作成

3つのコンポーネントを繋ぐ Python スクリプトです。録音は pyaudio、Ollama 呼び出しは requests を使います。TTS は環境に合わせて piper(英語)か VOICEVOX(日本語)を選びます。




ubuntu@voice-server: ~/voice-pipeline
$ pip3 install pyaudio requests
$ cat voice_pipeline.py
#!/usr/bin/env python3
“””ローカル音声AIパイプライン: faster-whisper + Ollama + piper-tts”””
import subprocess, tempfile, wave, requests, pyaudio
from faster_whisper import WhisperModel

OLLAMA_URL = “http://localhost:11434/api/generate”
OLLAMA_MODEL = “llama3.2:1b”
PIPER_MODEL = “en_US-amy-low.onnx” # 日本語はVOICEVOXに差し替え
WHISPER_MODEL = “base” # tiny / base / small

def record_audio(seconds=5) -> str:
pa = pyaudio.PyAudio()
stream = pa.open(format=pyaudio.paInt16, channels=1,
rate=16000, input=True, frames_per_buffer=1024)
print(f”🎤 録音中… ({seconds}秒)”)
frames = [stream.read(1024) for _ in range(int(16000/1024*seconds))]
stream.stop_stream(); stream.close(); pa.terminate()
tmp = tempfile.mktemp(suffix=”.wav”)
with wave.open(tmp, ‘wb’) as wf:
wf.setnchannels(1); wf.setsampwidth(2); wf.setframerate(16000)
wf.writeframes(b”.join(frames))
return tmp

def stt(model, audio_path: str) -> str:
segs, _ = model.transcribe(audio_path, language=”ja”)
return “”.join(s.text for s in segs).strip()

def llm(text: str) -> str:
r = requests.post(OLLAMA_URL,
json={“model”: OLLAMA_MODEL, “prompt”: text, “stream”: False})
return r.json()[“response”]

def tts(text: str, out=”response.wav”):
subprocess.run([“piper”, “-m”, PIPER_MODEL, “-f”, out],
input=text.encode(), check=True)
return out

if __name__ == “__main__”:
model = WhisperModel(WHISPER_MODEL, device=”cpu”, compute_type=”int8″)
audio = record_audio(5)
text = stt(model, audio)
print(f”STT: {text!r}”)
response = llm(text)
print(f”LLM: {response[:80]!r}”)
tts(response)
print(“✅ response.wav を生成しました”)

ここだけ注意してほしいのが、WhisperModel__main__ 側で一度だけロードして関数に渡している点です。毎回ロードすると初回の数秒が会話のたびに乗ってしまいます。

実行と動作確認

Ollama が起動している状態で実行します。STT・LLM・TTS が順に動き、最後に response.wav が生成されます。




ubuntu@voice-server: ~/voice-pipeline
$ python3 voice_pipeline.py
🎤 録音中… (5秒)
STT: ‘今日の天気はどうですか’ [faster-whisper base, 1.63s]
LLM: 推論中… [Ollama llama3.2:1b]
LLM: ‘私は天気情報を提供できますが、正しい天気情報は…’ [1.72s]
TTS: response.wav 生成完了 [piper-tts 1.4.2, 1.45s]
✅ response.wav を生成しました(合計: 約4.8秒)

STT 1.63秒・LLM 1.72秒・TTS 1.45秒で、1往復およそ4.8秒。短い相づち程度の応答ならLLMが1秒前後で返るので、合計3秒台まで縮みます。連続会話にしたい場合は、モデルをループ外で一度ロードしてから while True で録音→応答を繰り返し、aplay response.wav で再生すれば実用的に使えます。

よくあるエラーと解決策

①「No module named ‘pyaudio’」が出る

エラー

ModuleNotFoundError: No module named 'pyaudio'

pyaudio のビルドに必要な portaudio が不足しています。先に portaudio19-dev を入れてから pip で導入してください。




ubuntu@voice-server: ~
$ sudo apt-get install -y portaudio19-dev # 19.6.0-1.2build3
$ pip3 install pyaudio
Successfully installed pyaudio-0.2.14

②「CUDA not available」でエラーになる

GPUがない環境やコンテナ内では CUDA が使えません。WhisperModeldevice="cpu" を明示してください。compute_type="int8" を付けるとCPUでも高速です。




ubuntu@voice-server: ~
# ❌ GPU前提(GPU環境のみ動作)
model = WhisperModel(“base”, device=”cuda”)
# ✅ CPUを明示(GPUなしでも動く・int8で高速)
model = WhisperModel(“base”, device=”cpu”, compute_type=”int8″)

③Ollama の API に接続できない

コンテナが起動していないかポートが違う場合に起きます。docker ps/api/version で確認しましょう。




ubuntu@voice-server: ~
$ docker ps –filter “name=ollama”
8d90f25ce03b ollama/ollama:latest Up 0.0.0.0:11434->11434/tcp
$ curl -s http://localhost:11434/api/version
{“version”:”0.30.8″}

④piper で「model config not found」または日本語が文字化けする

.onnx と同じディレクトリに .onnx.json が無いと起動しません。両方ダウンロードできているか確認してください。また前述のとおり piper公式に日本語音声は無いため、日本語テキストを英語音声に渡すとローマ字読みのような不自然な出力になります。日本語は VOICEVOX を使ってください。




ubuntu@voice-server: ~/voice-pipeline
$ ls -la *.onnx*
-rw-r–r– 60M en_US-amy-low.onnx
-rw-r–r– 4.9K en_US-amy-low.onnx.json
# 両ファイルが揃っていればOK

VPS で本格運用するなら

自宅PCでも動きますが、常時稼働させたい・外出先からも使いたいなら VPS が便利です。音声パイプラインはCPUで動きますが、LLMはRAMが多いほど大きなモデルを快適に動かせます。今回の llama3.2:1b なら RAM 4GB で十分、より賢い llama3.2:3b を使うなら 8GB 以上が目安です。応答速度を優先するなら、レイテンシの小さい東京リージョンがあるVPSを選ぶと有利です。

VPS 学習用の目安プラン 東京リージョン 日本語サポート 音声AI向き度
Vultr 2 vCPU / 4GB〜 あり なし(英語) ★★★★★
DigitalOcean 2 vCPU / 4GB〜 なし(最寄シンガポール) なし(英語) ★★★★☆
Linode (Akamai) 2 vCPU / 4GB〜 大阪リージョンあり なし(英語) ★★★★☆
ConoHa VPS 2 vCPU / 4GB〜 国内データセンター あり(日本語) ★★★★☆

日本語応答の速さを優先するなら東京リージョンのある Vultr が遅延を抑えやすく、国内サポートに拘るなら ConoHa VPS も選択肢になります。

VPS に Docker と Ollama をセットアップする具体的な手順は も参考にしてください。

まとめ

Ubuntu 24.04 LTS 上にローカル音声AIパイプラインを構築し、各段を実測しました。ポイントは以下のとおりです。

  • STTは faster-whisper 1.2.1(CPU・int8)。約4.3秒の音声を base で1.63秒、tiny で0.96秒に認識
  • LLMは Ollama v0.30.8 + llama3.2:1b。CPUで平均45.4 tok/s、応答は0.6〜3.2秒
  • TTSは piper-tts 1.4.2。CPUで RTF 0.34と高速だが、公式に日本語音声は無い(161音声/47言語中ja=0)
  • 日本語を喋らせるTTSは VOICEVOX 等に差し替える。STT・LLMは日本語のまま動く
  • CPUのみで1往復 約4.8秒。すべてローカル処理でAPIコストゼロ・プライバシー安全

「piperの日本語音声をダウンロード」と書かれた手順で詰まった人は、それが存在しないからです。STT・LLMはローカルで日本語が動くので、TTSだけ VOICEVOX に差し替えれば日本語の音声チャットボットが完成します。まずはCPUで動かして感触を掴み、速度や常時稼働が欲しくなったらVPSやGPUへ移行するのがおすすめです。

コメント

タイトルとURLをコピーしました