diff --git a/EVT_GUI/Functions.py b/EVT_GUI/Functions.py index 8d9f06f..79a65ff 100644 --- a/EVT_GUI/Functions.py +++ b/EVT_GUI/Functions.py @@ -1,6 +1,7 @@ import re from typing import Union, Optional from PySide6.QtCore import Qt, QObject, Signal, Slot +from PySide6.QtCore import QCoreApplication as QCA from PySide6.QtGui import QFont from PySide6.QtWidgets import * @@ -10,71 +11,25 @@ from .Window import * ############################################################################################################################## -""" -def Function_InsertUI( - ParentUI: QWidget, - InsertType: object, - InsertPosition: str = "End", - UIParam: Optional[str] = None, - UIToolTip: Optional[str] = None, -): + +# Where to store custom signals +class CustomSignals_Functions(QObject): ''' - Function to insert UI - ''' - InsertUI = InsertType(UIParam) - if isinstance(InsertUI, QAbstractButton): - InsertUI.setMinimumHeight(24) - InsertUI.setStyleSheet( - f"{InsertType.__name__}" - "{" - "text-align: center;" - "font-size: 12px;" - "color: rgb(255, 255, 255);" - "background-color: rgb(90, 90, 90);" - "padding: 0px;" - "border-width: 0px;" - "border-radius: 6px;" - "border-style: solid;" - "}" - f"{InsertType.__name__}:hover" - "{" - "background-color: rgb(120, 120, 120);" - "}" - - "QToolTip" - "{" - "color: rgba(255, 255, 255, 210);" - "background-color: transparent;" - "border-width: 0px;" - "border-style: solid;" - "}" - ) - else: - pass + Set up signals for functions + ''' + # Run task + Signal_ExecuteTask = Signal(tuple) - Layout = ParentUI.layout() if ParentUI.layout() != None else QGridLayout(ParentUI) - if InsertPosition == "Start": - RowCount = 0 - if InsertPosition == "End": - RowCount = ParentUI.document().lineCount() if isinstance(ParentUI, (QPlainTextEdit, QTextEdit, QTextBrowser)) else round(ParentUI.height()/15) - for Row in range(0, RowCount): - SpacingUI = QWidget(ParentUI) - SpacingUI.setStyleSheet( - "QWidget" - "{" - "background-color: transparent;" - "padding: 0px;" - "border-width: 0px;" - "}" - ) - Layout.addWidget(SpacingUI, Row, 0) - Layout.addWidget(InsertUI, RowCount, 0) - - InsertUI.setToolTipDuration(-1) - InsertUI.setToolTip(UIToolTip) + # Monitor task + Signal_TaskStatus = Signal(str, str) + + # Force exit + Signal_ForceQuit = Signal() - return InsertUI -""" + +FunctionSignals = CustomSignals_Functions() + +############################################################################################################################## def Function_ScrollToWidget( Trigger: QWidget, @@ -107,8 +62,7 @@ def TreeWidgetEvent(Item, Column): def Function_SetTreeWidget( TreeWidget: QTreeWidget, - RootItemTexts: list = [], - ChildItemTexts: list = [()], + ItemTexts: dict = {'RootItemText': ('ChildItemText', )}, AddVertically: bool = False, HideHeader: bool = True, ExpandItems: bool = True @@ -119,13 +73,13 @@ def Function_SetTreeWidget( RootItems = [] - for Index, RootItemText in enumerate(ToIterable(RootItemTexts)): + for Index, RootItemText in enumerate(ItemTexts.keys()): RootItem = QTreeWidgetItem(TreeWidget) RootItem.setText(0 if AddVertically else Index, RootItemText) RootItemTextFont = QFont() RootItemTextFont.setPixelSize(15) RootItem.setFont(0 if AddVertically else Index, RootItemTextFont) - for ChildItemText in ToIterable(ChildItemTexts[Index]): + for ChildItemText in ToIterable(list(ItemTexts.values())[Index]): ChildItem = QTreeWidgetItem(RootItem) ChildItem.setText(0 if AddVertically else Index, ChildItemText) ChildItemTextFont = QFont() @@ -179,6 +133,19 @@ def Function_SetChildWidgetsVisibility( ) +def Function_SetImage(Widget: QWidget, ImagePath: str): + ''' + ''' + Image = QImage() + Image.load(NormPath(ImagePath)) + Pixmap = QPixmap.fromImage(Image) + def SetPic(): + Length = max(Widget.width(), Widget.height()) + ScaledPixmap = Pixmap.scaled(Length, Length, Qt.KeepAspectRatio, Qt.SmoothTransformation) + Widget.setPixmap(ScaledPixmap) + Widget.resized.connect(SetPic) if hasattr(Widget, 'resized') else SetPic() + + def Function_ConfigureCheckBox( CheckBox: QCheckBox, CheckedText: Optional[str] = None, @@ -557,7 +524,7 @@ def ResetParam(self, Widget: QWidget): Function_SetWidgetValue(Widget, self.Config, *value) def ClearSettings(self): - with open(self.ConfigPath, 'w') as Config: + with open(self.ConfigPath, 'w'): pass self.Config = ManageConfig(self.ConfigPath) @@ -577,4 +544,136 @@ def ExportSettings(self, SavePath: str): with open(SavePath, 'w') as Config: self.Config.Parser().write(Config) +############################################################################################################################## + +class Execute_Task(QObject): + ''' + A example class to excute tasks + ''' + started = Signal() + finished = Signal(str) + + def __init__(self): + super().__init__() + + @Slot(tuple) + def Execute(self, Params: tuple): + self.started.emit() + + def _run(self, Params: tuple): + ''' + Should put your task here and need to return an error info + ''' + Error = self._run(Params) + + self.finished.emit(str(Error)) + + def Terminate(self): + ProcessTerminator(self.Process.pid) if hasattr(self, 'Process') else None + + +def Function_SetMethodExecutor( + ParentWindow: Optional[QWidget] = None, + ExecuteButton: Optional[QAbstractButton] = None, + TerminateButton: Optional[QAbstractButton] = None, + ProgressBar: Optional[QProgressBar] = None, + ConsoleWidget: Optional[QWidget] = None, + Method: object = ..., + Params: Optional[tuple] = None, + ParamsFrom: Optional[list[QObject]] = None, + EmptyAllowed: Optional[list[QObject]] = None, + #StartEvents: Optional[list] = None, + FinishEvents: Optional[list] = None +): + ''' + Function to execute outer class methods + ''' + QualName = str(Method.__qualname__) + MethodName = QualName.split('.')[1] + + ClassInstance = GetClassFromMethod(Method)() + ClassInstance.started.connect(lambda: FunctionSignals.Signal_TaskStatus.emit(QualName, 'Started')) if hasattr(ClassInstance, 'started') else None + #ClassInstance.started.connect(lambda: RunEvents(StartEvents)) if hasattr(ClassInstance, 'started') else None + ClassInstance.finished.connect(lambda Error: FunctionSignals.Signal_TaskStatus.emit(QualName, 'Finished') if Error == str(None) else None) if hasattr(ClassInstance, 'finished') else None + ClassInstance.finished.connect(lambda Error: RunEvents(FinishEvents) if Error == str(None) else None) if hasattr(ClassInstance, 'finished') else None + ClassInstance.finished.connect(lambda Error: FunctionSignals.Signal_TaskStatus.emit(QualName, 'Failed') if Error != str(None) else None) if hasattr(ClassInstance, 'finished') else None + ClassInstance.finished.connect(lambda Error: Function_ShowMessageBox(ParentWindow, QMessageBox.Warning, 'Failure', f'发生错误:\n{Error}') if Error != str(None) else None) if hasattr(ClassInstance, 'finished') else None + + if not isinstance(ClassInstance, QThread): + WorkerThread = QThread() + ClassInstance.moveToThread(WorkerThread) + ClassInstance.finished.connect(WorkerThread.quit) if hasattr(ClassInstance, 'finished') else None + else: + WorkerThread = ClassInstance + + @Slot() + def ExecuteMethod(): + ''' + Update the attributes for outer class methods and wait to execute with multithreading + ''' + Args = Params#if Params != () else None + if ParamsFrom not in ([], None): + Args = Function_ParamsChecker(ParamsFrom, EmptyAllowed) + if Args == "Abort": + return print("Aborted.") + else: + pass #print("Continued.\n") + + FunctionSignals = CustomSignals_Functions() + FunctionSignals.Signal_ExecuteTask.connect(getattr(ClassInstance, MethodName)) #FunctionSignals.Signal_ExecuteTask.connect(lambda Args: getattr(ClassInstance, MethodName)(*Args)) + + WorkerThread.started.connect(lambda: Function_AnimateFrame(ConsoleWidget, MinHeight = 0, MaxHeight = 210, Mode = "Extend")) if ConsoleWidget else None + WorkerThread.started.connect(lambda: Function_AnimateProgressBar(ProgressBar, IsTaskAlive = True)) if ProgressBar else None + WorkerThread.started.connect(lambda: Function_AnimateStackedWidget(Function_FindParentUI(ExecuteButton, QStackedWidget), TargetIndex = 1)) if TerminateButton else None + WorkerThread.finished.connect(lambda: Function_AnimateFrame(ConsoleWidget, MinHeight = 0, MaxHeight = 210, Mode = "Reduce")) if ConsoleWidget else None + WorkerThread.finished.connect(lambda: Function_AnimateProgressBar(ProgressBar, IsTaskAlive = False)) if ProgressBar else None + WorkerThread.finished.connect(lambda: Function_AnimateStackedWidget(Function_FindParentUI(ExecuteButton, QStackedWidget), TargetIndex = 0)) if TerminateButton else None + #WorkerThread.finished.connect(lambda: FunctionSignals.Signal_ExecuteTask.disconnect(getattr(ClassInstance, MethodName))) + + FunctionSignals.Signal_ExecuteTask.emit(Args) + + WorkerThread.start() + + if ExecuteButton is not None: + ExecuteButton.clicked.connect(ExecuteMethod) + ExecuteButton.setText(QCA.translate("Button", "执行")) if len(ExecuteButton.text().strip()) == 0 else None + else: + TempButton = QPushButton(ParentWindow) + TempButton.clicked.connect(ExecuteMethod) + TempButton.setVisible(False) + TempButton.click() + WorkerThread.finished.connect(TempButton.deleteLater) + + @Slot() + def TerminateMethod(): + ''' + Terminate the running thread + ''' + if not WorkerThread.isFinished(): + try: + WorkerThread.terminate() + except: + WorkerThread.quit() + + ClassInstance.Terminate() if hasattr(ClassInstance, 'Terminate') else ProcessTerminator('python.exe', SearchKeyword = True) + + FunctionSignals.Signal_TaskStatus.emit(QualName, 'Failed') if hasattr(ClassInstance, 'finished') else None + + ProgressBar.setValue(0) if ProgressBar else None + + if TerminateButton is not None: + TerminateButton.clicked.connect( + lambda: Function_ShowMessageBox(ParentWindow, + MessageType = QMessageBox.Question, + WindowTitle = "Ask", + Text = "当前任务仍在执行中,是否确认终止?", + Buttons = QMessageBox.Yes|QMessageBox.No, + ButtonEvents = {QMessageBox.Yes: lambda: TerminateMethod()} + ) + ) + TerminateButton.setText(QCA.translate("Button", "终止")) if len(TerminateButton.text().strip()) == 0 else None + FunctionSignals.Signal_ForceQuit.connect(TerminateMethod) + else: + pass + ############################################################################################################################## \ No newline at end of file diff --git a/README.md b/README.md index f125f09..81c76c7 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ![Title](/docs/media/Title.png "Home Page") [![Releases](https://img.shields.io/github/v/release/Spr-Aachen/Easy-Voice-Toolkit?color=green&label=Release&logo=Github&logoColor=white&style=for-the-badge)](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/releases/latest)  -[![Bilibili](https://img.shields.io/badge/Bilibili-v1.0%20Intro-blue?logo=Bilibili&style=for-the-badge)](https://www.bilibili.com/video/BV)  +[![Bilibili](https://img.shields.io/badge/Bilibili-v1.0%20Intro-blue?logo=Bilibili&style=for-the-badge)](https://www.bilibili.com/video/BV1uJ4m157P2)  [![YouTube](https://img.shields.io/badge/YouTube-v1.0%20Intro-red?logo=YouTube&style=for-the-badge)](https://www.youtube.com/watch?v=) @@ -17,43 +17,39 @@

