test.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. """
  2. 语音唤醒模块测试脚本
  3. 测试各个组件的基本功能
  4. """
  5. import asyncio
  6. import sys
  7. from pathlib import Path
  8. # 添加模块路径
  9. # sys.path.insert(0, str(Path(__file__).parent))
  10. sys.path.insert(0, str(Path(__file__).parent.parent))
  11. from wake_word_module import WakeWordDetector, AudioCapture, WakeWordConfig
  12. def test_config():
  13. """测试配置类"""
  14. print("\n" + "=" * 60)
  15. print("测试 1: 配置类")
  16. print("=" * 60)
  17. try:
  18. config = WakeWordConfig(
  19. model_path="models",
  20. sample_rate=16000,
  21. keywords_threshold=0.2,
  22. )
  23. print(f"✅ 配置创建成功")
  24. print(f" 采样率: {config.sample_rate}Hz")
  25. print(f" 阈值: {config.keywords_threshold}")
  26. print(f" 冷却时间: {config.detection_cooldown}s")
  27. # 尝试验证(如果模型文件存在)
  28. try:
  29. config.validate()
  30. print(f"✅ 配置验证通过")
  31. except FileNotFoundError as e:
  32. print(f"⚠️ 配置验证跳过(模型文件不存在): {e}")
  33. return True
  34. except Exception as e:
  35. print(f"❌ 配置测试失败: {e}")
  36. return False
  37. def test_audio_capture():
  38. """测试音频采集器"""
  39. print("\n" + "=" * 60)
  40. print("测试 2: 音频采集器")
  41. print("=" * 60)
  42. try:
  43. # 列出设备
  44. print("\n列出可用设备:")
  45. AudioCapture.list_devices()
  46. # 创建采集器
  47. audio_capture = AudioCapture(
  48. sample_rate=16000,
  49. channels=1,
  50. device_id=None,
  51. )
  52. print(f"✅ 音频采集器创建成功")
  53. print(f" 采样率: {audio_capture.sample_rate}Hz")
  54. print(f" 声道数: {audio_capture.channels}")
  55. print(f" 帧大小: {audio_capture.frame_size}")
  56. return True
  57. except Exception as e:
  58. print(f"❌ 音频采集器测试失败: {e}")
  59. return False
  60. async def test_detector():
  61. """测试检测器"""
  62. print("\n" + "=" * 60)
  63. print("测试 3: 检测器")
  64. print("=" * 60)
  65. try:
  66. config = WakeWordConfig(
  67. model_path="models",
  68. sample_rate=16000,
  69. )
  70. # 尝试创建检测器
  71. try:
  72. detector = WakeWordDetector(config)
  73. print(f"✅ 检测器创建成功")
  74. print(f" 配置: {detector.config.model_path}")
  75. # 测试回调设置
  76. detector.on_detected(lambda r, t: print(f"检测: {r}"))
  77. detector.on_error(lambda e: print(f"错误: {e}"))
  78. print(f"✅ 回调设置成功")
  79. return True
  80. except FileNotFoundError as e:
  81. print(f"⚠️ 检测器创建跳过(模型文件不存在): {e}")
  82. return True # 不算失败,只是缺少模型文件
  83. except Exception as e:
  84. print(f"❌ 检测器测试失败: {e}")
  85. return False
  86. except Exception as e:
  87. print(f"❌ 检测器测试失败: {e}")
  88. return False
  89. async def test_integration():
  90. """集成测试"""
  91. print("\n" + "=" * 60)
  92. print("测试 4: 集成测试 - 唤醒词灵敏度测试")
  93. print("=" * 60)
  94. try:
  95. config = WakeWordConfig(
  96. model_path="models",
  97. sample_rate=16000,
  98. )
  99. audio_capture = AudioCapture(sample_rate=16000, channels=1)
  100. try:
  101. detector = WakeWordDetector(config)
  102. # 唤醒词检测统计
  103. detection_count = 0
  104. detection_times = []
  105. def on_detected(result, *args):
  106. nonlocal detection_count, detection_times
  107. detection_count += 1
  108. import time
  109. detection_times.append(time.time())
  110. # 尝试获取打分信息
  111. score = "未知"
  112. if hasattr(result, 'score'):
  113. score = result.score
  114. print(f"🎉 检测到唤醒词! (次数: {detection_count}, 打分: {score})")
  115. detector.on_detected(on_detected)
  116. # 连接
  117. audio_capture.add_audio_listener(detector)
  118. print(f"✅ 音频采集器和检测器连接成功")
  119. # 启动
  120. await audio_capture.start()
  121. await detector.start()
  122. print(f"✅ 系统启动成功")
  123. # 运行 60 秒进行测试
  124. test_duration = 60
  125. print(f"\n运行 {test_duration} 秒进行唤醒词灵敏度测试...")
  126. print("请在这段时间内说出唤醒词,测试系统的检测效果")
  127. import time
  128. start_time = time.time()
  129. while time.time() - start_time < test_duration:
  130. await asyncio.sleep(0.1)
  131. if detection_count > 0:
  132. # 每检测到一次唤醒词,显示剩余时间
  133. remaining = max(0, test_duration - (time.time() - start_time))
  134. print(f"剩余测试时间: {remaining:.1f} 秒")
  135. # 停止
  136. await detector.stop()
  137. await audio_capture.stop()
  138. print(f"✅ 系统停止成功")
  139. # 输出测试结果
  140. print(f"\n测试结果:")
  141. print(f"- 测试时长: {test_duration} 秒")
  142. print(f"- 检测到唤醒词次数: {detection_count}")
  143. if detection_count > 0:
  144. # 计算检测间隔
  145. intervals = []
  146. for i in range(1, len(detection_times)):
  147. intervals.append(detection_times[i] - detection_times[i-1])
  148. if intervals:
  149. avg_interval = sum(intervals) / len(intervals)
  150. print(f"- 平均检测间隔: {avg_interval:.2f} 秒")
  151. print("✅ 唤醒词灵敏度测试完成")
  152. else:
  153. print("⚠️ 未检测到唤醒词,请尝试调整唤醒词或提高音量")
  154. return True
  155. except FileNotFoundError as e:
  156. print(f"⚠️ 集成测试跳过(模型文件不存在): {e}")
  157. return True
  158. except Exception as e:
  159. print(f"❌ 集成测试失败: {e}")
  160. # 确保清理
  161. try:
  162. await audio_capture.stop()
  163. except:
  164. pass
  165. return False
  166. except Exception as e:
  167. print(f"❌ 集成测试失败: {e}")
  168. return False
  169. async def main():
  170. """主测试函数"""
  171. print("\n" + "=" * 60)
  172. print("语音唤醒模块测试")
  173. print("=" * 60)
  174. results = []
  175. # 测试 1: 配置类
  176. results.append(("配置类", test_config()))
  177. # 测试 2: 音频采集器
  178. results.append(("音频采集器", test_audio_capture()))
  179. # 测试 3: 检测器
  180. results.append(("检测器", await test_detector()))
  181. # 测试 4: 集成测试
  182. results.append(("集成测试", await test_integration()))
  183. # 汇总结果
  184. print("\n" + "=" * 60)
  185. print("测试结果汇总")
  186. print("=" * 60)
  187. for name, result in results:
  188. status = "✅ 通过" if result else "❌ 失败"
  189. print(f"{name:20s} {status}")
  190. # 统计
  191. passed = sum(1 for _, r in results if r)
  192. total = len(results)
  193. print(f"\n总计: {passed}/{total} 测试通过")
  194. return all(r for _, r in results)
  195. if __name__ == "__main__":
  196. try:
  197. success = asyncio.run(main())
  198. sys.exit(0 if success else 1)
  199. except KeyboardInterrupt:
  200. print("\n\n测试被中断")
  201. sys.exit(1)
  202. except Exception as e:
  203. print(f"\n❌ 测试异常: {e}")
  204. import traceback
  205. traceback.print_exc()
  206. sys.exit(1)