说明
使用 QTextToSpeech 的来实现阅读
QTextToSpeech 用法
正常情况下,应该正常的
如果不能发声的话,嘿嘿,可是使用了精简版的系统,那就没啥办法了
from PyQt6 import QtTextToSpeech, QtWidgets
import sys,time
'''
引擎:
['winrt', 'sapi', 'mock']
引擎的声音:
mock ['Bob', 'Anne'] # 这个引擎不能用
sapi ['Microsoft Huihui Desktop'] # 这个可以,只有一个声音
winrt ['Microsoft Huihui', 'Microsoft Yaoyao', 'Microsoft Kangkang'] # 这个可以
'''
# txt = '混沌未分天地乱茫茫渺渺无人见混沌未分天地乱茫茫渺渺无人见' # 无标点
# txt = '混沌未分天地乱,茫茫渺渺无人见.混沌未分天地乱,茫茫渺渺无人见.' # 加入英文标点
txt = '混沌未分天地乱,茫茫渺渺无人见。混沌未分天地乱,茫茫渺渺无人见。' # 加入中文标点
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
tts = QtTextToSpeech.QTextToSpeech(app)
# print(QtTextToSpeech.QTextToSpeech.availableEngines()) # ['winrt', 'sapi', 'mock']
tts.setEngine('winrt')
tts.setVoice(tts.availableVoices()[1])
# tts.setPitch(-0.1)
# tts.setRate(0.05)
# print(tts.engine(),tts.voice().name(), [voice.name() for voice in tts.availableVoices()] )
start = time.time()
tts.say(txt)
# button = QtWidgets.QPushButton('退出')
# button.clicked.connect(app.quit)
# button.show()
# locale = QtCore.QLocale.system()
# print(f'amText = {locale.amText()}')
# print(f'bcp47Name = {locale.bcp47Name()}')
# print(f'currencySymbol = {locale.currencySymbol()}')
# print(f'dateTimeFormat = {locale.dateTimeFormat()}')
# print(f'dayName = {locale.dayName(1,locale.FormatType.ShortFormat)}')
def on_tts_ready(state):
print()
if state == QtTextToSpeech.QTextToSpeech.State.Ready:
app.quit()
# QtCore.QTimer.singleShot(5000,app.quit)
tts.stateChanged.connect(on_tts_ready)
SystemExit(app.exec())
print( f'{
txt, len(txt), time.time() - start}')
# ('混沌未分天地乱茫茫渺渺无人见混沌未分天地乱茫茫渺渺无人见', 28, 7.014833927154541)
# ('混沌未分天地乱,茫茫渺渺无人见.混沌未分天地乱,茫茫渺渺无人见.', 32, 7.7734575271606445)
# ('混沌未分天地乱,茫茫渺渺无人见。混沌未分天地乱,茫茫渺渺无人见。', 32, 8.660011291503906)
界面 + TTS
程序样式如下图:
无框,拖动,右键菜单,滚轮改变透明度
自动缩放界面,估计在高分屏下会有问题,自己修改
功能按键:
- ESC : 退出
- Space: 暂停/继续
import time
from PyQt6 import QtTextToSpeech, QtCore, QtWidgets,QtGui
import sys,os,json5,math,re
from PyQt6.QtGui import QCloseEvent, QKeyEvent, QMouseEvent, QWheelEvent
chapter_line = -1 # 段落索引,从 1 开始,注意调整
file_idx = 0 # 文件索引,从 1 开始,注意调整
txt = '' # 保存文章内容
p_list = [] # 保存分割后的段落 去除空行
short_word_list = [] # 保存分割段落后的短句
short_word_idx = -1 # 保存当前的短句索引 从 1 开始,注意调整
# reg_str = r"[^。?”]+[?。”]+"
# 用句号分割
pat_str1 = r'[^“]{30,}。'
pat_str2 = r'[^“]*?“.*?[。!?]”'
pat_str3 = f'{
pat_str1}|{
pat_str2}'
reg_str = pat_str3
reg = re.compile(reg_str)
x=y=500
opacity = 1
isReadChapter = False
################################ 读取配置 ##########################################
# file_idx 文章的索引
# chapter_line 段落的索引
###################################################################################
def load_setting():
global chapter_line,file_idx,short_word_idx
global x,y,opacity
setting_file = f'{
xyj_dir+"progress.txt"}'
if not os.path.exists(setting_file):
file_idx = 1
chapter_line = 1
short_word_idx = 1
return
# 读取配置文件
with open(xyj_dir+"progress.txt",'r',encoding='utf-8') as f:
dic = json5.loads(f.read())
file_idx = dic['file_idx']
chapter_line = dic['line']
short_word_idx = dic['words']
if file_idx == 0:
file_idx =1
if file_idx > len(file_list):
f