前言
使用pyttsx3+tkinter+threading模块开发文字转语音
threading模块用于解决ui卡顿问题
文字转语音,可以直接转换编辑的文本内容为语音文件
可以根据选择的语速选项为您量身定制。
准备工作
这里使用的第三方模块为:“pyttsx3”,如果你还未安装该模块可以在pycharm中的terminal(终端)输入如下指令进行模块的安装。
pip install pyttsx3
pyttsx3模块介绍
语音引擎工厂
类似于设计模式中的“工厂模式”,pyttsx3通过初始化来获取语音引擎。当我们第一次调用init操作的时候,会返回一个pyttsx3的engine对象,再次调用的时候,如果存在engine对象实例,就会使用现有的,否则再重新创建一个。
pyttsx.init([driverName : string, debug : bool]) → pyttsx.Engine
从方法声明上来看,第一个参数指定的是语音驱动的名称,这个在底层适合操作系统密切相关的。如下:
1.drivename:由pyttsx3.driver模块根据操作系统类型来调用,默认使用当前操作系统可以使用的最好的驱动
sapi5 - SAPI5 on Windows
nsss - NSSpeechSynthesizer on Mac OS X
espeak - eSpeak on every other platform
2.debug: 这第二个参数是指定要不要以调试状态输出,建议开发阶段设置为True
引擎接口
要想很好的运用一个库,不了解其API是不行的。下面来看看pyttsx3。engine.Engine的引擎API。
方法签名 | 参数列表 | 返回值 | 简单释义 |
connect(topic : string, cb : callable) | topic:要描述的事件名称;cb:回调函数 | → dict | 在给定的topic上添加回调通知 |
disconnect(token : dict) | token:回调失联的返回标记 | Void | 结束连接 |
endLoop() | None | → None | 简单来说就是结束事件循环 |
getProperty(name : string) | name有这些枚举值“rate, vioce,vioces,volumn | → object | 获取当前引擎实例的属性值 |
setProperty(name : string) | name有这些枚举值“rate, vioce,vioces,volumn | → object | 设置当前引擎实例的属性值 |
say(text : unicode, name : string) | text:要进行朗读的文本数据; name:关联发音人,一般用不到 | → None | 预设要朗读的文本数据,这也是“万事俱备,只欠东风”中的“万事俱备” |
runAndWait() | None | → None | 这个方法就是“东风”了。当事件队列中事件全部清空的时候返回 |
startLoop([useDriverLoop : bool]) | useDriverLoop:是否启用驱动循环 | → None | 开启事件队列 |
元数据音调
在pyttsx3.voice.Voice中,处理合成器的发音。
age
发音人的年龄,默认为None
gender
以字符串为类型的发音人性别: male, female, or neutral.默认为None
id
关于Voice的字符串确认信息. 通过 pyttsx3.engine.Engine.setPropertyValue()来设置活动发音签名. 这个属性总是被定义。
languages
发音支持的语言列表,如果没有,则为一个空的列表。
name
发音人名称,默认为None.
文字转语音开发实战
在介绍完pyttsx3模块后,下面我们就开始编写文字转语音桌面应用程序的代码。
定义全局engine对象
engine = pyttsx3.init()
文字转语音功能函数:
1def say(): engine.setProperty('voice', 'zh') text = edit.get('0.0', 'end') engine.setProperty('rate', scale.get()) engine.say(text, 'fox') engine.runAndWait()
保存发音文件函数:
def save_file(): file = f'{int(time.time())}.mp3' engine.save_to_file(edit.get('0.0', 'end'), file) engine.runAndWait() tkinter.messagebox.showinfo('文件保存成功:', file)
线程函数(防止ui卡顿):
def thread_it(func, *args): '''将函数打包进线程''' # 创建 t = threading.Thread(target=func, args=args) # 守护 !!! t.setDaemon(True) # 启动 t.start()
gui窗口程序:
window = tk.Tk() window.geometry('400x500') window.title("文字转语音助手") window.resizable(width=False, height=False) edit = tk.Text(window, height=15, width=40, highlightcolor='blue', bd=1, highlightthickness=1) edit.pack(pady=25) scale = tk.Scale(window, bg='pink', fg='red', length=300, label='语速控制:', # 设置显示的标签 from_=0, to=300, # 设置最大最小值 # 注意设置最大值的属性不是'from',而是'from_',这是因为python中已经有了from关键字啦 resolution=1, # 设置步距值 orient=tk.HORIZONTAL, # 设置水平方向 ) scale.set(163) scale.pack(pady=4) button = tk.Button(window, fg='blue', font=('仿宋', 15), bg='orange', bd=5, width=35, text='试 听', command=lambda: thread_it(say)) button.pack(pady=15) button1 = tk.Button(window, fg='blue', font=('仿宋', 15), bg='pink', bd=5, width=35, text='保 存', command=lambda: thread_it(save_file)) button1.pack(pady=3) window.mainloop()
全部代码:
import threading import pyttsx3 import tkinter as tk import time import tkinter.messagebox engine = pyttsx3.init() def say(): engine.setProperty('voice', 'zh') text = edit.get('0.0', 'end') engine.setProperty('rate', scale.get()) engine.say(text, 'fox') engine.runAndWait() def save_file(): file = f'{int(time.time())}.mp3' engine.save_to_file(edit.get('0.0', 'end'), file) engine.runAndWait() tkinter.messagebox.showinfo('文件保存成功:', file) def thread_it(func, *args): '''将函数打包进线程''' # 创建 t = threading.Thread(target=func, args=args) # 守护 !!! t.setDaemon(True) # 启动 t.start() window = tk.Tk() window.geometry('400x500') window.title("文字转语音助手") window.resizable(width=False, height=False) edit = tk.Text(window, height=15, width=40, highlightcolor='blue', bd=1, highlightthickness=1) edit.pack(pady=25) scale = tk.Scale(window, bg='pink', fg='red', length=300, label='语速控制:', # 设置显示的标签 from_=0, to=300, # 设置最大最小值 # 注意设置最大值的属性不是'from',而是'from_',这是因为python中已经有了from关键字啦 resolution=1, # 设置步距值 orient=tk.HORIZONTAL, # 设置水平方向 ) scale.set(163) scale.pack(pady=4) button = tk.Button(window, fg='blue', font=('仿宋', 15), bg='orange', bd=5, width=35, text='试 听', command=lambda: thread_it(say)) button.pack(pady=15) button1 = tk.Button(window, fg='blue', font=('仿宋', 15), bg='pink', bd=5, width=35, text='保 存', command=lambda: thread_it(save_file)) button1.pack(pady=3) window.mainloop()
效果图:
创作不易,大家帮忙点个赞支持下作者吧~
关注获取更多实用技术分享