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.
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
TTS/ASR测试运行器
|
||||
便捷地运行各种测试组合
|
||||
|
||||
运行方式:
|
||||
python backend/tests/run_tests.py --help
|
||||
python backend/tests/run_tests.py unit
|
||||
python backend/tests/run_tests.py integration
|
||||
python backend/tests/run_tests.py simulate
|
||||
python backend/tests/run_tests.py all
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def run_command(cmd: list, cwd: str = None) -> int:
|
||||
"""运行命令并返回退出码"""
|
||||
print(f"\n执行: {' '.join(cmd)}")
|
||||
print("-" * 70)
|
||||
result = subprocess.run(cmd, cwd=cwd)
|
||||
return result.returncode
|
||||
|
||||
|
||||
def run_unit_tests(verbose: bool = False) -> int:
|
||||
"""运行单元测试"""
|
||||
print("\n" + "="*70)
|
||||
print("运行单元测试")
|
||||
print("="*70)
|
||||
|
||||
cmd = ['pytest', 'backend/tests/test_tts_asr_unit.py']
|
||||
if verbose:
|
||||
cmd.append('-v')
|
||||
|
||||
return run_command(cmd)
|
||||
|
||||
|
||||
def run_integration_tests(test_type: str = None, url: str = None, key: str = None) -> int:
|
||||
"""运行集成测试"""
|
||||
print("\n" + "="*70)
|
||||
print("运行集成测试")
|
||||
print("="*70)
|
||||
|
||||
cmd = ['python', 'backend/tests/test_tts_asr_integration.py']
|
||||
|
||||
if test_type:
|
||||
cmd.extend(['--test', test_type])
|
||||
|
||||
if url:
|
||||
cmd.extend(['--url', url])
|
||||
|
||||
if key:
|
||||
cmd.extend(['--key', key])
|
||||
|
||||
return run_command(cmd)
|
||||
|
||||
|
||||
def run_simulation(test_type: str = None) -> int:
|
||||
"""运行macOS模拟测试"""
|
||||
print("\n" + "="*70)
|
||||
print("运行macOS环境模拟测试")
|
||||
print("="*70)
|
||||
|
||||
if test_type == 'full':
|
||||
cmd = ['python', 'backend/tests/simulate_macos.py', '--full-simulation']
|
||||
elif test_type:
|
||||
cmd = ['python', 'backend/tests/simulate_macos.py', '--test', test_type]
|
||||
else:
|
||||
cmd = ['python', 'backend/tests/simulate_macos.py', '--full-simulation']
|
||||
|
||||
return run_command(cmd)
|
||||
|
||||
|
||||
def run_all_tests(url: str = None, key: str = None) -> int:
|
||||
"""运行所有测试"""
|
||||
print("\n" + "="*70)
|
||||
print("运行完整测试套件")
|
||||
print("="*70)
|
||||
|
||||
results = []
|
||||
|
||||
# 1. 单元测试
|
||||
print("\n[1/3] 单元测试")
|
||||
results.append(("单元测试", run_unit_tests(verbose=True)))
|
||||
|
||||
# 2. macOS模拟测试
|
||||
print("\n[2/3] macOS模拟测试")
|
||||
results.append(("macOS模拟", run_simulation(test_type='full')))
|
||||
|
||||
# 3. 集成测试(如果服务可用)
|
||||
print("\n[3/3] 集成测试")
|
||||
print("注意: 集成测试需要后端服务运行中")
|
||||
response = input("是否继续运行集成测试? [y/N]: ")
|
||||
|
||||
if response.lower() == 'y':
|
||||
results.append(("集成测试", run_integration_tests(url=url, key=key)))
|
||||
else:
|
||||
print("跳过集成测试")
|
||||
results.append(("集成测试", 0))
|
||||
|
||||
# 汇总结果
|
||||
print("\n" + "="*70)
|
||||
print("测试结果汇总")
|
||||
print("="*70)
|
||||
|
||||
total_passed = 0
|
||||
for name, code in results:
|
||||
status = "✓ 通过" if code == 0 else "✗ 失败"
|
||||
print(f"{name}: {status}")
|
||||
if code == 0:
|
||||
total_passed += 1
|
||||
|
||||
print("\n" + "-"*70)
|
||||
print(f"总计: {total_passed}/{len(results)} 测试套件通过")
|
||||
print("="*70)
|
||||
|
||||
return 0 if all(code == 0 for _, code in results) else 1
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='TTS/ASR测试运行器',
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
示例:
|
||||
# 运行单元测试
|
||||
python backend/tests/run_tests.py unit
|
||||
|
||||
# 运行集成测试
|
||||
python backend/tests/run_tests.py integration
|
||||
|
||||
# 运行macOS模拟测试
|
||||
python backend/tests/run_tests.py simulate
|
||||
|
||||
# 运行所有测试
|
||||
python backend/tests/run_tests.py all
|
||||
|
||||
# 运行特定集成测试
|
||||
python backend/tests/run_tests.py integration --test config
|
||||
|
||||
# 运行特定模拟测试
|
||||
python backend/tests/run_tests.py simulate --test device
|
||||
"""
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest='command', help='测试类型')
|
||||
|
||||
# 单元测试
|
||||
unit_parser = subparsers.add_parser('unit', help='运行单元测试')
|
||||
unit_parser.add_argument('-v', '--verbose', action='store_true', help='详细输出')
|
||||
|
||||
# 集成测试
|
||||
integration_parser = subparsers.add_parser('integration', help='运行集成测试')
|
||||
integration_parser.add_argument('--test', choices=[
|
||||
'config', 'status', 'warmup', 'tts', 'asr', 'perf'
|
||||
], help='运行特定测试')
|
||||
integration_parser.add_argument('--url', default='http://localhost:8001', help='API URL')
|
||||
integration_parser.add_argument('--key', default='your-secret-key-here', help='API密钥')
|
||||
|
||||
# macOS模拟测试
|
||||
simulate_parser = subparsers.add_parser('simulate', help='运行macOS模拟测试')
|
||||
simulate_parser.add_argument('--test', choices=[
|
||||
'device', 'memory', 'model', 'audio', 'env', 'full'
|
||||
], help='运行特定测试')
|
||||
|
||||
# 所有测试
|
||||
all_parser = subparsers.add_parser('all', help='运行所有测试')
|
||||
all_parser.add_argument('--url', default='http://localhost:8001', help='API URL')
|
||||
all_parser.add_argument('--key', default='your-secret-key-here', help='API密钥')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 确保在项目根目录
|
||||
project_root = Path(__file__).parent.parent.parent
|
||||
os.chdir(project_root)
|
||||
|
||||
if args.command == 'unit':
|
||||
return run_unit_tests(verbose=args.verbose)
|
||||
|
||||
elif args.command == 'integration':
|
||||
return run_integration_tests(
|
||||
test_type=args.test,
|
||||
url=args.url,
|
||||
key=args.key
|
||||
)
|
||||
|
||||
elif args.command == 'simulate':
|
||||
return run_simulation(test_type=args.test)
|
||||
|
||||
elif args.command == 'all':
|
||||
return run_all_tests(url=args.url, key=args.key)
|
||||
|
||||
else:
|
||||
parser.print_help()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user