没有合适的资源?快使用搜索试试~ 我知道了~
四个实验内容
资源推荐
资源详情
资源评论
简单的语音合成
一、实验目的
本实验完成了利用 python 中的 pyttsx3 库和 pygame 库实现语音合成功能,通过相
关逻辑的设置,在播放语音的过程中暂停或者继续播放,在上述基础上,增加了读取功
能(可以自己选定要读取的文件),翻译功能(基于百度 api,自动识别输入文本,支持
中英文互译),保存功能(将朗读的音频文件保存为 mp3 文件),设置功能(可以改变音
量、语速、音色)得到了使用 tkinter 库设计界面的声音播放器系统。
二、实验原理
2.1 语音合成功能
2.1 pyttsx3 库的使用
Pyttsx3 是一个用于文本到语音转换的 Python 库,可以将文本转换为语音并播放
出来,也可以设置语速、音调和音量等参数。
我们在这里主要使用 pyttsx3 来进行文本到音频的转换,但是考虑到在 pyttsx3 中
无法进行音频的暂停与继续播放(指的是不可以在暂停的地方继续播放),所以我们这
里只用 pyttsx3 来将文本生成 wav 音频文件,并将其保存在 temp 文件夹中,这里的 temp
文件夹起到一个临时文件的作用。在这里有两点需要说明,一是为什么不用 pygame 朗
读文本,这是因为 pygame 并不能直接将文本转化为音频输出,需要读取音频文件,二
是为什么不使用 mp3 格式,这是因为在一些说法中表示 pygame 对于 mp3 格式的文件支
持有限,可能会无法播放,实际中我就遇到了这个问题,所以我使用 wav 文件来作为音
频的临时存放处。
此外, pyttsx3 还提供 engine.getProperty()方法来返回此时的音量(volume)、
语速(rate)、音色(voices)参数,并可以通过 engine.setProperty()来修改对应参
数,达到调整的目的。
2.1.2 pygame 库的使用
Pygame 是一组专为创建视频游戏而设计的 Python 模块。它提供了处理图形、声音、
输入设备等功能。
我在这里使用的是它的 mixer 模块,mixer 模块在 pygame 里常用来处理声音,它提
供了 pygame.mixer.Sound()来读取音频,使用 play()来来播放音频。但是由于 play()
会创建一个新的播放实例,这就会导致多次调用 play()方法会有多个音频实例同时播
放,这与我们的理念不符,而且 Sound 对象没有暂停方法。所以,我们使用 pygame,mixer
的通道(channel)来播放音频,即 audio_file = pygame.mixer.Sound(temp_data)
channel = audio_file.play(0),使用 pause()和 unpause()来暂停和继续播放音
频,通过 channel.get_busy()来判断此时是否在播放音频,适当使用该方法,可以在一
定程度上增加程序的容错率。
2.2 基于百度 api 的使用
2.2.1 接入百度 api
百度开发者平台免费提供翻译服务,通过申请 appid 和密钥之后,按照百度提供的
通用翻译 api 接入文档拼接字符串 1,然后计算签名(对字符串 1 做 MD5 加密),使用
POST 方式传送,Content-Type 指定为:application/x-www-form-urlencoded,完成相
关接入。
2.2.2 与程序结合
在我的程序中,输入文本定义为全局变量 firsttext,通过对 firsttext 进行中英
文检验来确定申请的翻译类别,具体来说是通过'CJK' in unicodedata.name(char)以
及 char.isalpha()来判断文本中的字节是否为中文字节或者是英文字节。
2.3 保存与读取功能的实现
2.3.1 保存功能
利用 engine.save_to_file(firsttext,file_path)来保存相关文件。
2.3.2 读取功能
在用户选择文件之后,通过 with open(file_path, 'r', encoding='utf-8') as
file:firsttext = file.read()来获取文件中的文本信息。
三、实验步骤
3.1 程序的实现
3.1.1 朗读功能
3.1.2 读取与保存功能
3.1.3 翻译功能
def get_continue():
"""这是一个获取文本的函数,顺便检查是否文本框中有信息,没有就返回 True"""
global firsttext
firsttext = text.get("1.0", "end-1c")
engine.save_to_file(firsttext,temp_data)
engine.runAndWait()
if not firsttext:
messagebox.showinfo("错误信息", "请输入文本")
return True
def on_read_click():
"""朗读功能的设计"""
global channel
button2.config(text="暂停")
if get_continue():
return
if is_chinese_text(firsttext):
if judement_voice():
return
if channel and channel.get_busy():
channel.stop()
audio_file = pygame.mixer.Sound(temp_data)
channel = audio_file.play(0)
def choose_file_and_read():
"""读取功能的设计"""
# 打开文件选择对话框
global firsttext
text.delete(1.0, tk.END) # 清空文本框
file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt")])
if file_path: # 如果用户选择了文件
try: # 读取文件内容
with open(file_path, 'r', encoding='utf-8') as file:
firsttext = file.read()
text.insert("1.0", firsttext)
except Exception as e: # 如果读取文件时发生错误,显示错误信息
text_area.insert(tk.END, f"Error: {e}\n")
3.1.4 设置功能
该设置键会打开一个顶层窗口,在该窗口中,可以输入想要的音量和语速数值,可
以进行音色选择,点击确认会弹出提示信息。
def on_translate_click():
"""基于百度翻译 api"""
global firsttext
if get_continue():
return
appid = '20240316001995208'
appkey = 'oJrphLsEiCbNjNQFoeGp'
if judement()==0:
from_lang,to_lang = 'zh', 'en'
else:
from_lang, to_lang = 'en', 'zh'
if judement_voice():
return
endpoint = 'http://api.fanyi.baidu.com'
path = '/api/trans/vip/translate'
url = endpoint + path
get_continue()
query = firsttext # 我们的文本
# Generate salt and sign
def make_md5(s, encoding='utf-8'):
"""MD5 加密"""
return md5(s.encode(encoding)).hexdigest()
salt = random.randint(32768, 65536) # 随机数
sign = make_md5(appid + query + str(salt) + appkey) # 生成签名,为了保证调用安全,32 位,
用了 MD5 加密
# Build request,使用 POST 方式
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
payload = {'appid': appid, 'q': query, 'from': from_lang, 'to': to_lang, 'salt': salt, 'sign': sign}
# Send request
r = requests.post(url, params=payload, headers=headers)
result = r.json()
# 访问'dst'键对应的值
firsttext = result['trans_result'][0]['dst']
text.delete(1.0, tk.END) # 清空文本框
text.insert(tk.END, firsttext)
on_read_click()
def show_settings_window():
def on_radio_click():
selected_option = var.get()
if selected_option == 1:
voices = engine.getProperty("voices")
engine.setProperty("voice", voices[0].id)
elif selected_option == 2:
voices = engine.getProperty("voices")
engine.setProperty("voice", voices[1].id)
# 这是有关于窗口的设计
settings_window = tk.Toplevel(root)
settings_window.title("设置")
settings_window.geometry("600x250")
label1 = tk.Label(settings_window, text="音量:")
label1.pack()
text1 = tk.Text(settings_window, height=1, width=20)
volume = engine.getProperty("volume")
text1.insert("1.0", volume)
text1.pack()
label2 = tk.Label(settings_window, text="语速:")
label2.pack()
text2 = tk.Text(settings_window, height=1, width=20)
rate = engine.getProperty("rate")
text2.insert("1.0", rate)
text2.pack()
label3 = tk.Label(settings_window, text="英语音色(中文朗读选择 1):")
label3.pack()
var = tk.IntVar()
radio_button1 = tk.Radiobutton(settings_window, text=" 音色 1", variable=var,
value=1,command=on_radio_click)
radio_button1.pack()
radio_button2 = tk.Radiobutton(settings_window, text=" 音色 2", variable=var,
value=2,command=on_radio_click)
radio_button2.pack()
def save_settings(): # 有关于选择音色的设计
item1 = text1.get("1.0", "end-1c")
item2 = text2.get("1.0", "end-1c")
item3=var.get()
engine.setProperty("volume", float(item1))
engine.setProperty("rate", float(item2))
engine.runAndWait()
messagebox.showinfo("设置成功",f"音量: {item1}\n 语速: {item2}\n 英语音色: 音色
{item3}")
settings_window.destroy()
save_button = tk.Button(settings_window, text="确认", command=save_settings)
save_button.pack()
剩余27页未读,继续阅读
资源评论
weixin_74249132
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功