| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- """
- TTS音频缓存管理器模块
- 提供音频数据的本地缓存功能,避免重复调用TTS API
- """
- import threading
- import time
- import hashlib
- import pickle
- from pathlib import Path
- from utils.logger import logger
- class TTSCache:
- """TTS音频缓存管理器"""
- def __init__(self, cache_file: str = "tts_cache/tts_cache.pkl"):
- self.cache_file = Path(cache_file)
- self.cache_file.parent.mkdir(parents=True, exist_ok=True)
- self.cache_data = self._load_cache_data()
- self._lock = threading.Lock()
- def _load_cache_data(self):
- """加载缓存数据"""
- if self.cache_file.exists():
- try:
- with open(self.cache_file, 'rb') as f:
- return pickle.load(f)
- except Exception as e:
- logger.info(f"[缓存] 加载缓存数据失败: {e}")
- return {}
- def _save_cache_data(self):
- """保存缓存数据"""
- try:
- with open(self.cache_file, 'wb') as f:
- pickle.dump(self.cache_data, f)
- except Exception as e:
- logger.info(f"[缓存] 保存缓存数据失败: {e}")
- def _get_cache_key(self, text: str, voice: str = None) -> str:
- """生成缓存键"""
- if voice is None:
- from config.config.settings import config
- voice = config.TTS_VOICE
- # 使用文本内容和语音参数的哈希作为缓存键
- cache_data = f"{text.strip()}_{voice}"
- return hashlib.md5(cache_data.encode('utf-8')).hexdigest()
- def get_cached_audio(self, text: str, voice: str = None) -> bytes:
- """获取缓存的音频数据"""
- with self._lock:
- cache_key = self._get_cache_key(text, voice)
- if cache_key in self.cache_data:
- cache_info = self.cache_data[cache_key]
- audio_data = cache_info.get('audio_data')
- if audio_data:
- logger.info(f"[缓存] 命中缓存: {text[:20]}...")
- return audio_data
- else:
- # 删除损坏的缓存记录
- del self.cache_data[cache_key]
- self._save_cache_data()
- return None
- def save_audio_cache(self, text: str, audio_data: bytes, voice: str = None):
- """保存音频数据到缓存"""
- with self._lock:
- cache_key = self._get_cache_key(text, voice)
- try:
- # 更新缓存数据
- if voice is None:
- from config.config.settings import config
- voice = config.TTS_VOICE
- self.cache_data[cache_key] = {
- 'text': text,
- 'voice': voice,
- 'audio_data': audio_data,
- 'size': len(audio_data),
- 'created_time': time.time()
- }
- self._save_cache_data()
- logger.info(
- f"[缓存] 已缓存: {text[:20]}... (大小: {len(audio_data)} bytes)")
- except Exception as e:
- logger.info(f"[缓存] 保存缓存失败: {e}")
- def clear_cache(self, max_age_days: int = 30):
- """清理过期缓存"""
- with self._lock:
- current_time = time.time()
- expired_keys = []
- for cache_key, cache_info in self.cache_data.items():
- age_days = (current_time -
- cache_info['created_time']) / (24 * 3600)
- if age_days > max_age_days:
- expired_keys.append(cache_key)
- for cache_key in expired_keys:
- del self.cache_data[cache_key]
- if expired_keys:
- self._save_cache_data()
- logger.info(f"[缓存] 清理了 {len(expired_keys)} 个过期缓存")
- def get_cache_stats(self):
- """获取缓存统计信息"""
- with self._lock:
- total_size = sum(info['size']
- for info in self.cache_data.values())
- return {
- 'total_entries': len(self.cache_data),
- 'total_size_bytes': total_size,
- 'total_size_mb': total_size / (1024 * 1024)
- }
- def clear_all_cache(self):
- """清空所有缓存"""
- with self._lock:
- self.cache_data.clear()
- self._save_cache_data()
- logger.info("[缓存] 已清空所有缓存")
- def get_cache_info(self, text: str, voice: str = None):
- """获取指定文本的缓存信息"""
- with self._lock:
- cache_key = self._get_cache_key(text, voice)
- if cache_key in self.cache_data:
- cache_info = self.cache_data[cache_key].copy()
- # 不返回音频数据,只返回元信息
- cache_info.pop('audio_data', None)
- return cache_info
- return None
- # 全局缓存实例
- _tts_cache = TTSCache()
- def get_cache_instance():
- """获取缓存实例"""
- return _tts_cache
- def get_cached_audio(text: str, voice: str = None) -> bytes:
- """获取缓存的音频数据"""
- return _tts_cache.get_cached_audio(text, voice)
- def save_audio_cache(text: str, audio_data: bytes, voice: str = None):
- """保存音频数据到缓存"""
- _tts_cache.save_audio_cache(text, audio_data, voice)
- def clear_cache(max_age_days: int = 30):
- """清理过期缓存"""
- _tts_cache.clear_cache(max_age_days)
- def get_cache_stats():
- """获取缓存统计信息"""
- return _tts_cache.get_cache_stats()
- def clear_all_cache():
- """清空所有缓存"""
- _tts_cache.clear_all_cache()
- def get_cache_info(text: str, voice: str = None):
- """获取指定文本的缓存信息"""
- return _tts_cache.get_cache_info(text, voice)
|