1、首先安装python3+,这里不多展开,具体操作百度。(比如:安装Python - 廖雪峰的官方网站)
2、安装pyttsx3。这是一个调用操作系统语音包的库,可离线使用。
pip3 install pyttsx3 -i https://pypi.tuna.tsinghua.edu.cn/simple
(这里可能要求安装一些前置库,具体跟安装提示走即可)
1、听书的本质是程序根据字符播放对应的音频文件。这里pyttsx3已经帮我们集成好了文字到播放的这部分代码,具体的调用如下:
import pyttsx3
speakerEngine = pyttsx3.init() # 创建语音引擎实例
speakerEngine.setProperty('rate', 350) # 设置语速
speakerEngine.say('hello world!') # 开始朗读"hello world"
speakerEngine.runAndWait() # 阻塞线程直到"hello world"朗读完毕再执行下方代码
2、其余就是文本的读取、分段让pyttsx3帮我朗读了。文本的读取示例如下:
def ReadTxt(path):
with open(path, encoding='utf8') as f:
return f.read()
文本的分段如下(按行):
txt = ReadTxt(r'd:\小说.txt')
lines = txt.split('\n')
3、让讲师开始一段一段朗读小说吧~
import pyttsx3
def ReadTxt(path):
with open(path, encoding='utf8') as f:
return f.read()
speakerEngine = pyttsx3.init() # 创建语音引擎实例
speakerEngine.setProperty('rate', 350) # 设置语速
txt = ReadTxt(r'd:\小说.txt') # 将小说的文本内容读取到变量txt
lines = txt.split('\n') # 将小说内容按行分割成列表
for line in lines: # 按行遍历小说内容
speakerEngine.say(line) # 开始朗读小说段落
speakerEngine.runAndWait() # 阻塞线程直到"hello world"朗读完毕再执行下方代码
这里哈里提供一个可以显示当前朗读语句、能够记忆上次朗读位置下次继续播放、能够中途暂停的demo示例:
import json
import re
import time
import os
import pyttsx3
import threading
import tkinter
import tkinter.font as tf
def RTxt(path):
if not os.path.exists(path):
return None
with open(path, encoding='utf8') as f:
return f.read()
def WTxt(path, content):
try:
with open(path, 'w', encoding='utf8') as f:
f.write(content)
except Exception as e:
print('[error]WTxt.e=', e)
def InputKeyControl():
speaker.stopSay = not speaker.stopSay
btn['text'] = '暂停' if not speaker.stopSay else '继续'
def Exit():
speaker.end = True
form.quit()
class Speaker:
def __init__(self, tb: tkinter.Text):
# 初始化语音引擎
self.speakerEngine = pyttsx3.init()
self.speakerEngine.setProperty('rate', 350)
self.textBox = tb
self.end = False
self.stopSay = False
self.t = threading.Thread(target=self.Say)
self.t.setDaemon(True)
self.t.start()
def Say(self):
print('Say.Start')
txt = RTxt(txtPath)
lines = txt.split('\n')
for line in lines[readConfig['lineNum']:]:
while self.stopSay:
print('stopSay...')
time.sleep(1.0)
st = time.time()
if not re.findall(r'^\s*?$', line):
line = re.sub(r'\s', '', line)
self.speakerEngine.say(line)
print('line=', readConfig['lineNum'], line)
self.textBox.delete('1.0', '2.end')
self.textBox.insert('1.0', line)
# 等待语音播放完
self.speakerEngine.runAndWait()
readConfig['lineNum'] += 1
if time.time() - st > 1.0:
WTxt(readConfigPath, json.dumps(readConfig))
if self.end:
print('Say.end.2')
return
print('Say.end')
txtPath = r'd:\小说.txt' # 把这里修改成你要朗读的小说路径即可
txtRoot = os.path.dirname(txtPath)
txtName = os.path.basename(txtPath)
readConfigPath = txtRoot + r'\{}.json'.format(txtName)
readConfig = RTxt(readConfigPath)
if readConfig is None:
readConfig = {'lineNum': 0}
else:
readConfig = json.loads(readConfig)
form = tkinter.Tk()
form.title('txt阅读器')
form.geometry('620x100+10+10')
form.attributes("-topmost",1)
form.attributes('-alpha',0.5)
# form.overrideredirect(True)
font = tf.Font(family='微软雅黑', size=24)
btnFont = tf.Font(family='微软雅黑', size=12)
btn = tkinter.Button(form, text='暂停', command=InputKeyControl, font=btnFont)
btn.grid(row=1,column=1)
exitBtn = tkinter.Button(form, text='退出', command=Exit, font=btnFont, fg='red')
exitBtn.grid(row=2,column=1)
textBox = tkinter.Text(form, wrap="word", font=font, width=30, height=2, fg='red')
textBox.grid(row=1,column=0, rowspan=2)
speaker = Speaker(textBox)
form.mainloop()
speaker.end = True
print('end')
运行后如下: