经过测试,如果在windows上按下按键的时候才开始启动录音,录音启动会有一定的延迟,这个延迟大概在0.5到1秒钟。为了能做到按下按键的时候,就立刻开始录音,现在在启动引擎之后,现在程序会持续性调用麦克风(但不会将录音数据写入内存),对耗电量影响也不大,当按下按键的时候,就会立刻将录音数据开始写入内存,这样就可以做到按下按键的时候立马开始说话,也能捕捉到。

另外,录音进程是在一个新的线程中进行的,但是发现了pyside 的一个 bug,当新线程中存在一个 pyaudio stream 时,就会阻塞其他的图形界面。所以在启动引擎之后,就不要点击其他按钮了,可能会导致页面卡死。如果换成 PyQt5 就不会有这个问题。目前已反馈至 PySide 的 bug 反馈平台:https://bugreports.qt.io/browse/PYSIDE-1465,希望官方可以修复,如果不行的话,以后就换成 PyQt5。

对导入模块进行了精简。
This commit is contained in:
Haujet 2020-12-31 22:28:56 +08:00
parent 3d727d0364
commit 6bd5f55dcf
15 changed files with 58 additions and 69 deletions

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ __pycache__
*/dist/* */dist/*
*/build/* */build/*
*.db *.db
*test/*
*.afphoto *.afphoto
icon*.png icon*.png
视频封面.png 视频封面.png

View File

@ -6,9 +6,9 @@ os.chdir(os.path.dirname(os.path.abspath(__file__))) # 更改工作目录,指
sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 将当前目录导入 python 寻找 package 和 moduel 的变量 sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 将当前目录导入 python 寻找 package 和 moduel 的变量
# os.environ['PATH'] += os.pathsep + os.path.abspath('./bin') # 将可执行文件的目录加入环境变量 # os.environ['PATH'] += os.pathsep + os.path.abspath('./bin') # 将可执行文件的目录加入环境变量
from PySide2.QtWidgets import * from PySide2.QtWidgets import QApplication
from PySide2.QtCore import * from PySide2.QtCore import QCoreApplication
from PySide2.QtGui import * from PySide2.QtGui import Qt
from moduels.function.createDB import createDB # 引入检查和创建创建数据库的函数 from moduels.function.createDB import createDB # 引入检查和创建创建数据库的函数

View File

@ -1,10 +1,6 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
import json
import os
import pyaudio
import threading
import keyboard import keyboard
import time
from ali_speech.callbacks import SpeechRecognizerCallback from ali_speech.callbacks import SpeechRecognizerCallback

View File

@ -1,7 +1,10 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
import sys
from PySide2.QtWidgets import * from PySide2.QtWidgets import QTextEdit
from PySide2.QtGui import * from PySide2.QtGui import QTextCursor
from moduels.component.Stream import Stream
# 命令输出窗口中的多行文本框 # 命令输出窗口中的多行文本框
class QEditBox_StdoutBox(QTextEdit): class QEditBox_StdoutBox(QTextEdit):
@ -9,6 +12,9 @@ class QEditBox_StdoutBox(QTextEdit):
def __init__(self, parent=None): def __init__(self, parent=None):
super(QEditBox_StdoutBox, self).__init__(parent) super(QEditBox_StdoutBox, self).__init__(parent)
self.setReadOnly(True) self.setReadOnly(True)
self.标准输出流 = Stream()
self.标准输出流.newText.connect(self.print)
sys.stdout = self.标准输出流
def print(self, text): def print(self, text):
try: try:

View File

@ -1,8 +1,7 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
from PySide2.QtWidgets import * from PySide2.QtWidgets import QDialog
from PySide2.QtGui import * from PySide2.QtGui import Qt, QIcon, QPainter, QPixmap
from PySide2.QtCore import *
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量

View File

@ -1,6 +1,5 @@
from PySide2.QtWidgets import *
from PySide2.QtGui import * from PySide2.QtCore import Signal, QObject
from PySide2.QtCore import *
class Stream(QObject): class Stream(QObject):

View File

@ -1,9 +1,7 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
import os, sqlite3 import os, sqlite3
from PySide2.QtWidgets import * from PySide2.QtWidgets import QComboBox
from PySide2.QtGui import *
from PySide2.QtCore import *
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量
# 添加预设对话框 # 添加预设对话框

View File

@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
from PySide2.QtWidgets import * from PySide2.QtWidgets import QGroupBox, QLineEdit, QPushButton, QGridLayout
from moduels.gui.List_List import List_List from moduels.gui.List_List import List_List
# 添加预设对话框 # 添加预设对话框

View File

@ -1,8 +1,7 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
from PySide2.QtWidgets import * from PySide2.QtWidgets import QListWidget
from PySide2.QtGui import * from PySide2.QtCore import Signal
from PySide2.QtCore import *
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量
# 添加预设对话框 # 添加预设对话框

View File

@ -1,12 +1,11 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
from PySide2.QtWidgets import * from PySide2.QtWidgets import QMainWindow, QTabWidget
from PySide2.QtGui import * from PySide2.QtGui import QIcon, Qt
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量
from moduels.gui.Tab_CapsWriter import Tab_CapsWriter from moduels.gui.Tab_CapsWriter import Tab_CapsWriter
# from moduels.gui.Tab_Stdout import Tab_Stdout
from moduels.gui.Tab_Config import Tab_Config from moduels.gui.Tab_Config import Tab_Config
from moduels.gui.Tab_Help import Tab_Help from moduels.gui.Tab_Help import Tab_Help
@ -24,7 +23,6 @@ class MainWindow(QMainWindow):
# self.setWindowState(Qt.WindowMaximized) # self.setWindowState(Qt.WindowMaximized)
# sys.stdout = Stream(newText=self.onUpdateText)
def initElements(self): def initElements(self):
self.状态栏 = self.statusBar() self.状态栏 = self.statusBar()

View File

@ -1,8 +1,9 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
from PySide2.QtWidgets import * from PySide2.QtWidgets import QSystemTrayIcon, QMenu, QApplication, QAction
from PySide2.QtCore import * # from PySide2.QtCore import *
from PySide2.QtGui import * from PySide2.QtGui import QIcon
from PySide2.QtCore import Qt
import sys import sys

View File

@ -1,29 +1,16 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
from PySide2.QtWidgets import * from PySide2.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QPushButton
from PySide2.QtGui import * # from PySide2.QtGui import *
from PySide2.QtCore import * from PySide2.QtCore import Signal
import sys, os, re, subprocess, time import os, re, subprocess, time
import pyaudio import pyaudio
# from moduels.component.QLEdit_FilePathQLineEdit import QLEdit_FilePathQLineEdit
from moduels.component.Stream import Stream
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量
from moduels.component.QEditBox_StdoutBox import QEditBox_StdoutBox from moduels.component.QEditBox_StdoutBox import QEditBox_StdoutBox
# from moduels.component.SpaceLine import QHLine, QVLine
from moduels.thread.Thread_AliEngine import Thread_AliEngine from moduels.thread.Thread_AliEngine import Thread_AliEngine
# from moduels.thread.Thread_GenerateSkins import Thread_GenerateSkins
# from moduels.thread.Thread_ExtractAllSkin import Thread_ExtractAllSkin
# from moduels.function.applyTemplate import applyTemplate
# from moduels.function.openSkinSourcePath import openSkinSourcePath
#
# from moduels.gui.Dialog_AddSkin import Dialog_AddSkin
# from moduels.gui.Dialog_DecompressSkin import Dialog_DecompressSkin
# from moduels.gui.Dialog_RestoreSkin import Dialog_RestoreSkin
# from moduels.gui.Group_EditableList import Group_EditableList
# from moduels.gui.VBox_RBtnContainer import VBox_RBtnContainer
from moduels.gui.Combo_EngineList import Combo_EngineList from moduels.gui.Combo_EngineList import Combo_EngineList
@ -54,10 +41,10 @@ class Tab_CapsWriter(QWidget):
self.停止按钮 = QPushButton('停止 CapsWriter') self.停止按钮 = QPushButton('停止 CapsWriter')
self.启停按钮Box布局 = QHBoxLayout() self.启停按钮Box布局 = QHBoxLayout()
self.标准输出流 = Stream()
def initLayouts(self): def initLayouts(self):
self.标准输出流.newText.connect(self.更新控制台输出)
self.引擎选择Box布局.addWidget(self.引擎选择下拉框) self.引擎选择Box布局.addWidget(self.引擎选择下拉框)
@ -85,10 +72,8 @@ class Tab_CapsWriter(QWidget):
def initValues(self): def initValues(self):
self.引擎线程 = None self.引擎线程 = None
# self.aliClient = ali_speech.NlsClient()
# self.aliClient.set_log_level('WARNING') # 设置 client 输出日志信息的级别DEBUG、INFO、WARNING、ERROR
self.停止按钮.setDisabled(True) self.停止按钮.setDisabled(True)
sys.stdout = self.标准输出流
print("""\n软件介绍: print("""\n软件介绍:
CapsWriter顾名思义就是按下大写锁定键来打字的工具它的具体作用是当你按下键盘上的大写锁定键后软件开始语音识别当你松开大写锁定键时识别的结果就可以立马上屏 CapsWriter顾名思义就是按下大写锁定键来打字的工具它的具体作用是当你按下键盘上的大写锁定键后软件开始语音识别当你松开大写锁定键时识别的结果就可以立马上屏

View File

@ -1,8 +1,6 @@
import webbrowser import webbrowser
from PySide2.QtCore import * from PySide2.QtCore import Signal
from PySide2.QtGui import * from PySide2.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QGroupBox, QPushButton, QCheckBox
from PySide2.QtSql import *
from PySide2.QtWidgets import *
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量
from moduels.gui.Group_EditableList import Group_EditableList from moduels.gui.Group_EditableList import Group_EditableList
from moduels.gui.Dialog_AddEngine import Dialog_AddEngine from moduels.gui.Dialog_AddEngine import Dialog_AddEngine

View File

@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*- # -*- coding: UTF-8 -*-
from PySide2.QtWidgets import * from PySide2.QtWidgets import QWidget, QPushButton, QVBoxLayout
from PySide2.QtCore import Signal from PySide2.QtCore import Signal
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量
from moduels.component.SponsorDialog import SponsorDialog from moduels.component.SponsorDialog import SponsorDialog

View File

@ -10,9 +10,8 @@ import time
import ali_speech import ali_speech
from PySide2.QtWidgets import * from PySide2.QtCore import QThread, Signal
from PySide2.QtGui import * from PySide2.QtWidgets import QApplication
from PySide2.QtCore import *
from moduels.component.NormalValue import 常量 from moduels.component.NormalValue import 常量
from moduels.function.getAlibabaRecognizer import getAlibabaRecognizer from moduels.function.getAlibabaRecognizer import getAlibabaRecognizer
@ -40,6 +39,7 @@ class Thread_AliEngine(QThread):
def __init__(self, 引擎名称, parent=None): def __init__(self, 引擎名称, parent=None):
super().__init__(parent) super().__init__(parent)
self.持续录音 = True
self.正在运行 = 0 self.正在运行 = 0
self.引擎名称 = 引擎名称 self.引擎名称 = 引擎名称
self.得到引擎信息() self.得到引擎信息()
@ -98,7 +98,8 @@ class Thread_AliEngine(QThread):
self.识别中 = True self.识别中 = True
try: try:
self.data = [] self.data = []
threading.Thread(target=self.录音线程, args=[self.p]).start() # 开始录音 if not self.持续录音: # 如果录音进程不是被持续开启着,那么就需要在这里主动开启
threading.Thread(target=self.录音线程, args=[self.p]).start() # 开始录音
threading.Thread(target=self.识别线程).start() # 开始识别 threading.Thread(target=self.识别线程).start() # 开始识别
except: except:
@ -110,6 +111,7 @@ class Thread_AliEngine(QThread):
else: else:
# print(event.event_type) # print(event.event_type)
pass pass
def 为下一次输入准备识别器(self): def 为下一次输入准备识别器(self):
self.识别器 = getAlibabaRecognizer(self.client, self.识别器 = getAlibabaRecognizer(self.client,
self.appKey, self.appKey,
@ -140,11 +142,20 @@ class Thread_AliEngine(QThread):
rate=self.RATE, rate=self.RATE,
input=True, input=True,
frames_per_buffer=self.CHUNK) frames_per_buffer=self.CHUNK)
if self.持续录音:
while self.isRunning():
if self.识别中:
self.录音数据存入内存(stream)
else:
stream.read(self.CHUNK)
else:
self.录音数据存入内存(stream)
# print('录制器准备完毕') stream.stop_stream()# print('停止录制流')
# 录音写入序号 = 1 stream.close()
def 录音数据存入内存(self, stream):
for i in range(5): for i in range(5):
# self.访问录音数据的线程锁.acquire()
if not self.识别中: if not self.识别中:
self.data = [] self.data = []
# self.访问录音数据的线程锁.release() # self.访问录音数据的线程锁.release()
@ -153,7 +164,6 @@ class Thread_AliEngine(QThread):
self.data.append(stream.read(self.CHUNK)) self.data.append(stream.read(self.CHUNK))
# print(f'录音{录音写入序号},写入结束,时间 {time.time()}') # print(f'录音{录音写入序号},写入结束,时间 {time.time()}')
# 录音写入序号 += 1 # 录音写入序号 += 1
# self.访问录音数据的线程锁.release()
# 在这里录下5个小片段大约录制了0.32秒,如果这个时候松开了大写锁定键,就不打开连接。如果还继续按着,那就开始识别。 # 在这里录下5个小片段大约录制了0.32秒,如果这个时候松开了大写锁定键,就不打开连接。如果还继续按着,那就开始识别。
while self.识别中: while self.识别中:
@ -168,9 +178,6 @@ class Thread_AliEngine(QThread):
self.总共写入音频片段数 = len(self.data) self.总共写入音频片段数 = len(self.data)
# self.访问录音数据的线程锁.release() # self.访问录音数据的线程锁.release()
self.发送大写锁定键() # 再按下大写锁定键,还原大写锁定 self.发送大写锁定键() # 再按下大写锁定键,还原大写锁定
stream.stop_stream()# print('停止录制流')
stream.close()
# 这边开始上传识别 # 这边开始上传识别
def 识别(self): def 识别(self):
@ -250,6 +257,8 @@ class Thread_AliEngine(QThread):
return False return False
self.p = pyaudio.PyAudio() # 在 QThread 中引入 PyAudio 会使得 PySide2 图形界面阻塞 self.p = pyaudio.PyAudio() # 在 QThread 中引入 PyAudio 会使得 PySide2 图形界面阻塞
if self.持续录音:
threading.Thread(target=self.录音线程, args=[self.p]).start()
self.开始监听大写锁定键() self.开始监听大写锁定键()