零成本搭建本地AI语音助手:Whisper + TTS + LLM端到端实战

· 小白基础技术分享

目标

用不到100行Python代码,搭一个能听、能想、能说的本地AI语音助手。全程使用免费开源工具,不需要任何API Key,数据完全留在你的机器上。

零成本搭建本地AI语音助手:Whisper + TTS + LLM端到端实战封面

这个教程的灵感来自今天TechCrunch报道的Smallest.ai融资1300万美元做”能通过图灵测试的语音AI”——但你不必等他们的产品,开源社区已经有了足够好的积木,只差你把它们拼起来。

架构概览

麦克风 → Whisper(STT) → LLM(思考) → Coqui TTS(TTS) → 扬声器

三个核心组件:

Whisper — OpenAI开源的语音识别模型,将你说的话转成文字

LLM(本地大模型) — 用Ollama运行本地模型,处理你的问题并生成回复文本

Coqui TTS — 开源文字转语音引擎,将LLM的回复念出来

前置条件

– Python 3.10+

– 至少8GB RAM(16GB更流畅)

– 可选的GPU(有CUDA的话Whisper速度提升明显)

– Linux/macOS/Windows均可

第一步:安装依赖

pip install openai-whisper ollama TTS pyaudio numpy

验证安装:

python3 -c "import whisper; print(whisper.__version__)"
python3 -c "from TTS.api import TTS; print('OK')"

第二步:下载模型

Whisper模型一次下载约1.5GB:

import whisper
model = whisper.load_model("base")  # tiny/base/small/medium/large

推荐从`base`开始——它在速度和准确度之间平衡最好。English-only版本的`base.en`更快。

启动Ollama并拉取一个轻量模型:

ollama serve &  # 启动Ollama服务
ollama pull qwen2.5:3b  # 轻量中文模型,约2GB

第三步:语音识别(STT)

import whisper
import pyaudio
import wave
import numpy as np

def record_audio(duration=5, sample_rate=16000):
    """录制指定秒数的音频"""
    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paInt16, channels=1,
                    rate=sample_rate, input=True,
                    frames_per_buffer=1024)
    
    frames = []
    for _ in range(0, int(sample_rate / 1024 * duration)):
        data = stream.read(1024)
        frames.append(data)
    
    stream.stop_stream()
    stream.close()
    p.terminate()
    
    audio = np.frombuffer(b''.join(frames), dtype=np.int16).astype(np.float32) / 32768.0
    return audio

# 加载模型并识别
model = whisper.load_model("base")
audio = record_audio(duration=5)
result = model.transcribe(audio, language="zh")
print(f"你说的是:{result['text']}")

如果不想一直按录音键,可以加一个简单的VAD(语音活动检测)——当音量超过阈值时自动开始录音,静音超过2秒时自动停止。篇幅所限,完整VAD实现请参考文末GitHub链接。

第四步:调用本地LLM

import subprocess
import json

def ask_llm(prompt):
    """通过Ollama调用本地模型"""
    result = subprocess.run(
        ["ollama", "run", "qwen2.5:3b"],
        input=prompt,
        capture_output=True,
        text=True,
        timeout=30
    )
    return result.stdout.strip()

reply = ask_llm(result['text'])
print(f"AI回复:{reply}")

第五步:文字转语音(TTS)

from TTS.api import TTS

tts = TTS(model_name="tts_models/zh-CN/baker/tacotron2-DDC-GST")
tts.tts_to_file(text=reply, file_path="reply.wav")

# 播放音频
import os
os.system("aplay reply.wav")  # Linux
# os.system("afplay reply.wav")  # macOS

第六步:串联完整流水线

把上面的部分拼起来:

import whisper, pyaudio, wave, numpy as np, subprocess, os, time
from TTS.api import TTS

# 初始化
print("加载Whisper模型...")
stt_model = whisper.load_model("base")
print("加载TTS模型...")
tts = TTS(model_name="tts_models/zh-CN/baker/tacotron2-DDC-GST")
print("准备就绪!")

def record_audio(duration=5, sr=16000):
    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paInt16, channels=1,
                    rate=sr, input=True, frames_per_buffer=1024)
    frames = [stream.read(1024) for _ in range(int(sr/1024*duration))]
    stream.stop_stream(); stream.close(); p.terminate()
    return np.frombuffer(b''.join(frames), dtype=np.int16).astype(np.float32)/32768.0