-## 项目介绍
Description +
+ +[**简体中文**](./docs/README_CN.md) | **English** + +
-### 概述
Overview -一个基于开源语音项目实现的简易语音工具箱,提供了包括语音模型训练在内的多种自动化音频工具 -
A toolkit based on open source voice projects,which provides a variety of automated audio tools including speech model training +## Description -
工具箱目前包含以下功能: -
Functions that are currently included in the toolkit are as follows: +### Overview -- [音频处理](/docs/Audio-Processor.md) -
Audio Processing +A toolkit based on open source voice projects,which provides a variety of automated audio tools including speech model training -- [语音识别](/docs/Voice-Recognizer.md) -
Voice Recognition +Functions that are currently included in the toolkit are as follows: -- [语音转录](/docs/Voice-Transcriber.md) -
Voice Transcribing +- [Audio Processing](/docs/Audio-Processor.md) -- [数据集制作](/docs/Dataset-Creator.md) -
Dataset Creating (SRT Converting & WAV Splitting) +- [Voice Recognition](/docs/Voice-Recognizer.md) -- [模型训练](/docs/Voice-Trainer.md) -
Model Training +- [Voice Transcribing](/docs/Voice-Transcriber.md) -- [语音合成](/docs/Voice-Converter.md) -
Voice Convertion +- [Dataset Creating (SRT Converting & WAV Splitting)](/docs/Dataset-Creator.md) + +- [Model Training](/docs/Voice-Trainer.md) + +- [Voice Convertion](/docs/Voice-Converter.md) -
这些功能依次关联,能够形成一套完整的工作流
These functions can be seamlessly integrated to form a complete workflow -
用户可以根据自己的需求有选择性地使用,亦或者依次通过这些工具将未经处理的语音文件逐步变为理想的语音模型
Users can use these tools selectively according to their own needs, or use them in sequence to gradually transform raw audio files into ideal speech models -### 鸣谢
Acknowledgement +### Acknowledgement -由衷感谢以下项目的作者,这个工具箱的实现正是得益于他们的优秀成果 -
I'd like to express my sincere gratitude to the authors of the following projects, as their excellent work has contributed to the implementation of this toolkit +I'd like to express my sincere gratitude to the authors of the following projects, as their excellent work has contributed to the implementation of this toolkit - [audio-slicer](https://github.com/openvpi/audio-slicer) - [VoiceprintRecognition](https://github.com/yeyupiaoling/VoiceprintRecognition-Pytorch/tree/release/1.0) @@ -63,142 +59,129 @@ - [GPT-SoVITS](https://github.com/RVC-Boss/GPT-SoVITS) -## 注意事项
Consideration +## Consideration -### 系统
System +### System -目前UI界面仅支持Windows系统 -
Currently the UI interface only supports Windows system +Currently the UI interface only supports Windows system -### 语言
Language +### Language -目前各个工具对语言的支持情况如下: -
Languages that are currently supported/unsupported by the tools are shown as follows: +Languages that are currently supported/unsupported by the tools are shown as follows: - - - - + + + + - + - + - + - + - + - +
工具
Tool
中文
Chinese
英文
English
日文
Japnese
ToolChineseEnglishJapnese
音频处理
Audio Processor
Audio Processor
语音识别
Voice Recognizer
Voice Recognizer
语音转录
Voice Transcriber
Voice Transcriber
数据集制作
DataSet Creator
DataSet Creator
模型训练
Voice Trainer
Voice Trainer
语音合成
Voice Converter
Voice Converter
-## 项目部署
Deployment +## Deployment -### 本地部署 - 用户
Local Deployment - User +### Local Deployment - User -#### 下载
Download +#### Download -您有两种选择: -
-- 下载[轻量化的安装程序](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/releases/latest):包体小且拥有安装引导,但是未配置环境依赖且不带模型 -
Download the [lightweight installer](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/releases/latest): small package comes with installation instructions, but without necessary environmental dependencies and models +You have two options: -- 下载[解压即用的懒人包](https://pixeldrain.com/api/file/JLUJwfNA?download):配置了所有环境依赖并附带有预设模型,但是包体较大且需要解压 -
Download the [Ready-to-use portable package](https://pixeldrain.com/api/file/JLUJwfNA?download): huge package with all environmental dependencies and several model presets, need to unpack after download +- Download the [lightweight installer](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/releases/latest): small package comes with installation instructions, but without necessary environmental dependencies and models -#### 运行
Run +- Download the [Ready-to-use portable package](https://pixeldrain.com/api/file/JLUJwfNA?download): huge package with all environmental dependencies and several model presets, need to unpack after download -点击.exe文件或其快捷方式即可 -
Just click on the .exe file or its shortcut +#### Run -### 本地部署 - 开发者
Local Deployment - Developer +Just click on the .exe file or its shortcut -#### 搭建环境
Setup Environment +### Local Deployment - Developer -- 请确保您已安装了`版本≥3.8`的[Python](https://www.python.org/downloads/) -
Please make sure that you've installed [Python](https://www.python.org/downloads/) `version 3.8 or higher` +#### Setup Environment -#### 获取项目
Obtain Project +Please make sure that you've installed [Python](https://www.python.org/downloads/) `version 3.8 or higher` -- 克隆项目仓库 -
Clone Repository +#### Obtain Project + +- Clone Repository ```shell git clone https://github.com/Spr-Aachen/Easy-Voice-Toolkit.git ``` -- 切至项目目录 -
Change directory +- Change directory ```shell %cd Easy-Voice-Toolkit ``` -#### 安装依赖
Install Dependencies +#### Install Dependencies -- 安装pytorch(需从[官网](https://pytorch.org/get-started/locally/)复制命令) -
Install pytorch (Command can be get from the [official site](https://pytorch.org/get-started/locally/)) +- Install pytorch (Command can be get from the [official site](https://pytorch.org/get-started/locally/)) ```shell # e.g. (注意自己的cuda版本,这里以11.8为例) pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu118 ``` -- 安装项目依赖 -
Install project requirements +- Install project requirements ```shell pip install -r requirements.txt ``` -- 安装GUI依赖 -
Install GUI dependency +- Install GUI dependency ```shell pip install pyside6 QEasyWidgets pywin32==300 psutil pynvml darkdetect PyGithub ``` -#### 运行程序
Run Programm +#### Run Programm -- 启动图形界面 -
Activate GUI +- Activate GUI ```shell Run.py ``` -### 云端部署
Cloud Deployment +### Cloud Deployment #### Google Colab [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Spr-Aachen/EVT-Resources/blob/main/Easy_Voice_Toolkit_for_Colab.ipynb) -
点击以使用上面的demo,或者在Colab中上传[Run.ipynb](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/blob/main/Run.ipynb)
Click to use the demo above, or access to Colab and upload [Run.ipynb](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/blob/main/Run.ipynb) -## 测试平台
Tested Devices +## Tested Devices ### Windows OS @@ -218,19 +201,19 @@ #### (Waiting to add other devices) -## 疑问解答
FAQ +## FAQ -- **Q**: 更新客户端/下载依赖/模型时总是提示失败/报错该怎么办? -
**A**: 开代理或者直接用懒人包 +- **Q**: What should I do if the client update / dependency download always fails or gives an error? +
**A**: Use a proxy or switch to the Ready-to-use portable package. -- **Q**: 好多参数都不清楚要如何设置该怎么办? -
**A**: 不明白的话使用默认值就好 +- **Q**: There are many parameter settings that I don't know how to deal with, what should I do? +
**A**: Just use the default values. -- **Q**: 你这永久免费开源...它保真吗? -
**A**: 嗯哼~♪ +- **Q**: Free and open source ? +
**A**: Natürlich~♪ -## 使用条例
Terms of Use +## Terms of Use **Please solve the authorization problem of the dataset on your own. You shall be solely responsible for any problems caused by the use of non-authorized datasets for training and all consequences thereof.The repository and its maintainer have nothing to do with the consequences!** @@ -248,16 +231,13 @@ Reference: [so-vits-svc](https://github.com/svc-develop-team/so-vits-svc) -**相关法律请参照《中华人民共和国治安管理处罚法》和《中华人民共和国民法典》。** - -## 联系方式
Contact Details +## Contact Details [![QQ](https://img.shields.io/badge/QQ-2835946988-brightgreen?style=for-the-badge&logo=tencent-qq&logoColor=white)]() -
倘若大伙儿有什么好的建议欢迎随时叨扰哦~
Please feel free to contact me at any time, any comments and suggestions will be appreciated:) -## 收藏趋势
Stargazers over time +## Stargazers over time [![Stargazers over time](https://starchart.cc/Spr-Aachen/Easy-Voice-Toolkit.svg)](https://starchart.cc/Spr-Aachen/Easy-Voice-Toolkit) \ No newline at end of file diff --git a/Run.py b/Run.py index cd414a7..61fa08c 100644 --- a/Run.py +++ b/Run.py @@ -20,7 +20,7 @@ ############################################################################################################################## # Set current version -CurrentVersion = "v1.0.9" +CurrentVersion = "v1.1.0" ############################################################################################################################## @@ -844,15 +844,6 @@ class CustomSignals_MainWindow(QObject): ''' Signal_MainWindowShown = Signal() - # Run task - Signal_ExecuteTask = Signal(tuple) - - # Monitor task - Signal_TaskStatus = Signal(str, str) - - # Force exit - Signal_ForceQuit = Signal() - MainWindowSignals = CustomSignals_MainWindow() @@ -869,109 +860,6 @@ def __init__(self): self.MonitorUsage = MonitorUsage() self.MonitorUsage.start() - def Function_SetMethodExecutor(self, - ExecuteButton: Optional[QAbstractButton] = None, - TerminateButton: Optional[QAbstractButton] = None, - ProgressBar: Optional[QProgressBar] = None, - ConsoleWidget: Optional[QWidget] = None, - Method: object = ..., - Params: Optional[tuple] = None, - ParamsFrom: Optional[list[QObject]] = None, - EmptyAllowed: Optional[list[QObject]] = None, - #StartEvents: Optional[list] = None, - FinishEvents: Optional[list] = None - ): - ''' - Function to execute outer class methods (through button) - ''' - QualName = str(Method.__qualname__) - ClassName = QualName.split('.')[0] - MethodName = QualName.split('.')[1] - - ClassInstance = globals()[ClassName]() - ClassInstance.started.connect(lambda: MainWindowSignals.Signal_TaskStatus.emit(QualName, 'Started')) if hasattr(ClassInstance, 'started') else None - #ClassInstance.started.connect(lambda: RunEvents(StartEvents)) if hasattr(ClassInstance, 'started') else None - ClassInstance.finished.connect(lambda Error: MainWindowSignals.Signal_TaskStatus.emit(QualName, 'Finished') if Error == str(None) else None) if hasattr(ClassInstance, 'finished') else None - ClassInstance.finished.connect(lambda Error: RunEvents(FinishEvents) if Error == str(None) else None) if hasattr(ClassInstance, 'finished') else None - ClassInstance.finished.connect(lambda Error: MainWindowSignals.Signal_TaskStatus.emit(QualName, 'Failed') if Error != str(None) else None) if hasattr(ClassInstance, 'finished') else None - ClassInstance.finished.connect(lambda Error: Function_ShowMessageBox(self, QMessageBox.Warning, 'Failure', f'发生错误:\n{Error}') if Error != str(None) else None) if hasattr(ClassInstance, 'finished') else None - - if not isinstance(ClassInstance, QThread): - WorkerThread = QThread() - ClassInstance.moveToThread(WorkerThread) - ClassInstance.finished.connect(WorkerThread.quit) if hasattr(ClassInstance, 'finished') else None - else: - WorkerThread = ClassInstance - - @Slot() - def ExecuteMethod(): - ''' - Update the attributes for outer class methods and wait to execute with multithreading - ''' - Args = Params#if Params != () else None - if ParamsFrom not in ([], None): - Args = Function_ParamsChecker(ParamsFrom, EmptyAllowed) - if Args == "Abort": - return print("Aborted.") - else: - pass #print("Continued.\n") - - MainWindowSignals = CustomSignals_MainWindow() - MainWindowSignals.Signal_ExecuteTask.connect(getattr(ClassInstance, MethodName)) #MainWindowSignals.Signal_ExecuteTask.connect(lambda Args: getattr(ClassInstance, MethodName)(*Args)) - - WorkerThread.started.connect(lambda: Function_AnimateFrame(ConsoleWidget, MinHeight = 0, MaxHeight = 210, Mode = "Extend")) if ConsoleWidget else None - WorkerThread.started.connect(lambda: Function_AnimateProgressBar(ProgressBar, IsTaskAlive = True)) if ProgressBar else None - WorkerThread.started.connect(lambda: Function_AnimateStackedWidget(Function_FindParentUI(ExecuteButton, QStackedWidget), TargetIndex = 1)) if TerminateButton else None - WorkerThread.finished.connect(lambda: Function_AnimateFrame(ConsoleWidget, MinHeight = 0, MaxHeight = 210, Mode = "Reduce")) if ConsoleWidget else None - WorkerThread.finished.connect(lambda: Function_AnimateProgressBar(ProgressBar, IsTaskAlive = False)) if ProgressBar else None - WorkerThread.finished.connect(lambda: Function_AnimateStackedWidget(Function_FindParentUI(ExecuteButton, QStackedWidget), TargetIndex = 0)) if TerminateButton else None - #WorkerThread.finished.connect(lambda: MainWindowSignals.Signal_ExecuteTask.disconnect(getattr(ClassInstance, MethodName))) - - MainWindowSignals.Signal_ExecuteTask.emit(Args) - - WorkerThread.start() - - if ExecuteButton is not None: - ExecuteButton.clicked.connect(ExecuteMethod) - ExecuteButton.setText(QCA.translate("Button", "执行")) if len(ExecuteButton.text().strip()) == 0 else None - else: - TempButton = QPushButton(self) - TempButton.clicked.connect(ExecuteMethod) - TempButton.click() - WorkerThread.finished.connect(TempButton.deleteLater) - - @Slot() - def TerminateMethod(): - ''' - Terminate the running thread - ''' - if not WorkerThread.isFinished(): - try: - WorkerThread.terminate() - except: - WorkerThread.quit() - - ClassInstance.Terminate() if hasattr(ClassInstance, 'Terminate') else ProcessTerminator('python.exe', SearchKeyword = True) - - MainWindowSignals.Signal_TaskStatus.emit(QualName, 'Failed') if hasattr(ClassInstance, 'finished') else None - - ProgressBar.setValue(0) if ProgressBar else None - - if TerminateButton is not None: - TerminateButton.clicked.connect( - lambda: Function_ShowMessageBox(self, - MessageType = QMessageBox.Question, - WindowTitle = "Ask", - Text = "当前任务仍在执行中,是否确认终止?", - Buttons = QMessageBox.Yes|QMessageBox.No, - ButtonEvents = {QMessageBox.Yes: lambda: TerminateMethod()} - ) - ) - TerminateButton.setText(QCA.translate("Button", "终止")) if len(TerminateButton.text().strip()) == 0 else None - MainWindowSignals.Signal_ForceQuit.connect(TerminateMethod) - else: - pass - def Main(self): ''' Main funtion to orgnize all the subfunctions @@ -1004,8 +892,8 @@ def Main(self): # Window controling buttons self.closed.connect( lambda: ( - MainWindowSignals.Signal_ForceQuit.emit(), - MainWindowSignals.Signal_TaskStatus.connect(QApplication.exit), + FunctionSignals.Signal_ForceQuit.emit(), + FunctionSignals.Signal_TaskStatus.connect(QApplication.exit), #os._exit(0) ) ) @@ -1167,15 +1055,10 @@ def Main(self): ############################################################# #self.ui.ToolButton_Home_Title.setText(QCA.translate("Label", "主页")) - - Image = QImage() - Image.load(NormPath(Path(ResourceDir).joinpath('Sources/Cover.png'), 'Posix')) - Pixmap = QPixmap.fromImage(Image) - def SetPic(): - Length = max(self.ui.Label_Cover_Home.width(), self.ui.Label_Cover_Home.height()) - ScaledPixmap = Pixmap.scaled(Length, Length, Qt.KeepAspectRatio, Qt.SmoothTransformation) - self.ui.Label_Cover_Home.setPixmap(ScaledPixmap) - self.ui.Label_Cover_Home.Resized.connect(SetPic) + Function_SetImage( + Widget = self.ui.Label_Cover_Home, + ImagePath = Path(ResourceDir).joinpath('Sources/Cover.png') + ) Function_SetText( Widget = self.ui.TextBrowser_Text_Home, @@ -1238,7 +1121,7 @@ def SetPic(): self.ui.ToolButton_Env_Install_Title.setText(QCA.translate("Label", "自动配置")) self.ui.Label_Env_Install_Aria2.setText(QCA.translate("Label", "Aria2")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Install_Aria2, ProgressBar = self.ui.ProgressBar_Env_Install_Aria2, Method = Aria2_Installer.Execute, @@ -1282,7 +1165,7 @@ def SetPic(): ) self.ui.Label_Env_Install_FFmpeg.setText(QCA.translate("Label", "FFmpeg")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Install_FFmpeg, ProgressBar = self.ui.ProgressBar_Env_Install_FFmpeg, Method = FFmpeg_Installer.Execute, @@ -1326,7 +1209,7 @@ def SetPic(): ) self.ui.Label_Env_Install_Python.setText(QCA.translate("Label", "Python")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Install_Python, ProgressBar = self.ui.ProgressBar_Env_Install_Python, Method = Python_Installer.Execute, @@ -1370,7 +1253,7 @@ def SetPic(): ) self.ui.Label_Env_Install_PyReqs.setText(QCA.translate("Label", "Python Requirements")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Install_PyReqs, ProgressBar = self.ui.ProgressBar_Env_Install_PyReqs, Method = PyReqs_Installer.Execute, @@ -1414,7 +1297,7 @@ def SetPic(): ) self.ui.Label_Env_Install_Pytorch.setText(QCA.translate("Label", "Pytorch")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Install_Pytorch, ProgressBar = self.ui.ProgressBar_Env_Install_Pytorch, Method = Pytorch_Installer.Execute, @@ -1462,7 +1345,7 @@ def SetPic(): ############################################################# MainWindowSignals.Signal_MainWindowShown.connect( - lambda: self.Function_SetMethodExecutor( + lambda: Function_SetMethodExecutor(self, Method = Model_View.Execute ) ) @@ -1485,7 +1368,7 @@ def SetPic(): self.ui.Table_Models_Process_UVR.SetHorizontalHeaders(['名字', '类型', '大小', '日期', '操作']) ModelViewSignals.Signal_Process_UVR.connect(self.ui.Table_Models_Process_UVR.SetValue) self.ui.Table_Models_Process_UVR.Download.connect( - lambda Params: self.Function_SetMethodExecutor( + lambda Params: Function_SetMethodExecutor(self, Method = Model_Downloader.Execute, Params = Params ) @@ -1509,7 +1392,7 @@ def SetPic(): self.ui.Table_Models_ASR_VPR.SetHorizontalHeaders(['名字', '类型', '大小', '日期', '操作']) ModelViewSignals.Signal_ASR_VPR.connect(self.ui.Table_Models_ASR_VPR.SetValue) self.ui.Table_Models_ASR_VPR.Download.connect( - lambda Params: self.Function_SetMethodExecutor( + lambda Params: Function_SetMethodExecutor(self, Method = Model_Downloader.Execute, Params = Params ) @@ -1533,7 +1416,7 @@ def SetPic(): self.ui.Table_Models_STT_Whisper.SetHorizontalHeaders(['名字', '类型', '大小', '日期', '操作']) ModelViewSignals.Signal_STT_Whisper.connect(self.ui.Table_Models_STT_Whisper.SetValue) self.ui.Table_Models_STT_Whisper.Download.connect( - lambda Params: self.Function_SetMethodExecutor( + lambda Params: Function_SetMethodExecutor(self, Method = Model_Downloader.Execute, Params = Params ) @@ -1557,7 +1440,7 @@ def SetPic(): self.ui.Table_Models_TTS_GPTSoVITS.SetHorizontalHeaders(['名字', '类型', '大小', '日期', '操作']) ModelViewSignals.Signal_TTS_GPTSoVITS.connect(self.ui.Table_Models_TTS_GPTSoVITS.SetValue) self.ui.Table_Models_TTS_GPTSoVITS.Download.connect( - lambda Params: self.Function_SetMethodExecutor( + lambda Params: Function_SetMethodExecutor(self, Method = Model_Downloader.Execute, Params = Params ) @@ -1567,7 +1450,7 @@ def SetPic(): self.ui.Table_Models_TTS_VITS.SetHorizontalHeaders(['名字', '类型', '大小', '日期', '操作']) ModelViewSignals.Signal_TTS_VITS.connect(self.ui.Table_Models_TTS_VITS.SetValue) self.ui.Table_Models_TTS_VITS.Download.connect( - lambda Params: self.Function_SetMethodExecutor( + lambda Params: Function_SetMethodExecutor(self, Method = Model_Downloader.Execute, Params = Params ) @@ -1575,7 +1458,7 @@ def SetPic(): self.ui.Button_Models_Refresh.setText(QCA.translate("ToolButton", '刷新')) self.ui.Button_Models_Refresh.clicked.connect( - lambda: self.Function_SetMethodExecutor( + lambda: Function_SetMethodExecutor(self, Method = Model_View.Execute ) ) @@ -2073,18 +1956,12 @@ def SetText_LineEdit_Process_OutputDir(): # Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_Process, - RootItemTexts = [ - self.ui.GroupBox_Process_InputParams.title(), - self.ui.GroupBox_Process_DenoiserParams.title(), - self.ui.GroupBox_Process_SlicerParams.title(), - self.ui.GroupBox_Process_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置"), - ("基础设置","高级设置"), - ("基础设置","高级设置") - ], + ItemTexts = { + self.ui.GroupBox_Process_InputParams.title(): ("基础设置"), + self.ui.GroupBox_Process_DenoiserParams.title(): ("基础设置"), + self.ui.GroupBox_Process_SlicerParams.title(): ("基础设置","高级设置"), + self.ui.GroupBox_Process_OutputParams.title(): ("基础设置","高级设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -2183,7 +2060,7 @@ def SetText_LineEdit_Process_OutputDir(): # Bottom self.ui.Button_Process_Execute.setToolTip(QCA.translate("ToolTip", "执行音频处理")) self.ui.Button_Process_Terminate.setToolTip(QCA.translate("ToolTip", "终止音频处理")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Process_Execute, TerminateButton = self.ui.Button_Process_Terminate, ProgressBar = self.ui.ProgressBar_Process, @@ -2604,16 +2481,11 @@ def SetText_LineEdit_ASR_VPR_AudioSpeakersDataPath(): # Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_ASR_VPR, - RootItemTexts = [ - self.ui.GroupBox_ASR_VPR_InputParams.title(), - self.ui.GroupBox_ASR_VPR_VPRParams.title(), - self.ui.GroupBox_ASR_VPR_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置","高级设置"), - ("基础设置","高级设置") - ], + ItemTexts = { + self.ui.GroupBox_ASR_VPR_InputParams.title(): ("基础设置"), + self.ui.GroupBox_ASR_VPR_VPRParams.title(): ("基础设置","高级设置"), + self.ui.GroupBox_ASR_VPR_OutputParams.title(): ("基础设置","高级设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -2718,7 +2590,7 @@ def EditASRResult(): # Bottom self.ui.Button_ASR_VPR_Execute.setToolTip("执行语音识别") self.ui.Button_ASR_VPR_Terminate.setToolTip("终止语音识别") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_ASR_VPR_Execute, TerminateButton = self.ui.Button_ASR_VPR_Terminate, ProgressBar = self.ui.ProgressBar_ASR_VPR, @@ -3056,16 +2928,11 @@ def SetText_LineEdit_STT_Whisper_OutputDir(): # Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_STT_Whisper, - RootItemTexts = [ - self.ui.GroupBox_STT_Whisper_InputParams.title(), - self.ui.GroupBox_STT_Whisper_WhisperParams.title(), - self.ui.GroupBox_STT_Whisper_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置","高级设置"), - ("基础设置") - ], + ItemTexts = { + self.ui.GroupBox_STT_Whisper_InputParams.title(): ("基础设置"), + self.ui.GroupBox_STT_Whisper_WhisperParams.title(): ("基础设置","高级设置"), + self.ui.GroupBox_STT_Whisper_OutputParams.title(): ("基础设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -3149,7 +3016,7 @@ def SetText_LineEdit_STT_Whisper_OutputDir(): # Bottom self.ui.Button_STT_Whisper_Execute.setToolTip("执行语音转录") self.ui.Button_STT_Whisper_Terminate.setToolTip("终止语音转录") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_STT_Whisper_Execute, TerminateButton = self.ui.Button_STT_Whisper_Terminate, ProgressBar = self.ui.ProgressBar_STT_Whisper, @@ -3537,16 +3404,11 @@ def SetText_LineEdit_DAT_GPTSoVITS_FileListPath(): # GPT-SoVITS - Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_DAT_GPTSoVITS, - RootItemTexts = [ - self.ui.GroupBox_DAT_GPTSoVITS_InputParams.title(), - self.ui.GroupBox_DAT_GPTSoVITS_GPTSoVITSParams.title(), - self.ui.GroupBox_DAT_GPTSoVITS_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置"), - ("基础设置","高级设置") - ], + ItemTexts = { + self.ui.GroupBox_DAT_GPTSoVITS_InputParams.title(): ("基础设置"), + self.ui.GroupBox_DAT_GPTSoVITS_GPTSoVITSParams.title(): ("基础设置"), + self.ui.GroupBox_DAT_GPTSoVITS_OutputParams.title(): ("基础设置","高级设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -3630,7 +3492,7 @@ def SetText_LineEdit_DAT_GPTSoVITS_FileListPath(): # GPT-SoVITS - Bottom self.ui.Button_DAT_GPTSoVITS_Execute.setToolTip("执行数据集制作") self.ui.Button_DAT_GPTSoVITS_Terminate.setToolTip("终止数据集制作") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_DAT_GPTSoVITS_Execute, TerminateButton = self.ui.Button_DAT_GPTSoVITS_Terminate, ProgressBar = self.ui.ProgressBar_DAT_GPTSoVITS, @@ -4125,16 +3987,11 @@ def SetText_LineEdit_DAT_VITS_FileListPathValidation(): # VITS - Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_DAT_VITS, - RootItemTexts = [ - self.ui.GroupBox_DAT_VITS_InputParams.title(), - self.ui.GroupBox_DAT_VITS_VITSParams.title(), - self.ui.GroupBox_DAT_VITS_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置","高级设置"), - ("基础设置","高级设置") - ], + ItemTexts = { + self.ui.GroupBox_DAT_VITS_InputParams.title(): ("基础设置"), + self.ui.GroupBox_DAT_VITS_VITSParams.title(): ("基础设置","高级设置"), + self.ui.GroupBox_DAT_VITS_OutputParams.title(): ("基础设置","高级设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -4223,7 +4080,7 @@ def SetText_LineEdit_DAT_VITS_FileListPathValidation(): # VITS - Bottom self.ui.Button_DAT_VITS_Execute.setToolTip("执行数据集制作") self.ui.Button_DAT_VITS_Terminate.setToolTip("终止数据集制作") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_DAT_VITS_Execute, TerminateButton = self.ui.Button_DAT_VITS_Terminate, ProgressBar = self.ui.ProgressBar_DAT_VITS, @@ -4624,16 +4481,11 @@ def SetText_LineEdit_Train_GPTSoVITS_OutputDir(): # GPTSo-VITS - Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_Train_GPTSoVITS, - RootItemTexts = [ - self.ui.GroupBox_Train_GPTSoVITS_InputParams.title(), - self.ui.GroupBox_Train_GPTSoVITS_GPTSoVITSParams.title(), - self.ui.GroupBox_Train_GPTSoVITS_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置","高级设置"), - ("基础设置","高级设置") - ], + ItemTexts = { + self.ui.GroupBox_Train_GPTSoVITS_InputParams.title(): ("基础设置"), + self.ui.GroupBox_Train_GPTSoVITS_GPTSoVITSParams.title(): ("基础设置","高级设置"), + self.ui.GroupBox_Train_GPTSoVITS_OutputParams.title(): ("基础设置","高级设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -4712,7 +4564,7 @@ def SetText_LineEdit_Train_GPTSoVITS_OutputDir(): ) self.ui.Button_RunTensorboard_Train_GPTSoVITS.setText(QCA.translate("Button", "启动Tensorboard")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_RunTensorboard_Train_GPTSoVITS, Method = Tensorboard_Runner.Execute, ParamsFrom = [ @@ -4731,7 +4583,7 @@ def SetText_LineEdit_Train_GPTSoVITS_OutputDir(): # GPT-SoVITS - Bottom self.ui.Button_Train_GPTSoVITS_Execute.setToolTip("执行模型训练") self.ui.Button_Train_GPTSoVITS_Terminate.setToolTip("终止模型训练") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Train_GPTSoVITS_Execute, TerminateButton = self.ui.Button_Train_GPTSoVITS_Terminate, ProgressBar = self.ui.ProgressBar_Train_GPTSoVITS, @@ -4761,7 +4613,7 @@ def SetText_LineEdit_Train_GPTSoVITS_OutputDir(): ) ] ) - MainWindowSignals.Signal_TaskStatus.connect( + FunctionSignals.Signal_TaskStatus.connect( lambda Task, Status: Function_ShowMessageBox(self, MessageType = QMessageBox.Question, WindowTitle = "Ask", @@ -5252,16 +5104,11 @@ def SetText_LineEdit_Train_VITS_OutputDir(): # VITS - Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_Train_VITS, - RootItemTexts = [ - self.ui.GroupBox_Train_VITS_InputParams.title(), - self.ui.GroupBox_Train_VITS_VITSParams.title(), - self.ui.GroupBox_Train_VITS_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置","高级设置"), - ("基础设置","高级设置") - ], + ItemTexts = { + self.ui.GroupBox_Train_VITS_InputParams.title(): ("基础设置"), + self.ui.GroupBox_Train_VITS_VITSParams.title(): ("基础设置","高级设置"), + self.ui.GroupBox_Train_VITS_OutputParams.title(): ("基础设置","高级设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -5340,7 +5187,7 @@ def SetText_LineEdit_Train_VITS_OutputDir(): ) self.ui.Button_RunTensorboard_Train_VITS.setText(QCA.translate("Button", "启动Tensorboard")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_RunTensorboard_Train_VITS, Method = Tensorboard_Runner.Execute, ParamsFrom = [ @@ -5359,7 +5206,7 @@ def SetText_LineEdit_Train_VITS_OutputDir(): # VITS - Bottom self.ui.Button_Train_VITS_Execute.setToolTip("执行模型训练") self.ui.Button_Train_VITS_Terminate.setToolTip("终止模型训练") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Train_VITS_Execute, TerminateButton = self.ui.Button_Train_VITS_Terminate, ProgressBar = self.ui.ProgressBar_Train_VITS, @@ -5394,7 +5241,7 @@ def SetText_LineEdit_Train_VITS_OutputDir(): ) ] ) - MainWindowSignals.Signal_TaskStatus.connect( + FunctionSignals.Signal_TaskStatus.connect( lambda Task, Status: Function_ShowMessageBox(self, MessageType = QMessageBox.Question, WindowTitle = "Ask", @@ -5632,14 +5479,10 @@ def SetText_LineEdit_Train_VITS_OutputDir(): # GPT-SoVITS - Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_TTS_GPTSoVITS, - RootItemTexts = [ - self.ui.GroupBox_TTS_GPTSoVITS_InputParams.title(), - self.ui.GroupBox_TTS_GPTSoVITS_GPTSoVITSParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置") - ], + ItemTexts = { + self.ui.GroupBox_TTS_GPTSoVITS_InputParams.title(): ("基础设置"), + self.ui.GroupBox_TTS_GPTSoVITS_GPTSoVITSParams.title(): ("基础设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -5666,7 +5509,7 @@ def SetText_LineEdit_Train_VITS_OutputDir(): # GPT-SoVITS - Bottom self.ui.Button_TTS_GPTSoVITS_Execute.setToolTip("执行语音合成") self.ui.Button_TTS_GPTSoVITS_Terminate.setToolTip("终止语音合成") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_TTS_GPTSoVITS_Execute, TerminateButton = self.ui.Button_TTS_GPTSoVITS_Terminate, ProgressBar = self.ui.ProgressBar_TTS_GPTSoVITS, @@ -6085,16 +5928,11 @@ def SetText_LineEdit_Train_VITS_OutputDir(): # VITS - Left Function_SetTreeWidget( TreeWidget = self.ui.TreeWidget_Catalogue_TTS_VITS, - RootItemTexts = [ - self.ui.GroupBox_TTS_VITS_InputParams.title(), - self.ui.GroupBox_TTS_VITS_VITSParams.title(), - self.ui.GroupBox_TTS_VITS_OutputParams.title() - ], - ChildItemTexts = [ - ("基础设置"), - ("基础设置","高级设置"), - ("基础设置") - ], + ItemTexts = { + self.ui.GroupBox_TTS_VITS_InputParams.title(): ("基础设置"), + self.ui.GroupBox_TTS_VITS_VITSParams.title(): ("基础设置","高级设置"), + self.ui.GroupBox_TTS_VITS_OutputParams.title(): ("基础设置") + }, AddVertically = True ) Function_ScrollToWidget( @@ -6136,7 +5974,7 @@ def SetText_LineEdit_Train_VITS_OutputDir(): # VITS - Bottom self.ui.Button_TTS_VITS_Execute.setToolTip("执行语音合成") self.ui.Button_TTS_VITS_Terminate.setToolTip("终止语音合成") - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_TTS_VITS_Execute, TerminateButton = self.ui.Button_TTS_VITS_Terminate, ProgressBar = self.ui.ProgressBar_TTS_VITS, @@ -6253,12 +6091,12 @@ def SetText_LineEdit_Train_VITS_OutputDir(): self.ui.Button_Setting_ClientRebooter.setText(QCA.translate("Button", "重启客户端")) self.ui.Button_Setting_ClientRebooter.setToolTip(QCA.translate("ToolTip", "重启EVT客户端")) - self.Function_SetMethodExecutor( + Function_SetMethodExecutor(self, ExecuteButton = self.ui.Button_Setting_IntegrityChecker, Method = Integrity_Checker.Execute, Params = () ) - MainWindowSignals.Signal_TaskStatus.connect( + FunctionSignals.Signal_TaskStatus.connect( lambda Task, Status: self.ui.Button_Setting_IntegrityChecker.setCheckable( False if Status == 'Started' else True ) @@ -6590,7 +6428,7 @@ def SetText_LineEdit_Train_VITS_OutputDir(): # Display ToolsStatus self.ui.Label_ToolsStatus.clear() - MainWindowSignals.Signal_TaskStatus.connect( + FunctionSignals.Signal_TaskStatus.connect( lambda Task, Status: self.ui.Label_ToolsStatus.setText( f"工具状态:{'忙碌' if Status == 'Started' else '空闲'}" ) if Task in [ diff --git a/Updater.py b/Updater.py index 5ea2813..ec60bdd 100644 --- a/Updater.py +++ b/Updater.py @@ -8,7 +8,7 @@ from PySide6.QtWidgets import QApplication, QVBoxLayout, QSizePolicy, QWidget, QMessageBox, QPushButton, QProgressBar, QLabel from QEasyWidgets.Utils import CheckUpdate, DownloadFile, NormPath, SetRichText, RunBat, BootWithBat, GetFileInfo, GetBaseDir, ManageConfig -from EVT_GUI.Functions import Function_AnimateProgressBar, Function_SetText, Function_ShowMessageBox +from EVT_GUI.Functions import Function_SetMethodExecutor, Function_SetText, Function_ShowMessageBox ############################################################################################################################## @@ -233,37 +233,6 @@ def __init__(self): self.Layout.addWidget(self.ProgressBar) self.Layout.addWidget(self.SkipButton) - def Function_ExecuteMethod(self, - ProgressBar: Optional[QProgressBar] = None, - Method: object = ..., - Params: Optional[tuple] = () - ): - ClassName = str(Method.__qualname__).split('.')[0] - MethodName = str(Method.__qualname__).split('.')[1] - - ClassInstance = globals()[ClassName]() - - WorkerThread = QThread() - ClassInstance.moveToThread(WorkerThread) - ClassInstance.finished.connect(WorkerThread.quit) - - def ExecuteMethod(): - Args = Params - - QFunctionsSignals = CustomSignals_Updater() - QFunctionsSignals.Signal_ExecuteTask.connect(getattr(ClassInstance, MethodName)) - - WorkerThread.started.connect(lambda: Function_AnimateProgressBar(ProgressBar, IsTaskAlive = True)) if ProgressBar else None - WorkerThread.finished.connect(lambda: Function_AnimateProgressBar(ProgressBar, IsTaskAlive = False)) if ProgressBar else None - - QFunctionsSignals.Signal_ExecuteTask.emit(Args) - WorkerThread.start() - - TempButton = QPushButton(self) - TempButton.hide() - TempButton.clicked.connect(ExecuteMethod) - TempButton.click() - def Main(self): self.DownloadURL = str() def UpdateDownloadURL(DownloadURL): @@ -284,7 +253,7 @@ def UpdateDownloadURL(DownloadURL): Text = '检测到可用的新版本,是否更新?\nNew version available, wanna update?', Buttons = QMessageBox.Yes|QMessageBox.No, ButtonEvents = { - QMessageBox.Yes: lambda: self.Function_ExecuteMethod( + QMessageBox.Yes: lambda: Function_SetMethodExecutor(self, ProgressBar = self.ProgressBar, Method = Execute_Update_Downloading.Execute, Params = (self.DownloadURL) @@ -308,7 +277,7 @@ def UpdateDownloadURL(DownloadURL): ) ) - self.Function_ExecuteMethod( + Function_SetMethodExecutor(self, ProgressBar = self.ProgressBar, Method = Execute_Update_Checking.Execute, Params = () diff --git a/docs/README_CN.md b/docs/README_CN.md new file mode 100644 index 0000000..f9c34be --- /dev/null +++ b/docs/README_CN.md @@ -0,0 +1,238 @@ +
+ +# 简易语音工具箱 + +![Title](/docs/media/Title.png "Home Page") + +[![Releases](https://img.shields.io/github/v/release/Spr-Aachen/Easy-Voice-Toolkit?color=green&label=Release&logo=Github&logoColor=white&style=for-the-badge)](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/releases/latest)  +[![Bilibili](https://img.shields.io/badge/Bilibili-v1.0%20Intro-blue?logo=Bilibili&style=for-the-badge)](https://www.bilibili.com/video/BV1uJ4m157P2)  +[![YouTube](https://img.shields.io/badge/YouTube-v1.0%20Intro-red?logo=YouTube&style=for-the-badge)](https://www.youtube.com/watch?v=) + +
+ +

+ + + +

+ + +
+ +**简体中文** | [**English**](../README.md) + +
+ + +## 项目介绍 + +### 概述 + +一个基于开源语音项目实现的简易语音工具箱,提供了包括语音模型训练在内的多种自动化音频工具 + +
工具箱目前包含以下功能: + +- [音频处理](/docs/Audio-Processor.md) + +- [语音识别](/docs/Voice-Recognizer.md) + +- [语音转录](/docs/Voice-Transcriber.md) + +- [数据集制作](/docs/Dataset-Creator.md) + +- [模型训练](/docs/Voice-Trainer.md) + +- [语音合成](/docs/Voice-Converter.md) + +
这些功能依次关联,能够形成一套完整的工作流 +
用户可以根据自己的需求有选择性地使用,亦或者依次通过这些工具将未经处理的语音文件逐步变为理想的语音模型 + +### 鸣谢 + +由衷感谢以下项目的作者,这个工具箱的实现正是得益于他们的优秀成果 + +- [audio-slicer](https://github.com/openvpi/audio-slicer) +- [VoiceprintRecognition](https://github.com/yeyupiaoling/VoiceprintRecognition-Pytorch/tree/release/1.0) +- [whisper](https://github.com/openai/whisper) +- [SRT-to-CSV-and-audio-split](https://github.com/tobiasrordorf/SRT-to-CSV-and-audio-split) +- [vits](https://github.com/CjangCjengh/vits) +- [GPT-SoVITS](https://github.com/RVC-Boss/GPT-SoVITS) + + +## 注意事项 + +### 系统 + +目前UI界面仅支持Windows系统 + +### 语言 + +目前各个工具对语言的支持情况如下: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
工具中文英文日文
音频处理
语音识别
语音转录
数据集制作
模型训练
语音合成
+ + +## 项目部署 + +### 本地部署 - 用户 + +#### 下载 + +您有两种选择: + +- 下载[轻量化的安装程序](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/releases/latest):包体小且拥有安装引导,但是未配置环境依赖且不带模型 + +- 下载[解压即用的懒人包](https://pixeldrain.com/api/file/JLUJwfNA?download):配置了所有环境依赖并附带有预设模型,但是包体较大且需要解压 + +#### 运行 + +点击.exe文件或其快捷方式即可 + +### 本地部署 - 开发者 + +#### 搭建环境 + +- 请确保您已安装了`版本≥3.8`的[Python](https://www.python.org/downloads/) + +#### 获取项目 + +- 克隆项目仓库 + ```shell + git clone https://github.com/Spr-Aachen/Easy-Voice-Toolkit.git + ``` + +- 切至项目目录 + ```shell + %cd Easy-Voice-Toolkit + ``` + +#### 安装依赖 + +- 安装pytorch(需从[官网](https://pytorch.org/get-started/locally/)复制命令) + ```shell + # e.g. (注意自己的cuda版本,这里以11.8为例) + pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu118 + ``` + +- 安装项目依赖 + ```shell + pip install -r requirements.txt + ``` + +- 安装GUI依赖 + ```shell + pip install pyside6 QEasyWidgets pywin32==300 psutil pynvml darkdetect PyGithub + ``` + +#### 运行程序 + +- 启动图形界面 + ```shell + Run.py + ``` + +### 云端部署 + +#### Google Colab + +[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Spr-Aachen/EVT-Resources/blob/main/Easy_Voice_Toolkit_for_Colab.ipynb) +
点击以使用上面的demo,或者在Colab中上传[Run.ipynb](https://github.com/Spr-Aachen/Easy-Voice-Toolkit/blob/main/Run.ipynb) + + +## 测试平台 + +### Windows 系统 + +#### Honor Hunter V700 +- **Type**: Laptop +- **GPU**: GTX 1660Ti +- **CPU**: i5-10300H +- **RAM**: 16G +- **OS**: Win10 +- **Python**: 3.9 +- **Torch**: 2.0.1 + +#### (待添加) + +### Linux 系统 + +#### (待添加) + + +## 疑问解答 + +- **Q**: 更新客户端/下载依赖/模型时总是提示失败/报错该怎么办? +
**A**: 开代理或者直接用懒人包 + +- **Q**: 好多参数都不清楚要如何设置该怎么办? +
**A**: 不明白的话使用默认值就好 + +- **Q**: 你这永久免费开源...它保真吗? +
**A**: 嗯哼~♪ + + +## 使用条例 + +**请自行解决数据集的授权问题。对于使用未经授权的数据集进行训练所导致的任何问题,您将承担全部责任,并且该仓库及其维护者不承担任何后果!相关法律请参照《中华人民共和国治安管理处罚法》和《中华人民共和国民法典》** + +0. 本项目仅用于学术交流目的,旨在促进沟通和学习。不适用于生产环境。 +1. 基于 Easy Voice Toolkit 发布的任何视频必须在描述中明确指出它们用于变声,并指定声音或音频的输入源,例如使用他人发布的视频或音频,并将分离出的人声作为转换的输入源,必须提供清晰的原始视频链接。如果您使用自己的声音或其他商业语音合成软件生成的声音作为转换的输入源,也必须在描述中说明。 +2. 您将对输入源引起的任何侵权问题负全部责任。当使用其他商业语音合成软件作为输入源时,请确保遵守该软件的使用条款。请注意,许多语音合成引擎在其使用条款中明确声明不能用于输入源转换。 +3. 继续使用本项目被视为同意本仓库 README 中所述的相关条款。本仓库的 README 有义务进行劝导,但不承担可能出现的任何后续问题的责任。 +4. 如果您分发此仓库的代码或将由此项目生成的任何结果公开发布(包括但不限于视频分享平台),请注明原始作者和代码来源(即此仓库)。 +5. 如果您将此项目用于任何其他计划,请提前与本仓库的作者联系并告知 + +Reference: [so-vits-svc](https://github.com/svc-develop-team/so-vits-svc) + + +## 联系方式 + +[![QQ](https://img.shields.io/badge/QQ-2835946988-brightgreen?style=for-the-badge&logo=tencent-qq&logoColor=white)]() +
倘若大伙儿有什么好的建议欢迎随时叨扰哦~ + + +## 收藏趋势 + +[![Stargazers over time](https://starchart.cc/Spr-Aachen/Easy-Voice-Toolkit.svg)](https://starchart.cc/Spr-Aachen/Easy-Voice-Toolkit) \ No newline at end of file