图像与设计
在本地部署 Gemma 4 + Kokoro TTS…
适用于在 macOS Apple Silicon 或 Linux GPU 上,以完全本地方式运行可听可看的实时语音 AI 助手,并按步骤完成安装、配置、扩展和问题排查。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在本地部署 Gemma 4 + Koko特定
解决思路
- 整体数据流:浏览器采集麦克风和摄像头,通过 WebSocket 发送 PCM 音频和 JPEG 帧到 FastAPI 服务器;服务器用 Gemma 4 E2B via LiteRT-LM 理解语音和视觉,再用 Kokoro TTS 流式回传音频到浏览器播放和显示转写。
- 安装:`git clone https://github.com/fikrikarim/parlor.git`;`cd parlor`。
- 安装 uv(如未安装):`curl -LsSf https://astral.sh/uv/install.sh | sh`。
- 同步依赖:`cd src`;`uv sync`。
- 启动服务:`uv run server.py`。
- 打开 `http://localhost:8000`,授予摄像头和麦克风权限,然后开始说话。
- 首次运行会自动下载模型(约 2.6 GB 的 Gemma 4 E2B 加 TTS 模型)。
- 指定本地模型:`export MODEL_PATH=/path/to/gemma-4-E2B-it.litertlm`,避免自动从 HuggingFace 下载。
- 修改端口:`export PORT=9000`(默认 8000),然后 `uv run server.py`。
- 按项目结构定位修改点:`src/server.py` 是 FastAPI WebSocket 服务器 + Gemma 4 推理;`src/tts.py` 是平台感知 TTS;`src/index.html` 是前端 UI(VAD、摄像头、音频播放);`src/pyproject.toml` 是依赖;`src/benchmarks/bench.py` 是端到端 WebSocket 基准;`src/benchmarks/benchmark_tts.py` 是 TTS 后端比较。
- 实现 FastAPI WebSocket 服务:在 `server.py` 中创建 `/ws` endpoint,`await websocket.accept()`,用 `async for data in websocket.iter_bytes()` 接收包含 PCM 音频和可选 JPEG 帧的数据,调用 `run_gemma_inference(data)` 得到文本,再调用 `run_tts(response_text)` 得到音频块,对每个音频块执行 `await websocket.send_bytes(chunk)`。
- 实现平台感知 TTS:在 `tts.py` 中检测平台,`platform.system() == 'Darwin'` 时使用 `kokoro_mlx.KokoroMLX`,否则使用 `kokoro.KokoroPipeline(lang_code='a')`。
- 实现句子级流式 TTS:编写 `synthesize_streaming(text)`,遍历 `split_sentences(text)`,对每句调用 `tts.synthesize(sentence)` 并 `yield` 音频,使音频在完整回复生成前就开始播放。
- 实现 Gemma 4 E2B 推理:使用 `litert_lm.LiteRTLM.from_pretrained('google/gemma-4-E2B-it', local_path=model_path)`,其中 `model_path = os.environ.get('MODEL_PATH', None)`;未设置时自动下载。
- 构建多模态输入:`inputs = {'audio': audio_pcm}`;如果有 `image_jpeg`,加入 `inputs['image'] = image_jpeg`;用 `async for token in model.generate_stream(**inputs)` 累积响应文本。
- 前端实现 hands-free:使用 Silero VAD 在浏览器执行语音活动检测,配置 `MicVAD.new({ positiveSpeechThreshold: 0.6, negativeSpeechThreshold: 0.35, minSpeechFrames: 3, onSpeechStart: ..., onSpeechEnd: (audio) => sendAudioToServer(audio) })`;降低 `positiveSpeechThreshold` 会更敏感。
- 实现 barge-in:AI 播放回复时持续运行 VAD,一旦检测到用户再次说话就停止当前音频播放并发送新音频,以打断 AI 当前回复。
- 运行端到端 WebSocket 延迟基准:`cd src`;`uv run benchmarks/bench.py`。
- 比较 TTS 后端(MLX vs ONNX):`cd src`;`uv run benchmarks/benchmark_tts.py`。
- 参考性能(Apple M3 Pro):语音+视觉理解约 1.8–2.2s;生成约 25 tokens 约 0.3s;TTS 1–3 句约 0.3–0.7s;端到端总计约 2.5–3.0s;GPU 解码速度约 83 tokens/sec。
- 修改系统提示词:在 `server.py` 中编辑 `SYSTEM_PROMPT`,例如改成语言导师、要求 1–3 句对话、纠正语法、结合摄像头画面讨论。
- 添加 TTS 语言:在 `tts.py` 设置 `KokoroPipeline(lang_code='e')`;语言码包括 `'a'` 美式英语、`'b'` 英式英语、`'e'` 西班牙语、`'f'` 法语、`'z'` 中文、`'j'` 日语。
- 用程序发送帧:用 `websockets.connect('ws://localhost:8000/ws')`;构造 `payload = {'audio': base64.b64encode(audio_pcm_bytes).decode()}`,如有图像加 `payload['image'] = base64.b64encode(jpeg_bytes).decode()`;`await ws.send(json.dumps(payload))`;然后 `async for message in ws` 接收原始 PCM 音频块。
- 模型下载失败时:用 `huggingface_hub.hf_hub_download('google/gemma-4-E2B-it', 'gemma-4-E2B-it.litertlm')` 手动预下载,打印路径后 `export MODEL_PATH=/path/shown/above`,再 `uv run server.py`。
- 浏览器麦克风/摄像头不工作时:必须通过 `http://localhost` 访问(不能用 IP 地址),并检查浏览器权限,在地址栏锁图标里重置权限。
- Linux 上 TTS 未加载时:`uv add onnxruntime`,或 GPU 版本 `uv add onnxruntime-gpu`。
- 延迟高或推理慢时:检查启动日志是否使用 Metal(Mac)或 CUDA(Linux),关闭其他占用 GPU 的应用;Linux 上确认 CUDA 驱动与 `onnxruntime-gpu` 版本匹配。
- 端口被占用时:`export PORT=8080` 后 `uv run server.py`,或 `lsof -ti:8000 | xargs kill` 杀掉现有进程。
- `uv sync` 因 Python 版本不匹配失败时:`python3 --version` 检查;安装 3.12(pyenv 或系统包管理器),然后 `uv python pin 3.12`;`uv sync`。
- 依赖由 `uv sync` 安装,关键包包括 `litert-lm`、`fastapi` + `uvicorn`、`kokoro`、`kokoro-mlx`(Mac only)、`silero-vad`(浏览器侧通过 CDN)、`huggingface-hub`。
适用边界 · 注意事项
- 不适用于没有 macOS Apple Silicon 或 Linux 支持 GPU、无法满足 Python 3.12+ / uv、或可用内存不足约 3 GB 的环境;CPU-only 或资源不足会导致无法运行或延迟很高。
- 不适用于希望使用云端 API、托管服务、多租户生产部署或 API Key 管理而非完全本地推理的场景。
- 不适用于无法接受首次下载约 2.6 GB Gemma 模型及额外 TTS 模型、或不能通过 http://localhost 访问浏览器的环境。