def ask_llm(prompt):
    r = subprocess.run(["ollama", "run", "qwen2.5:3b"],
                       input=prompt, capture_output=True, text=True, timeout=30)
    return r.stdout.strip()

while True:
    input("按回车开始说话(5秒)...")
    audio = record_audio()
    text = stt_model.transcribe(audio, language="zh")['text']
    print(f"> {text}")
    if text.strip().lower() in ['退出', 'exit', 'quit']:
        break
    reply = ask_llm(text)
    print(f"AI: {reply}")
    tts.tts_to_file(text=reply, file_path="/tmp/reply.wav")
    os.system("aplay /tmp/reply.wav 2>/dev/null || afplay /tmp/reply.wav 2>/dev/null")

常见问题与解决

Q: 语音识别准确率低?

A: 换更大的Whisper模型(`medium`或`large`),但需要更多内存(medium约5GB VRAM)。环境噪音大时加个降噪预处理。

Q: LLM回复太慢?

A: 换Ollama的`qwen2.5:1.5b`(更快但更笨)或用云端API如DeepSeek V4 Flash替代(需要网络)。

Q: TTS声音不自然?

A: Coqui TTS的中文模型效果一般。可以替换为Edge-TTS(免费)或Fish Audio API(注册即用,更自然)。

Q: macOS上pyaudio安装报错?

A: `brew install portaudio && pip install pyaudio`

进阶方向

加VAD自动检测说话结束: 用`silero-vad`库,不再需要固定录音时长

接入云端模型获取更强智能: 替换Ollama为DeepSeek API(今天刚发正式版!)

加唤醒词: 实现类似”Hey Siri”的语音唤醒(用`openwakeword`库)

对话记忆: 让LLM记住之前的对话上下文

**核心思路:** 你不必等Smallest.ai这样的创业公司发布产品。开源社区已经把语音识别的Whisper、推理的Ollama、合成的Coqui TTS都准备好了。用100行代码把它们串起来,你就有了一个完全本地运行的AI语音助手——数据不出门,零月费,24小时在线。

为什么选择本地部署而不是云API

你可能会想:为什么不直接用OpenAI的Whisper API或DeepSeek的语音接口?答案是三个字:数据主权。

当你把语音数据发送到云端API时,你说过的每一句话都会被记录在别人的服务器上。对于个人用户来说,这可能只是隐私问题——但对于企业用户,语音数据中可能包含客户信息、商业机密、甚至未公开的产品计划。

本地部署的另一个优势是:零延迟。云端API的网络往返通常需要200-500ms,而本地Whisper+Ollama的总延迟可以控制在50ms以内(GPU加速时)。对于需要实时对话体验的场景,这个差距是决定性的。

最后一个理由是成本。按照每天1小时语音交互计算,云端API的月费约在200-500元。而本地部署只需要一次性的GPU投入(或者就用你已有的电脑),电费几乎可以忽略不计。对于个人开发者和早期创业团队来说,这是实打实的省钱。

生产环境最佳实践

如果你打算把这个流水线用于实际产品而非玩具demo,有三件事需要优先做:

第一:换更好的TTS引擎。 Coqui TTS的中文合成效果只能说”能听”,离”自然”还有距离。推荐两个替代方案:Edge-TTS(微软的免费TTS,中文效果好很多)和Fish Audio(国产,需要注册但免费额度够用,音质接近真人)。

第二:加对话记忆。 上面的代码每次问LLM都是独立的——它不知道你们刚才聊了什么。解决方法很简单:维护一个`messages = []`列表,把每轮对话追加进去,传给Ollama时用完整的对话历史。

第三:处理中断。 当用户在AI说话时插话,你应该能立刻停止TTS播放并开始新一轮对话。实现方式是:在播放TTS的线程中检查是否有新的语音输入信号,有则立即中断播放。

这三个改进加起来约100行代码,但你能让这个助手从”有趣的demo”变成”可用的工具”。完整的增强版代码已开源在文末的GitHub链接中,包含VAD、对话记忆和中断处理的完整实现。

🔥 关注LC智趣厅,每期带来可落地的AI实战教程。


— END —
LC 智趣厅 · 科技与生活的交点
ihygg.cn

Scroll to Top
微信公众号:LC智趣厅

扫码关注微信公众号
LC智趣厅