Compare commits

...

5 Commits
v2.0 ... master

Author SHA1 Message Date
Haujet
f2b2038a2c 启用引擎时禁用其它按钮,这样就避免了误触,只有停止引擎时才能操作。更新版本号到 2.1.0 2021-02-11 08:51:11 +08:00
Haujet
6bd5f55dcf 经过测试,如果在windows上按下按键的时候才开始启动录音,录音启动会有一定的延迟,这个延迟大概在0.5到1秒钟。为了能做到按下按键的时候,就立刻开始录音,现在在启动引擎之后,现在程序会持续性调用麦克风(但不会将录音数据写入内存),对耗电量影响也不大,当按下按键的时候,就会立刻将录音数据开始写入内存,这样就可以做到按下按键的时候立马开始说话,也能捕捉到。
另外,录音进程是在一个新的线程中进行的,但是发现了pyside 的一个 bug,当新线程中存在一个 pyaudio stream 时,就会阻塞其他的图形界面。所以在启动引擎之后,就不要点击其他按钮了,可能会导致页面卡死。如果换成 PyQt5 就不会有这个问题。目前已反馈至 PySide 的 bug 反馈平台:https://bugreports.qt.io/browse/PYSIDE-1465,希望官方可以修复,如果不行的话,以后就换成 PyQt5。

对导入模块进行了精简。
2020-12-31 22:28:56 +08:00
Haujet
3d727d0364 为添加api的输入框设置了字符校验器,可以避免添加引擎的时候意外输入空格或者换行符 2020-12-28 12:46:34 +08:00
Haujet
c711dfc66c 将截取 sys.stdout 的过程放到了 tab 中
取消了一些 createDB 的 print 提示
使用 __file__ 的绝对路径添加当前目录和 bin 目录到环境变量
2020-12-27 22:37:19 +08:00
Haujet
c471e901ec 脚本改为 ansi 编码 2020-12-25 16:53:03 +08:00
21 changed files with 111 additions and 109 deletions

8
.gitignore vendored
View File

@ -5,16 +5,20 @@ __pycache__
*.mp4
*.mkv
*.wav
.DS_Store
.idea
.DS_Store
*info
*database.db
*test.py
*.7z
*/dist/*
*/build/*
*.db
*test/*
*.afphoto
icon*.png
Scripts/*
Lib/*
pyvenv.cfg
视频封面.png

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -1,5 +1,6 @@
setuptools
pyaudio
keyboard
aliyunsdkcore
aliyun-python-sdk-core
PySide2
pywin32

View File

@ -1,16 +1,14 @@
# -*- coding: UTF-8 -*-
import os, sys, time
try:
os.chdir(os.path.dirname(__file__)) # 更改工作目录,指向正确的当前文件夹
sys.path.append(os.path.dirname(__file__)) # 将当前目录导入 python 寻找 package 和 moduel 的变量
except:
print('更改使用路径失败,不过没关系')
os.chdir(os.path.dirname(os.path.abspath(__file__))) # 更改工作目录,指向正确的当前文件夹
sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 将当前目录导入 python 寻找 package 和 moduel 的变量
# os.environ['PATH'] += os.pathsep + os.path.abspath('./bin') # 将可执行文件的目录加入环境变量
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import QApplication
from PySide2.QtCore import QCoreApplication
from PySide2.QtGui import Qt
from moduels.function.createDB import createDB # 引入检查和创建创建数据库的函数
@ -23,11 +21,11 @@ from moduels.component.NormalValue import 常量
def 高分屏变量设置(app):
os.environ['QT_SCALE_FACTOR'] = '1'
app.setAttribute(Qt.AA_EnableHighDpiScaling)
QCoreApplication.instance().setAttribute(Qt.AA_UseHighDpiPixmaps)
def main():
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv)
高分屏变量设置(app)
createDB()

View File

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

View File

@ -5,7 +5,7 @@ import subprocess
class NormalValue():
样式文件 = 'misc/style.css'
软件版本 = '2.0.0'
软件版本 = '2.1.0'
主窗口 = None
托盘 = None

View File

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

View File

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

View File

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

View File

@ -19,8 +19,8 @@ def createDB():
value text
)''')
else:
print('偏好设置表单已存在')
#
# print('偏好设置表单已存在')
pass
result = cursor.execute(f'select * from sqlite_master where name = "{语音引擎表单名}";')
if result.fetchone() == None:
cursor.execute(f'''create table {语音引擎表单名} (
@ -33,7 +33,8 @@ def createDB():
AccessKeySecret text
)''')
else:
print('语音引擎表单名已存在')
# print('语音引擎表单名已存在')
pass
#
# result = cursor.execute(f'select * from sqlite_master where name = "{皮肤表单名}";')
# if result.fetchone() == None:

View File

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

View File

@ -33,6 +33,9 @@ class Dialog_AddEngine(QDialog):
self.表格布局 = QFormLayout()
self.按钮横向布局 = QHBoxLayout()
self.Api输入校验器 = QRegExpValidator()
def initSlots(self):
self.服务商选择框.currentTextChanged.connect(self.服务商变化)
@ -68,6 +71,11 @@ class Dialog_AddEngine(QDialog):
self.setWindowTitle(self.tr('添加或更新 Api'))
self.setWindowModality(Qt.NonModal)
self.Api输入校验器.setRegExp(QRegExp(r'\w+'))
self.appKey输入框.setValidator(self.Api输入校验器)
self.accessKeyId输入框.setValidator(self.Api输入校验器)
self.AccessKeySecret输入框.setValidator(self.Api输入校验器)
if self.列表.currentItem():
已选中的列表项 = self.列表.currentItem().text()
填充数据 = self.从数据库得到选中项的数据(已选中的列表项)

View File

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

View File

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

View File

@ -1,12 +1,11 @@
# -*- coding: UTF-8 -*-
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtWidgets import QMainWindow, QTabWidget
from PySide2.QtGui import QIcon, Qt
from moduels.component.NormalValue import 常量
from moduels.component.Stream import Stream
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_Help import Tab_Help
@ -24,7 +23,6 @@ class MainWindow(QMainWindow):
# self.setWindowState(Qt.WindowMaximized)
# sys.stdout = Stream(newText=self.onUpdateText)
def initElements(self):
self.状态栏 = self.statusBar()
@ -34,10 +32,9 @@ class MainWindow(QMainWindow):
# 定义多个不同功能的 tab
self.设置标签页 = Tab_Config() # 设置页要在前排加载,以确保一些设置加载成功
self.CapsWriter标签页 = Tab_CapsWriter() # 主要功能的 tab
# self.打印输出标签页 = Tab_Stdout()
self.帮助标签页 = Tab_Help()
self.标准输出流 = Stream()
#
@ -54,33 +51,17 @@ class MainWindow(QMainWindow):
# self.设置标签页.状态栏消息.connect(lambda 消息, 时间: self.状态栏.showMessage(消息, 时间))
self.帮助标签页.状态栏消息.connect(lambda 消息, 时间: self.状态栏.showMessage(消息, 时间))
self.标准输出流.newText.connect(self.CapsWriter标签页.更新控制台输出)
pass
def initValues(self):
# self.adjustSize()
# self.setGeometry(QStyle(Qt.LeftToRight, Qt.AlignCenter, self.size(), QApplication.desktop().availableGeometry()))
常量.状态栏 = self.状态栏
sys.stdout = self.标准输出流
self.setWindowIcon(QIcon(常量.图标路径))
self.setWindowTitle('CapsWriter 语音输入工具')
self.setWindowFlag(Qt.WindowStaysOnTopHint) # 始终在前台
print("""\n软件介绍:
CapsWriter顾名思义就是按下大写锁定键来打字的工具它的具体作用是当你按下键盘上的大写锁定键后软件开始语音识别当你松开大写锁定键时识别的结果就可以立马上屏
目前软件内置了对阿里云一句话识别 API 的支持如果你要使用就需要先在阿里云上实名认证申请语音识别 API在设置页面添加一个语音识别引擎
具体申请阿里云 API 的方法可以参考我这个视频https://www.bilibili.com/video/BV1qK4y1s7Fb/
添加上引擎后在当前页面选择一个引擎点击启用按钮就可以进行语音识别了
启用后在实际使用中只要按下 CapsLock 软件就会立刻开始录音
如果只是单击 CapsLock 后松开录音数据会立刻被删除
如果按下 CapsLock 键时长超过 0.3 就会开始连网进行语音识别松开 CapsLock 键时语音识别结果会被立刻输入
所以你只需要按下 CapsLock 无需等待就可以开始说话因为当你按下按下 CapsLock 键的时候程序就开始录音了说完后松开识别结果立马上屏\r\n""")
self.show()

View File

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

View File

@ -1,28 +1,16 @@
# -*- coding: UTF-8 -*-
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
from PySide2.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QPushButton
# from PySide2.QtGui import *
from PySide2.QtCore import Signal
import os, re, subprocess, time
import pyaudio
# from moduels.component.QLEdit_FilePathQLineEdit import QLEdit_FilePathQLineEdit
from moduels.component.NormalValue import 常量
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_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
@ -53,7 +41,11 @@ class Tab_CapsWriter(QWidget):
self.停止按钮 = QPushButton('停止 CapsWriter')
self.启停按钮Box布局 = QHBoxLayout()
def initLayouts(self):
self.引擎选择Box布局.addWidget(self.引擎选择下拉框)
self.控制台输出Box布局.addWidget(self.控制台输出框)
@ -78,18 +70,35 @@ class Tab_CapsWriter(QWidget):
def 更新控制台输出(self, 文本):
self.控制台输出框.print(文本)
def initValues(self):
self.引擎线程 = None
# self.aliClient = ali_speech.NlsClient()
# self.aliClient.set_log_level('WARNING') # 设置 client 输出日志信息的级别DEBUG、INFO、WARNING、ERROR
self.停止按钮.setDisabled(True)
print("""\n软件介绍:
CapsWriter顾名思义就是按下大写锁定键来打字的工具它的具体作用是当你按下键盘上的大写锁定键后软件开始语音识别当你松开大写锁定键时识别的结果就可以立马上屏
目前软件内置了对阿里云一句话识别 API 的支持如果你要使用就需要先在阿里云上实名认证申请语音识别 API在设置页面添加一个语音识别引擎
具体申请阿里云 API 的方法可以参考我这个视频https://www.bilibili.com/video/BV1qK4y1s7Fb/
添加上引擎后在当前页面选择一个引擎点击启用按钮就可以进行语音识别了
启用后在实际使用中只要按下 CapsLock 软件就会立刻开始录音
如果只是单击 CapsLock 后松开录音数据会立刻被删除
如果按下 CapsLock 键时长超过 0.3 就会开始连网进行语音识别松开 CapsLock 键时语音识别结果会被立刻输入
所以你只需要按下 CapsLock 无需等待就可以开始说话因为当你按下按下 CapsLock 键的时候程序就开始录音了说完后松开识别结果立马上屏\r\n""")
def 启动引擎(self):
if self.引擎线程 != None: return
引擎名称 = self.引擎选择下拉框.currentText()
if 引擎名称 == '': return
self.启动按钮.setDisabled(True)
self.引擎选择下拉框.setDisabled(True)
self.parent().parent().setTabEnabled(1, False)
self.parent().parent().setTabEnabled(2, False)
self.停止按钮.setEnabled(True)
result = 常量.数据库连接.execute(f'''select * from {常量.语音引擎表单名} where 引擎名称 = :引擎名称''',
{'引擎名称': 引擎名称}).fetchone()
@ -107,6 +116,9 @@ class Tab_CapsWriter(QWidget):
# print(self.引擎线程.isRunning())
self.引擎线程 = None
self.启动按钮.setEnabled(True)
self.引擎选择下拉框.setEnabled(True)
self.parent().parent().setTabEnabled(1, True)
self.parent().parent().setTabEnabled(2, True)
self.停止按钮.setDisabled(True)

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@ pyinstaller --hidden-import sqlite3 --noconfirm -i "../src/misc/icon.ico" "..
echo d | xcopy /y /s .\dist\rely .\dist\__init__
ren .\dist\__init__\__init__.exe "_CapsWriter语音输入工具.exe"
ren .\dist\__init__\__init__.exe "_CapsWriter刀稜渴흙묏야.exe"
move .\dist\__init__ .\dist\CapsWriter