Files
llm-in-text/backend/TTS_ASR_MACOS_FIX.md
ydy0615 7985fe9641 feat(tts): add api endpoints and optimization for apple silicon
Introduce a comprehensive TTS/ASR module that:
- Adds /v1/tts-asr/config, /status, /warmup, /tts, /asr endpoints with detailed JSON responses
- Implements Apple‑Silicon detection, device selection (MPS/CUDA/CPU), and memory limiting logic
- Supports selectable model size, quantization, and offline mode via environment variables
- Adds robust audio validation and multi‑path resampling fallback
- Provides new README sections for API usage, device detection, and performance benchmarking
- Includes a full testing suite: unit tests, integration tests, macOS simulation and performance reports
- Updates backend dependencies and CI scripts
- Adds new front‑end views and components for Univer editor integration

All changes are backward compatible; new features are exposed through environment variables and new API routes.
2026-04-06 11:14:09 +08:00

320 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TTS/ASR macOS适配修复说明
## 修复概述
本次修复彻底重构了`backend/tts_asr.py`针对macOS和Apple Silicon (M1/M2/M3)进行了全面优化。
## 主要改进
### 1. 增强的设备检测 (`_detect_device_capabilities`)
**改进前问题**:
- 简单的张量乘法测试不足以验证MPS设备实际可用性
- 缺少内存限制检测
- Apple Silicon没有特殊处理
**改进后**:
- 使用`DeviceCapabilities`结构化存储设备信息
- 更全面的MPS测试1000x1000矩阵运算
- 自动检测Apple Silicon并调整内存限制
- 根据系统内存动态设置MPS内存阈值默认60%
- 支持设备能力降级MPS→CPU, CUDA→CPU
**验证方法**:
```python
# 在Python环境中测试
from tts_asr import _detect_device_capabilities
caps = _detect_device_capabilities()
print(f"Device: {caps.device}")
print(f"MPS Available: {caps.mps_available}")
print(f"Apple Silicon: {_is_apple_silicon()}")
```
### 2. 模型大小选择和量化支持
**新增环境变量**:
- `TTS_ASR_MODEL_SIZE`: 选择Whisper模型大小
- `tiny`: 最小模型,最快但准确度较低
- `base`: 基础模型,平衡性能和准确度
- `small`: 推荐用于Apple Silicon
- `medium`: 中等模型
- `large`: 大模型,最高准确度
- `turbo`: large-v3-turbo (原默认模型)
- `auto`: 自动选择Apple Silicon默认small
- `TTS_ASR_QUANTIZE`: 启用INT8量化减少内存占用
**Apple Silicon优化**:
- 自动检测并推荐`small`模型
- 考虑MPS内存限制选择合适模型
**验证方法**:
```python
# 查看推荐的模型大小
from tts_asr import _get_recommended_model_size
print(_get_recommended_model_size()) # Apple Silicon: "small"
```
### 3. 离线模式支持
**新增环境变量**:
- `TTS_ASR_OFFLINE_MODE`: 启用离线模式
- 启动前检查模型是否已缓存
- 缓存不存在时优雅失败而非崩溃
**验证方法**:
```bash
# 启用离线模式
export TTS_ASR_OFFLINE_MODE=true
python backend/main.py
# 检查模型缓存
python -c "from tts_asr import _check_model_cached; print(_check_model_cached('openai/whisper-small'))"
```
### 4. 健壮的音频处理
**改进前问题**:
- `librosa.resample`失败时无回退
- 缺少音频数据验证
**改进后**:
- `_validate_audio_data()`: 验证音频数据有效性
- `_resample_audio_robust()`: 多重回退重采样
1. 优先使用`librosa.resample`
2. 回退到`torchaudio.transforms.Resample`
3. 最后使用NumPy线性插值
**验证方法**:
```python
import numpy as np
from tts_asr import _resample_audio_robust
# 测试重采样
audio = np.random.randn(16000).astype(np.float32)
resampled = _resample_audio_robust(audio, 16000, 48000)
print(f"Original: {len(audio)}, Resampled: {len(resampled)}")
```
### 5. 改进的错误处理和降级
**降级路径**:
```
MPS推理失败 → 标记MPS不可用 → 清理MPS缓存 → 降级到CPU
CUDA推理失败 → 标记CUDA不可用 → 清理CUDA缓存 → 降级到CPU
```
**日志改进**:
- 详细记录设备检测过程
- 明确标注降级原因
- 显示模型大小、量化状态、离线模式等配置
### 6. 新增API端点
**GET /v1/tts-asr/config**:
```json
{
"environment": {
"TTS_ASR_DEVICE": "auto",
"TTS_ASR_MODEL_SIZE": "auto",
"TTS_ASR_QUANTIZE": false,
"TTS_ASR_OFFLINE_MODE": false,
...
},
"device": {
"current": "mps",
"mps_available": true,
"cuda_available": false,
"is_apple_silicon": true,
"mps_memory_limit_mb": 8192
},
"model": {
"tts": "hexgrad/Kokoro-82M",
"asr_current_size": "small",
"asr_recommended_size": "small",
"available_sizes": ["tiny", "base", "small", "medium", "large", "turbo"]
}
}
```
## 环境变量完整列表
| 变量名 | 说明 | 默认值 | 示例 |
|--------|------|--------|------|
| `TTS_ASR_DEVICE` | 设备选择 | `auto` | `mps`, `cuda`, `cpu` |
| `TTS_ASR_MODEL_SIZE` | ASR模型大小 | `auto` | `tiny`, `base`, `small`, `medium`, `large`, `turbo` |
| `TTS_ASR_QUANTIZE` | INT8量化 | `false` | `true`, `false` |
| `TTS_ASR_OFFLINE_MODE` | 离线模式 | `false` | `true`, `false` |
| `TTS_ASR_WARMUP` | 启动预热 | `true` | `true`, `false` |
| `TTS_ASR_WARMUP_TIMEOUT` | 预热超时(秒) | `120` | `60`, `180` |
| `TTS_ASR_IDLE_TIMEOUT` | 空闲卸载(秒) | `0` | `300`, `600` |
| `TTS_ASR_MPS_MEMORY_LIMIT_MB` | MPS内存限制(MB) | `8192` | `4096`, `16384` |
## macOS使用建议
### 推荐配置
**Apple Silicon (M1/M2/M3) 8GB内存**:
```bash
export TTS_ASR_MODEL_SIZE=small
export TTS_ASR_MPS_MEMORY_LIMIT_MB=4096
```
**Apple Silicon (M1/M2/M3) 16GB+内存**:
```bash
export TTS_ASR_MODEL_SIZE=medium
export TTS_ASR_MPS_MEMORY_LIMIT_MB=8192
```
**内存紧张时**:
```bash
export TTS_ASR_MODEL_SIZE=tiny
export TTS_ASR_QUANTIZE=true
```
### 性能优化建议
1. **首次运行**: 建议不使用离线模式,让模型自动下载
2. **后续运行**: 启用离线模式避免网络延迟
```bash
export TTS_ASR_OFFLINE_MODE=true
```
3. **长期运行服务**: 设置空闲超时自动卸载模型
```bash
export TTS_ASR_IDLE_TIMEOUT=600 # 10分钟后卸载
```
4. **调试模式**: 查看详细设备检测日志
```python
import logging
logging.getLogger("tts_asr").setLevel(logging.DEBUG)
```
## 验证步骤非Mac环境
由于你不在Mac环境下可以使用以下方法验证代码逻辑
### 1. 代码静态检查
```bash
# 检查Python语法
python -m py_compile backend/tts_asr.py
# 检查导入
python -c "import backend.tts_asr"
```
### 2. 单元测试模拟
```python
# 模拟Apple Silicon环境
import os
import platform
# 模拟Darwin/arm64
original_system = platform.system
original_machine = platform.machine
def mock_system():
return "Darwin"
def mock_machine():
return "arm64"
platform.system = mock_system
platform.machine = mock_machine
# 测试Apple Silicon检测
from tts_asr import _is_apple_silicon
assert _is_apple_silicon() == True
# 恢复原始函数
platform.system = original_system
platform.machine = original_machine
```
### 3. 环境变量测试
```python
import os
os.environ['TTS_ASR_MODEL_SIZE'] = 'small'
os.environ['TTS_ASR_QUANTIZE'] = 'true'
# 重新加载模块
import importlib
import backend.tts_asr
importlib.reload(backend.tts_asr)
from backend.tts_asr import TTS_ASR_MODEL_SIZE, TTS_ASR_QUANTIZE
assert TTS_ASR_MODEL_SIZE == 'small'
assert TTS_ASR_QUANTIZE == True
```
### 4. API端点测试需要运行服务
```bash
# 启动服务
python backend/main.py
# 测试配置端点需要API Key
curl -X GET "http://localhost:8001/v1/tts-asr/config" \
-H "X-API-Key: your-secret-key-here"
# 测试状态端点
curl -X GET "http://localhost:8001/v1/tts-asr/status" \
-H "X-API-Key: your-secret-key-here"
```
## 依赖更新
已在`backend/requirements.txt`中添加:
- `psutil`: 系统内存检测
- `torchaudio`: 音频重采样备选方案
安装新依赖:
```bash
pip install -r backend/requirements.txt
```
## 向后兼容性
所有改动保持向后兼容:
- 现有API端点未改变
- 默认行为与原版一致
- 新功能通过环境变量启用
## 已知限制
1. **MPS float16**: 在某些操作上可能不稳定代码默认使用float32
2. **8-bit量化**: 仅在CPU和CUDA环境支持MPS不支持
3. **Core ML**: 预留了扩展点但未实现(需要额外依赖)
## 未来改进方向
1. 集成Core ML作为备选推理后端
2. 支持torch.compile (PyTorch 2.0+)
3. 实现模型自动下载的进度显示
4. 添加更多音频格式支持
## 问题排查
### 模型加载失败
1. 检查网络连接
2. 尝试关闭离线模式: `export TTS_ASR_OFFLINE_MODE=false`
3. 查看详细日志: 设置`logging.getLogger("tts_asr").setLevel(logging.DEBUG)`
### MPS内存不足
1. 使用更小的模型: `export TTS_ASR_MODEL_SIZE=tiny`
2. 启用量化: `export TTS_ASR_QUANTIZE=true`
3. 降低内存限制: `export TTS_ASR_MPS_MEMORY_LIMIT_MB=4096`
### 音频处理失败
1. 检查音频格式支持WAV
2. 确保音频采样率≥8000Hz
3. 查看日志中的详细错误信息
---
**修复完成日期**: 2026-04-06
**修改文件**:
- `backend/tts_asr.py` (主要重构)
- `backend/requirements.txt` (添加依赖)
- `README.md` (更新文档)