为智能家居注入灵魂:我动手打造专属温柔语音包(edge-tts)
我一直热衷于折腾智能家居自动化,灯光、窗帘、空调都接入了系统。每天下班回家,一句“开灯”就能让客厅亮起温馨的光,非常方便。但时间长了,总觉得缺了点什么——那就是语音助手的音色。无论是小爱、小艺还是Siri,它们的声音虽然清晰,但总感觉过于“官方”和“机械”,少了点家的温度和温柔。
我理想中的智能家居,应该有一个像家人一样亲切、柔和的声音来回应我。既然现有的语音助手无法满足这个个性化的需求,作为一个喜欢动手的程序员,我决定自己来造一个。
我的思路是:利用微软Edge TTS优质的神经网络语音合成技术,通过Python脚本,将我想让“家”说的话,用更温柔的语音合成出来,并集成到我的智能家居自动化流程中。
准备工作:安装必要的包
在开始编写脚本前,你需要先安装核心的Python库。
# 核心TTS库
pip install edge-tts
# 如果你需要像进阶脚本那样实时播放音频,还需要安装pygame
pip install pygame
注意事项:
-
edge-tts是一个命令行工具,也是一个Python库,它需要联网调用微软的云服务来合成语音。 -
语音合成质量很高,但会有轻微的网络延迟,不适合需要毫秒级响应的场景。对于智能家居的提醒、播报等场景,完全足够。
初级玩法:快速生成语音文件
这个脚本(比如保存为 simple_tts.py)非常适合用来生成固定的、需要重复使用的语音片段。比如,你可以提前合成好“欢迎回家”、“浴室热水已烧好”、“空调已为您调到26度”等语音提示,保存在智能家居系统的媒体库中。
代码示例:
# simple_tts.py
import asyncio
import edge_tts
# 你希望智能家居“说”的话
TEXT = "主人,欢迎回家!灯光已为您调至温馨模式,现在室内温度26度,非常舒适。"
# 输出的音频文件名
OUTPUT_FILE = "welcome_home.mp3"
# 指定语音名称,这里是我非常喜欢的温柔女声“晓晓”
VOICE = "zh-CN-XiaoxiaoNeural"
async def main() -> None:
# 创建TTS对象
communicate = edge_tts.Communicate(TEXT, VOICE)
# 运行并保存音频文件
await communicate.save(OUTPUT_FILE)
print(f"语音合成完成!文件已保存为:{OUTPUT_FILE}")
if __name__ == "__main__":
asyncio.run(main())
运行方式与用途:
-
在命令行执行
python simple_tts.py。 -
脚本会生成一个
welcome_home.mp3文件。 -
你可以在智能家居App(如Home Assistant、Node-RED等)中,将这个音频文件设置为自动化动作——例如,当门窗传感器检测到你下班回家时,就在家里的音箱上播放这个音频
进阶玩法:交互式测试与实时生成
当你需要测试不同文本的朗读效果,或者自动化流程需要动态生成不固定的语音内容时(比如播报“今天北京晴,最高温度30度”),一个交互式的脚本就更方便了。
这个脚本(比如保存为 interactive_tts.py)允许你随时输入文本,立即试听效果,帮你快速找到最温柔的语调和措辞。
代码示例:
-
实时合成与播放:输入文本后直接播放,无需手动点击音频文件。
-
非阻塞播放:你可以在上一句还在播放时,输入下一句进行测试。
-
语音切换:方便地在“晓晓”(女声)和“云希”(男声)等不同音色间切换。
-
临时文件管理:自动清理合成过程中产生的临时音频文件,保持系统整洁。
#interactive_tts.py import asyncio import edge_tts import pygame import threading import tempfile import os import time from io import BytesIO class EdgeTTSPlayer: def __init__(self): """初始化TTS播放器""" pygame.mixer.init() self.is_playing = False self.current_text = "" self.voice = "zh-CN-XiaoxiaoNeural" self.temp_files = [] # 用于跟踪临时文件 async def text_to_speech(self, text): """将文本转换为语音并播放 Args: text: 要转换的文本 """ if not text.strip(): print("输入文本为空,请重新输入。") return self.current_text = text print(f"正在合成语音: {text}") try: # 创建TTS通信对象 communicate = edge_tts.Communicate(text, self.voice) # 创建临时文件来保存音频 with tempfile.NamedTemporaryFile(delete=False, suffix='.mp3') as temp_file: temp_filename = temp_file.name # 保存音频到临时文件 await communicate.save(temp_filename) # 播放音频 self.play_audio(temp_filename) except Exception as e: print(f"语音合成失败: {e}") # 清理临时文件 if 'temp_filename' in locals(): try: os.unlink(temp_filename) except: pass def play_audio(self, audio_file_path): """播放音频文件""" def _play(): self.is_playing = True try: # 使用文件路径加载音频 pygame.mixer.music.load(audio_file_path) pygame.mixer.music.play() # 等待播放完成 while pygame.mixer.music.get_busy(): pygame.time.Clock().tick(10) # 每秒检查10次 except Exception as e: print(f"播放失败: {e}") finally: self.is_playing = False # 播放完成后清理临时文件 try: os.unlink(audio_file_path) except: pass # 在新线程中播放以避免阻塞 play_thread = threading.Thread(target=_play) play_thread.daemon = True play_thread.start() def stop_playback(self): """停止当前播放""" if pygame.mixer.music.get_busy(): pygame.mixer.music.stop() self.is_playing = False # 以下是您原有的InteractiveTTSApp类,只需确保它使用修复后的EdgeTTSPlayer class InteractiveTTSApp: def __init__(self): """初始化交互式TTS应用""" self.tts_player = EdgeTTSPlayer() self.running = True def display_menu(self): """显示菜单选项""" print("\n" + "="*50) print(" Edge TTS 交互式语音合成系统") print("="*50) print("1. 输入文本并合成语音") print("2. 停止当前播放") print("3. 更换语音(当前: 晓晓)") print("4. 退出系统") print("="*50) def get_user_input(self): """获取用户输入的文本""" print("\n请输入要转换为语音的文本:") text = input("> ").strip() return text def change_voice(self): """更换语音选项""" print("\n可用的语音选项:") print("1. 晓晓 (zh-CN-XiaoxiaoNeural) - 女声") print("2. 云希 (zh-CN-YunxiNeural) - 男声") choice = input("请选择语音 (1-2, 回车使用当前语音): ").strip() voice_map = { "1": "zh-CN-XiaoxiaoNeural", "2": "zh-CN-YunxiNeural" } if choice in voice_map: self.tts_player.voice = voice_map[choice] print(f"已切换语音到: {voice_map[choice]}") else: print("使用当前语音: 晓晓") async def process_choice(self, choice): """处理用户选择""" if choice == "1": text = self.get_user_input() if text: await self.tts_player.text_to_speech(text) elif choice == "2": self.tts_player.stop_playback() print("已停止当前播放") elif choice == "3": self.change_voice() elif choice == "4": self.running = False print("感谢使用,再见!") else: print("无效选择,请重新输入。") async def run(self): """运行主应用程序""" print("系统初始化完成,开始运行...") while self.running: self.display_menu() choice = input("请选择操作 (1-4): ").strip() await self.process_choice(choice) async def main(): """主函数""" app = InteractiveTTSApp() await app.run() if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("\n程序被用户中断") except Exception as e: print(f"程序运行出错: {e}")
使用方式:
-
直接运行
python interactive_tts.py。 -
会出现一个命令行菜单,选择“1”并输入你想测试的文本,比如“亲爱的,浴缸的热水已经放好了,可以来泡澡了”。
-
回车后,程序会自动合成并用你选择的语音播放出来。
-
你可以反复调整文本,直到合成出最令你满意的、最温柔的语音效果。
版权声明:本文为个人技术实践记录,欢迎交流学习。
更多推荐
所有评论(0)