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.
8.1 KiB
8.1 KiB
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环境中测试
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 Siliconmedium: 中等模型large: 大模型,最高准确度turbo: large-v3-turbo (原默认模型)auto: 自动选择(Apple Silicon默认small)
-
TTS_ASR_QUANTIZE: 启用INT8量化(减少内存占用)
Apple Silicon优化:
- 自动检测并推荐
small模型 - 考虑MPS内存限制选择合适模型
验证方法:
# 查看推荐的模型大小
from tts_asr import _get_recommended_model_size
print(_get_recommended_model_size()) # Apple Silicon: "small"
3. 离线模式支持
新增环境变量:
TTS_ASR_OFFLINE_MODE: 启用离线模式- 启动前检查模型是否已缓存
- 缓存不存在时优雅失败而非崩溃
验证方法:
# 启用离线模式
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(): 多重回退重采样- 优先使用
librosa.resample - 回退到
torchaudio.transforms.Resample - 最后使用NumPy线性插值
- 优先使用
验证方法:
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:
{
"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内存:
export TTS_ASR_MODEL_SIZE=small
export TTS_ASR_MPS_MEMORY_LIMIT_MB=4096
Apple Silicon (M1/M2/M3) 16GB+内存:
export TTS_ASR_MODEL_SIZE=medium
export TTS_ASR_MPS_MEMORY_LIMIT_MB=8192
内存紧张时:
export TTS_ASR_MODEL_SIZE=tiny
export TTS_ASR_QUANTIZE=true
性能优化建议
-
首次运行: 建议不使用离线模式,让模型自动下载
-
后续运行: 启用离线模式避免网络延迟
export TTS_ASR_OFFLINE_MODE=true -
长期运行服务: 设置空闲超时自动卸载模型
export TTS_ASR_IDLE_TIMEOUT=600 # 10分钟后卸载 -
调试模式: 查看详细设备检测日志
import logging logging.getLogger("tts_asr").setLevel(logging.DEBUG)
验证步骤(非Mac环境)
由于你不在Mac环境下,可以使用以下方法验证代码逻辑:
1. 代码静态检查
# 检查Python语法
python -m py_compile backend/tts_asr.py
# 检查导入
python -c "import backend.tts_asr"
2. 单元测试模拟
# 模拟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. 环境变量测试
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端点测试(需要运行服务)
# 启动服务
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: 音频重采样备选方案
安装新依赖:
pip install -r backend/requirements.txt
向后兼容性
所有改动保持向后兼容:
- 现有API端点未改变
- 默认行为与原版一致
- 新功能通过环境变量启用
已知限制
- MPS float16: 在某些操作上可能不稳定,代码默认使用float32
- 8-bit量化: 仅在CPU和CUDA环境支持,MPS不支持
- Core ML: 预留了扩展点但未实现(需要额外依赖)
未来改进方向
- 集成Core ML作为备选推理后端
- 支持torch.compile (PyTorch 2.0+)
- 实现模型自动下载的进度显示
- 添加更多音频格式支持
问题排查
模型加载失败
- 检查网络连接
- 尝试关闭离线模式:
export TTS_ASR_OFFLINE_MODE=false - 查看详细日志: 设置
logging.getLogger("tts_asr").setLevel(logging.DEBUG)
MPS内存不足
- 使用更小的模型:
export TTS_ASR_MODEL_SIZE=tiny - 启用量化:
export TTS_ASR_QUANTIZE=true - 降低内存限制:
export TTS_ASR_MPS_MEMORY_LIMIT_MB=4096
音频处理失败
- 检查音频格式(支持WAV)
- 确保音频采样率≥8000Hz
- 查看日志中的详细错误信息
修复完成日期: 2026-04-06
修改文件:
backend/tts_asr.py(主要重构)backend/requirements.txt(添加依赖)README.md(更新文档)