utils.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. """
  2. 工具函数模块
  3. """
  4. import time
  5. from typing import Dict
  6. from loguru import logger
  7. class RateLimiter:
  8. """简单的速率限制器"""
  9. def __init__(self, max_requests: int = 100, window_seconds: int = 60):
  10. self.max_requests = max_requests
  11. self.window_seconds = window_seconds
  12. self.requests: Dict[str, list] = {}
  13. def is_allowed(self, client_id: str) -> bool:
  14. """检查是否允许请求"""
  15. now = time.time()
  16. # 清理过期记录
  17. if client_id in self.requests:
  18. self.requests[client_id] = [
  19. req_time for req_time in self.requests[client_id]
  20. if now - req_time < self.window_seconds
  21. ]
  22. else:
  23. self.requests[client_id] = []
  24. # 检查是否超限
  25. if len(self.requests[client_id]) >= self.max_requests:
  26. logger.warning(f"客户端 {client_id} 请求频率超限")
  27. return False
  28. # 记录请求
  29. self.requests[client_id].append(now)
  30. return True
  31. def get_remaining(self, client_id: str) -> int:
  32. """获取剩余配额"""
  33. if client_id not in self.requests:
  34. return self.max_requests
  35. return max(0, self.max_requests - len(self.requests[client_id]))
  36. def validate_audio_data(audio_data: bytes, max_size: int = 1024 * 1024) -> bool:
  37. """验证音频数据"""
  38. if not audio_data:
  39. return False
  40. if len(audio_data) > max_size:
  41. logger.warning(f"音频数据过大: {len(audio_data)} bytes")
  42. return False
  43. return True
  44. def format_bytes(bytes_num: int) -> str:
  45. """格式化字节数"""
  46. for unit in ['B', 'KB', 'MB', 'GB']:
  47. if bytes_num < 1024.0:
  48. return f"{bytes_num:.2f} {unit}"
  49. bytes_num /= 1024.0
  50. return f"{bytes_num:.2f} TB"
  51. def calculate_audio_duration(audio_bytes: int, sample_rate: int = 16000, bit_depth: int = 16, channels: int = 1) -> float:
  52. """计算音频时长(秒)"""
  53. bytes_per_second = sample_rate * (bit_depth / 8) * channels
  54. return audio_bytes / bytes_per_second