单词发音,为语音识别准备素材
单词发音,为语音识别准备素材
环境
这里我用的是python3.7.9。pycharm编译器。windows系统。
windows下安装pyttsx3
pip install pyttsx3
linux下安装pyttsx3
linux下安装pyttsx3时,要先安装两个插件,要不用起来会报错
sudo apt-get install alsa-utils
sudo apt-get install espeak
pip install pyttsx3
界面展示
图形化界面
图形化界面,很简陋的一个

输出文档
是我做好之后的音频素材文档

保存单词的word.txt

单词发音

写作过程
1.导入相关包。
os,用来进行文件的读写。re,正则匹配。pyttsx3,文字读语音。
import os
import tkinter
from tkinter.filedialog import *
from tkinter import ttk
import pyttsx3
import re
2.这里我准备了一个类来做图形化界面,函数功能也直接在类里面实现了。结果就是看起来十分臃肿,一点都不美观。不过这解决了函数放在类外面出现的一些问题。比如说变量调用很麻烦之类的。
里面变量有些数字大的在前面,这是因为我写的时候是按照从小到大开始写的,但刚开始有些功能没有想明白,把新代码插在了中间。
self.path: 存放文件的输入框
self.path1: 单词的输入框
self.language: 选择发音
self.prompt_statement: 提示语句
self.batch_file: 批文件的输入框。文件里面存放多个英文单词
self.words: 文件里面的单词数量
class painting():
def __init__(self):
self.app1 = tkinter.Tk()
self.app1.title("单词音频保存")
self.app1.geometry("760x430")
self.path = tkinter.StringVar()
self.path1 = tkinter.StringVar()
self.languages = tkinter.StringVar()
self.prompt_statement = tkinter.StringVar()
self.prompt_statement.set('提示语句!')
self.batch_file = tkinter.StringVar()
self.words = []
# 初始化输入框
# self.path.set(os.path.abspath('.'))
self.label1 = tkinter.Label(self.app1, text="单词:", width=9).place(x=70, y=30)
self.entry1 = tkinter.Entry(self.app1, width=50, textvariable=self.path1).place(x=130, y=30)
self.button1 = tkinter.Button(self.app1, text="下载", command=self.audio_save).place(x=500, y=25)
self.label4 = tkinter.Label(self.app1, text="批量下载:", width=9).place(x=70, y=65)
self.entry4 = tkinter.Entry(self.app1, textvariable=self.batch_file, width=50).place(x=130, y=65)
self.button4 = tkinter.Button(self.app1, text="批量导入", command=self.batch_load).place(x=500, y=65)
self.button5 = tkinter.Button(self.app1, text="批量下载", command=self.batch_save).place(x=580, y=65)
self.label2 = tkinter.Label(self.app1, text="保存目录:", width=9).place(x=70, y=100)
self.entry2 = tkinter.Entry(self.app1, width=50, textvariable=self.path).place(x=130, y=100)
self.button2 = tkinter.Button(self.app1, text="选择目录", command=self.output_file_path).place(x=500, y=100)
self.label3 = tkinter.Label(self.app1, text="发音语言:", width=9).place(x=70, y=150)
self.values = ["Chinese", "English"]
self.dropdown_box = ttk.Combobox(values=self.values, textvariable=self.languages).place(x=130, y=150)
self.label4 = tkinter.Label(self.app1, textvariable=self.prompt_statement).place(x=200, y=200)
self.app1.mainloop()
3.图像化界面创建好了,接下来就可以写功能了。以下功能写在类里面。
定义输出文件。
# 定义输出文件
def output_file_path(self):
# 打开文件
# file_name=str(askopenfile())[25:-28]
# 选择文件夹
file_path = askdirectory()
self.path.set(file_path)
# print(file_path)
检查文字与发音选择是否对应:
# 检测发音
def detect_languages(self):
language = self.languages.get()
if language == "Chinese":
if not self.is_Chinese(self.path1.get()):
# print('不是中文!')
self.prompt_statement.set('不是中文')
return False
return "Chinese"
elif language == "English":
return "English"
else:
# print('发音选择错误,请重新开始选择!')
self.prompt_statement.set('发音选择错误,请重新开始选择!')
return False
里面用到了判断是否是中文的函数。这是因为在linux下中文如果用不小心用了英文发音器,只会发出letter,letter的声音。很不友好。
# 判断是否中文
def is_Chinese(self, word):
for ch in word:
if '\u4e00' <= ch <= '\u9fff':
return True
return False
检查单词长度。这里我们不希望单词太长,对单词长度做了限制。
# 检查单词长度
def detect_word_length(self):
word = self.path1.get()
if len(word) > 10:
self.prompt_statement.set("单词太长了!")
return False
else:
return word
单词发音,没有储存目录则默认不会存储。
# 单词发音转音频,未选择保存目录则只发音不保存音频
def word_to_audio(self, word, output_path, language):
engine = pyttsx3.init()
# 增大音量
volume = engine.getProperty('volume')
volume = engine.setProperty('volume', volume + 10)
# 选择是否中文
if language == "Chinese":
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[0].id)
engine.say(word)
engine.save_to_file(word, output_path)
# print("language:","Chinese")
self.prompt_statement.set("Language: Chinese")
else:
# 默认英文。
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[1].id)
engine.say(word)
engine.save_to_file(word, output_path)
# print("language:", "English")
self.prompt_statement.set("Language:English")
engine.runAndWait()
存储文件的路径问题:
# 发音保存
def audio_save(self):
word = self.detect_word_length()
if word:
word_save_folder = self.path.get() + "/" + word
if os.path.exists(word_save_folder):
word_save_path = word_save_folder + '/' + word + '.wav'
else:
os.mkdir(word_save_folder)
word_save_path = word_save_folder + '/' + word + '.wav'
language = self.detect_languages()
if language:
# print(language)
# print(word,word_save_path,"English")
self.word_to_audio(word, word_save_path, language)
else:
return False
4.一个个单词发音太麻烦了。这里,我选择从文本导入英文单词,执行发音函数。当然,也可以选择从网上爬取英文单词和音频。不过我爬虫学的不怎么好,这里就不献丑了。
这里我只选择了前四个单词作输入。我单词文本第一行不是英文。
# 批量导入英文单词
def batch_load(self):
file_path = askopenfilename()
self.batch_file.set(file_path)
file_name = self.batch_file.get()
f = open(file_name, 'r', encoding='utf-8')
try:
content = f.readlines()[1:5]
for i in range(len(content)):
word = re.match(r'[A-Za-z0-9]*', content[i])
self.words.append(word.group(0))
finally:
f.close()
print(self.words)
批量保存:
# 批量下载
def batch_save(self):
if not self.words:
# print('没有单词')
self.prompt_statement.set("没有单词!")
return False
if self.path.get() == '':
self.prompt_statement.set('批量下载输出路径没有定义!')
return False
for word in self.words:
word_save_folder = self.path.get() + "/" + word
if os.path.exists(word_save_folder):
word_save_path = word_save_folder + '/' + word + '.wav'
else:
os.mkdir(word_save_folder)
word_save_path = word_save_folder + '/' + word + '.wav'
self.word_to_audio(word, word_save_path, 'English')
注意事项
1.在创建图像化界面的时候,点击函数对应的功能。记住函数后面不能带"()"。否则打开图像化界面,按钮就被默认点击了一次,里面的函数也会同步执行一次。
错误:self.button1 = tkinter.Button(self.app1, text=“下载”, command=self.audio_save()).place(x=500, y=25)
正确:self.button1 = tkinter.Button(self.app1, text=“下载”, command=self.audio_save).place(x=500, y=25)
2.在linux执行保存音频的时候,出现了错误。查找之后发现是python版本的问题。**python3.7以下不能用pyttsx3保存音频。**由于我做机器学习linux下的python版本用的是python3.6,所以这个准备素材的活在Windows下写了。
3.Linux下选择中文发音器时。普通话中文发音器是倒数第二个,而windows下是第一个。
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[-2].id)
完整代码
# tkinter进行图像化设计
import os
import tkinter
from tkinter.filedialog import *
from tkinter import ttk
import pyttsx3
import re
class painting():
def __init__(self):
self.app1 = tkinter.Tk()
self.app1.title("单词音频保存")
self.app1.geometry("760x430")
self.path = tkinter.StringVar()
self.path1 = tkinter.StringVar()
self.languages = tkinter.StringVar()
self.prompt_statement = tkinter.StringVar()
self.prompt_statement.set('提示语句!')
self.batch_file = tkinter.StringVar()
self.words = []
# 初始化输入框
# self.path.set(os.path.abspath('.'))
self.label1 = tkinter.Label(self.app1, text="单词:", width=9).place(x=70, y=30)
self.entry1 = tkinter.Entry(self.app1, width=50, textvariable=self.path1).place(x=130, y=30)
self.button1 = tkinter.Button(self.app1, text="下载", command=self.audio_save).place(x=500, y=25)
self.label4 = tkinter.Label(self.app1, text="批量下载:", width=9).place(x=70, y=65)
self.entry4 = tkinter.Entry(self.app1, textvariable=self.batch_file, width=50).place(x=130, y=65)
self.button4 = tkinter.Button(self.app1, text="批量导入", command=self.batch_load).place(x=500, y=65)
self.button5 = tkinter.Button(self.app1, text="批量下载", command=self.batch_save).place(x=580, y=65)
self.label2 = tkinter.Label(self.app1, text="保存目录:", width=9).place(x=70, y=100)
self.entry2 = tkinter.Entry(self.app1, width=50, textvariable=self.path).place(x=130, y=100)
self.button2 = tkinter.Button(self.app1, text="选择目录", command=self.output_file_path).place(x=500, y=100)
self.label3 = tkinter.Label(self.app1, text="发音语言:", width=9).place(x=70, y=150)
self.values = ["Chinese", "English"]
self.dropdown_box = ttk.Combobox(values=self.values, textvariable=self.languages).place(x=130, y=150)
self.label4 = tkinter.Label(self.app1, textvariable=self.prompt_statement).place(x=200, y=200)
self.app1.mainloop()
# 检查单词长度
def detect_word_length(self):
word = self.path1.get()
if len(word) > 10:
self.prompt_statement.set("单词太长了!")
return False
else:
return word
# 判断是否中文
def is_Chinese(self, word):
for ch in word:
if '\u4e00' <= ch <= '\u9fff':
return True
return False
# 检测发音
def detect_languages(self):
language = self.languages.get()
if language == "Chinese":
if not self.is_Chinese(self.path1.get()):
# print('不是中文!')
self.prompt_statement.set('不是中文')
return False
return "Chinese"
elif language == "English":
return "English"
else:
# print('发音选择错误,请重新开始选择!')
self.prompt_statement.set('发音选择错误,请重新开始选择!')
return False
# 单词发音转音频,未选择保存目录则只发音不保存音频
def word_to_audio(self, word, output_path, language):
engine = pyttsx3.init()
# 增大音量
volume = engine.getProperty('volume')
volume = engine.setProperty('volume', volume + 10)
# 选择是否中文
if language == "Chinese":
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[0].id)
engine.say(word)
engine.save_to_file(word, output_path)
# print("language:","Chinese")
self.prompt_statement.set("Language: Chinese")
else:
# 默认英文。
voices = engine.getProperty('voices')
engine.setProperty('voice', voices[1].id)
engine.say(word)
engine.save_to_file(word, output_path)
# print("language:", "English")
self.prompt_statement.set("Language:English")
engine.runAndWait()
# 发音保存
def audio_save(self):
word = self.detect_word_length()
if word:
word_save_folder = self.path.get() + "/" + word
if os.path.exists(word_save_folder):
word_save_path = word_save_folder + '/' + word + '.wav'
else:
os.mkdir(word_save_folder)
word_save_path = word_save_folder + '/' + word + '.wav'
language = self.detect_languages()
if language:
# print(language)
# print(word,word_save_path,"English")
self.word_to_audio(word, word_save_path, language)
else:
return False
# 定义输出文件
def output_file_path(self):
# 打开文件
# file_name=str(askopenfile())[25:-28]
# 选择文件夹
file_path = askdirectory()
self.path.set(file_path)
# print(file_path)
# 批量导入英文单词
def batch_load(self):
file_path = askopenfilename()
self.batch_file.set(file_path)
file_name = self.batch_file.get()
f = open(file_name, 'r', encoding='utf-8')
try:
content = f.readlines()[1:5]
for i in range(len(content)):
word = re.match(r'[A-Za-z0-9]*', content[i])
self.words.append(word.group(0))
finally:
f.close()
print(self.words)
# 批量下载
def batch_save(self):
if not self.words:
# print('没有单词')
self.prompt_statement.set("没有单词!")
return False
if self.path.get() == '':
self.prompt_statement.set('批量下载输出路径没有定义!')
return False
for word in self.words:
word_save_folder = self.path.get() + "/" + word
if os.path.exists(word_save_folder):
word_save_path = word_save_folder + '/' + word + '.wav'
else:
os.mkdir(word_save_folder)
word_save_path = word_save_folder + '/' + word + '.wav'
self.word_to_audio(word, word_save_path, 'English')
if __name__ == '__main__':
painting()