【Python】PC端听书工具

一、准备

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')

运行后如下:

【Python】PC端听书工具_第1张图片

你可能感兴趣的:(我的Python朋友,python,开发语言)