Spaces:
Build error
Build error
| import os | |
| import json | |
| from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QScrollArea, | |
| QPushButton, QMessageBox, QSplitter) | |
| from PySide6.QtCore import Qt, Signal | |
| from ui_components import (CustomSlider, FloatSlider, RadioButtonGroup, | |
| AudioSelector, VideoPlayer) | |
| class SettingsTab(QWidget): | |
| """ | |
| 配置页面,允许用户设置所有处理参数并保存到config.json | |
| """ | |
| # 定义配置变更信号 | |
| config_changed = Signal(dict) | |
| def __init__(self, parent=None): | |
| super().__init__(parent) | |
| self.init_ui() | |
| self.load_config() | |
| def init_ui(self): | |
| """初始化配置页面UI""" | |
| self.layout = QVBoxLayout(self) | |
| # 创建一个滚动区域用于容纳配置项 | |
| self.scroll_area = QScrollArea() | |
| self.scroll_area.setWidgetResizable(True) | |
| self.scroll_widget = QWidget() | |
| self.scroll_layout = QVBoxLayout(self.scroll_widget) | |
| # 添加所有配置控件 | |
| self.add_config_widgets() | |
| # 创建保存配置按钮 | |
| self.button_layout = QHBoxLayout() | |
| self.save_config_button = QPushButton("保存配置") | |
| self.save_config_button.clicked.connect(self.save_config) | |
| self.save_config_button.setMinimumHeight(40) | |
| self.save_config_button.setStyleSheet("background-color: #4CAF50; color: white;") | |
| self.reset_config_button = QPushButton("重置配置") | |
| self.reset_config_button.clicked.connect(self.reset_config) | |
| self.reset_config_button.setMinimumHeight(40) | |
| self.button_layout.addWidget(self.reset_config_button) | |
| self.button_layout.addWidget(self.save_config_button) | |
| # 设置滚动区域 | |
| self.scroll_area.setWidget(self.scroll_widget) | |
| self.layout.addWidget(self.scroll_area) | |
| self.layout.addLayout(self.button_layout) | |
| self.setLayout(self.layout) | |
| def add_config_widgets(self): | |
| """添加所有配置控件""" | |
| # 视频配置 | |
| self.scroll_layout.addWidget(QLabel("=== 视频下载配置 ===")) | |
| self.scroll_layout.addWidget(QLabel("视频输出文件夹")) | |
| self.video_folder = self.add_label_value("videos", "视频输出到此文件夹") | |
| # 分辨率 | |
| self.resolution = RadioButtonGroup( | |
| ['4320p', '2160p', '1440p', '1080p', '720p', '480p', '360p', '240p', '144p'], | |
| "分辨率", | |
| '1080p' | |
| ) | |
| self.scroll_layout.addWidget(self.resolution) | |
| # 下载视频数量 | |
| self.video_count = CustomSlider(1, 100, 1, "下载视频数量", 5) | |
| self.scroll_layout.addWidget(self.video_count) | |
| # 音频处理配置 | |
| self.scroll_layout.addWidget(QLabel("=== 音频处理配置 ===")) | |
| # 模型 | |
| self.model = RadioButtonGroup( | |
| ['htdemucs', 'htdemucs_ft', 'htdemucs_6s', 'hdemucs_mmi', 'mdx', 'mdx_extra', 'mdx_q', 'mdx_extra_q', | |
| 'SIG'], | |
| "人声分离模型", | |
| 'htdemucs_ft' | |
| ) | |
| self.scroll_layout.addWidget(self.model) | |
| # 计算设备 | |
| self.device = RadioButtonGroup(['auto', 'cuda', 'cpu'], "计算设备", 'auto') | |
| self.scroll_layout.addWidget(self.device) | |
| # 移位次数 | |
| self.shifts = CustomSlider(0, 10, 1, "移位次数 Number of shifts", 5) | |
| self.scroll_layout.addWidget(self.shifts) | |
| # ASR配置 | |
| self.scroll_layout.addWidget(QLabel("=== 语音识别配置 ===")) | |
| # ASR模型选择 | |
| self.asr_model_label = QLabel("ASR模型选择") | |
| self.scroll_layout.addWidget(self.asr_model_label) | |
| self.asr_model = RadioButtonGroup(['WhisperX', 'FunASR'], "ASR模型选择", 'WhisperX') | |
| self.scroll_layout.addWidget(self.asr_model) | |
| # WhisperX模型大小 | |
| self.whisperx_size = RadioButtonGroup(['large', 'medium', 'small', 'base', 'tiny'], "WhisperX模型大小", 'large') | |
| self.scroll_layout.addWidget(self.whisperx_size) | |
| # 批处理大小 | |
| self.batch_size = CustomSlider(1, 128, 1, "批处理大小 Batch Size", 32) | |
| self.scroll_layout.addWidget(self.batch_size) | |
| # 分离多个说话人 | |
| self.separate_speakers = RadioButtonGroup([True, False], "分离多个说话人", True) | |
| self.scroll_layout.addWidget(self.separate_speakers) | |
| # 最小说话人数 | |
| self.min_speakers = RadioButtonGroup([None, 1, 2, 3, 4, 5, 6, 7, 8, 9], "最小说话人数", None) | |
| self.scroll_layout.addWidget(self.min_speakers) | |
| # 最大说话人数 | |
| self.max_speakers = RadioButtonGroup([None, 1, 2, 3, 4, 5, 6, 7, 8, 9], "最大说话人数", None) | |
| self.scroll_layout.addWidget(self.max_speakers) | |
| # 翻译配置 | |
| self.scroll_layout.addWidget(QLabel("=== 翻译配置 ===")) | |
| # 翻译方式 | |
| self.translation_method_label = QLabel("翻译方式") | |
| self.scroll_layout.addWidget(self.translation_method_label) | |
| self.translation_method = RadioButtonGroup( | |
| ['OpenAI', 'LLM', 'Google Translate', 'Bing Translate', 'Ernie', '火山引擎-deepseek', "deepseek-api", | |
| "阿里云-通义千问","Ollama"], "翻译方式", 'LLM') | |
| self.scroll_layout.addWidget(self.translation_method) | |
| # 目标语言 (翻译) | |
| self.target_language_translation_label = QLabel("目标语言 (翻译)") | |
| self.scroll_layout.addWidget(self.target_language_translation_label) | |
| self.target_language_translation = RadioButtonGroup( | |
| ['简体中文', '繁体中文', 'English', 'Cantonese', 'Japanese', 'Korean'], "目标语言 (翻译)", '简体中文') | |
| self.scroll_layout.addWidget(self.target_language_translation) | |
| # TTS配置 | |
| self.scroll_layout.addWidget(QLabel("=== 语音合成配置 ===")) | |
| # AI语音生成方法 | |
| self.tts_method_label = QLabel("AI语音生成方法") | |
| self.scroll_layout.addWidget(self.tts_method_label) | |
| self.tts_method = RadioButtonGroup(['xtts', 'cosyvoice', 'EdgeTTS'], "AI语音生成方法", 'EdgeTTS') | |
| self.scroll_layout.addWidget(self.tts_method) | |
| # 目标语言 (TTS) | |
| self.target_language_tts_label = QLabel("目标语言 (TTS)") | |
| self.scroll_layout.addWidget(self.target_language_tts_label) | |
| self.target_language_tts = RadioButtonGroup( | |
| ['中文', 'English', '粤语', 'Japanese', 'Korean', 'Spanish', 'French'], "目标语言 (TTS)", '中文') | |
| self.scroll_layout.addWidget(self.target_language_tts) | |
| # EdgeTTS声音选择 | |
| self.edge_tts_voice_label = QLabel("EdgeTTS声音选择") | |
| self.scroll_layout.addWidget(self.edge_tts_voice_label) | |
| self.edge_tts_voice = RadioButtonGroup( | |
| ['zh-CN-XiaoxiaoNeural', 'zh-CN-YunxiNeural', 'en-US-JennyNeural', 'ja-JP-NanamiNeural'], | |
| "EdgeTTS声音选择", 'zh-CN-XiaoxiaoNeural') | |
| self.scroll_layout.addWidget(self.edge_tts_voice) | |
| # 视频合成配置 | |
| self.scroll_layout.addWidget(QLabel("=== 视频合成配置 ===")) | |
| # 添加字幕 | |
| self.add_subtitles = RadioButtonGroup([True, False], "添加字幕", True) | |
| self.scroll_layout.addWidget(self.add_subtitles) | |
| # 加速倍数 | |
| self.speed_factor = FloatSlider(0.5, 2, 0.05, "加速倍数", 1.00) | |
| self.scroll_layout.addWidget(self.speed_factor) | |
| # 帧率 | |
| self.frame_rate = CustomSlider(1, 60, 1, "帧率", 30) | |
| self.scroll_layout.addWidget(self.frame_rate) | |
| # 背景音乐 | |
| self.background_music = AudioSelector("背景音乐") | |
| self.scroll_layout.addWidget(self.background_music) | |
| # 背景音乐音量 | |
| self.bg_music_volume = FloatSlider(0, 1, 0.05, "背景音乐音量", 0.5) | |
| self.scroll_layout.addWidget(self.bg_music_volume) | |
| # 视频音量 | |
| self.video_volume = FloatSlider(0, 1, 0.05, "视频音量", 1.0) | |
| self.scroll_layout.addWidget(self.video_volume) | |
| # 分辨率 (输出) | |
| self.output_resolution = RadioButtonGroup( | |
| ['4320p', '2160p', '1440p', '1080p', '720p', '480p', '360p', '240p', '144p'], | |
| "输出分辨率", | |
| '1080p' | |
| ) | |
| self.scroll_layout.addWidget(self.output_resolution) | |
| # 高级配置 | |
| self.scroll_layout.addWidget(QLabel("=== 高级配置 ===")) | |
| # Max Workers | |
| self.max_workers = CustomSlider(1, 100, 1, "Max Workers", 1) | |
| self.scroll_layout.addWidget(self.max_workers) | |
| # Max Retries | |
| self.max_retries = CustomSlider(1, 10, 1, "Max Retries", 3) | |
| self.scroll_layout.addWidget(self.max_retries) | |
| def add_label_value(self, value, tooltip=None): | |
| """为简单的文本值创建一个标签""" | |
| label = QLabel(value) | |
| if tooltip: | |
| label.setToolTip(tooltip) | |
| self.scroll_layout.addWidget(label) | |
| return label | |
| def get_config(self): | |
| """从UI控件中获取当前配置""" | |
| config = { | |
| "video_folder": self.video_folder.text(), | |
| "resolution": self.resolution.value(), | |
| "video_count": self.video_count.value(), | |
| "model": self.model.value(), | |
| "device": self.device.value(), | |
| "shifts": self.shifts.value(), | |
| "asr_model": self.asr_model.value(), | |
| "whisperx_size": self.whisperx_size.value(), | |
| "batch_size": self.batch_size.value(), | |
| "separate_speakers": self.separate_speakers.value(), | |
| "min_speakers": self.min_speakers.value(), | |
| "max_speakers": self.max_speakers.value(), | |
| "translation_method": self.translation_method.value(), | |
| "target_language_translation": self.target_language_translation.value(), | |
| "tts_method": self.tts_method.value(), | |
| "target_language_tts": self.target_language_tts.value(), | |
| "edge_tts_voice": self.edge_tts_voice.value(), | |
| "add_subtitles": self.add_subtitles.value(), | |
| "speed_factor": self.speed_factor.value(), | |
| "frame_rate": self.frame_rate.value(), | |
| "background_music": self.background_music.value(), | |
| "bg_music_volume": self.bg_music_volume.value(), | |
| "video_volume": self.video_volume.value(), | |
| "output_resolution": self.output_resolution.value(), | |
| "max_workers": self.max_workers.value(), | |
| "max_retries": self.max_retries.value() | |
| } | |
| return config | |
| def apply_config(self, config): | |
| """将配置应用到UI控件""" | |
| try: | |
| # 基本设置 | |
| self.video_folder.setText(config.get("video_folder", "videos")) | |
| # 为每个单选按钮组应用更健壮的选择逻辑 | |
| # 分辨率 | |
| resolution_value = config.get("resolution", "1080p") | |
| self._set_radio_button(self.resolution.buttons, resolution_value, "1080p") | |
| # 视频数量 | |
| self.video_count.setValue(config.get("video_count", 5)) | |
| # 模型 | |
| model_value = config.get("model", "htdemucs_ft") | |
| self._set_radio_button(self.model.buttons, model_value, "htdemucs_ft") | |
| # 设备 | |
| device_value = config.get("device", "auto") | |
| self._set_radio_button(self.device.buttons, device_value, "auto") | |
| # 移位次数 | |
| self.shifts.setValue(config.get("shifts", 5)) | |
| # ASR模型 | |
| asr_model_value = config.get("asr_model", "WhisperX") | |
| self._set_radio_button(self.asr_model.buttons, asr_model_value, "WhisperX") | |
| # WhisperX模型大小 | |
| whisperx_size_value = config.get("whisperx_size", "large") | |
| self._set_radio_button(self.whisperx_size.buttons, whisperx_size_value, "large") | |
| # 批处理大小 | |
| self.batch_size.setValue(config.get("batch_size", 32)) | |
| # 分离多个说话人 | |
| separate_speakers_value = config.get("separate_speakers", True) | |
| self._set_radio_button(self.separate_speakers.buttons, separate_speakers_value, True) | |
| # 最小说话人数 | |
| min_speakers_value = config.get("min_speakers", None) | |
| self._set_radio_button(self.min_speakers.buttons, min_speakers_value, None) | |
| # 最大说话人数 | |
| max_speakers_value = config.get("max_speakers", None) | |
| self._set_radio_button(self.max_speakers.buttons, max_speakers_value, None) | |
| # 翻译方式 | |
| translation_method_value = config.get("translation_method", "LLM") | |
| self._set_radio_button(self.translation_method.buttons, translation_method_value, "LLM") | |
| # 目标语言 (翻译) | |
| target_lang_trans_value = config.get("target_language_translation", "简体中文") | |
| self._set_radio_button(self.target_language_translation.buttons, target_lang_trans_value, "简体中文") | |
| # TTS方法 | |
| tts_method_value = config.get("tts_method", "EdgeTTS") | |
| self._set_radio_button(self.tts_method.buttons, tts_method_value, "EdgeTTS") | |
| # 目标语言 (TTS) | |
| target_lang_tts_value = config.get("target_language_tts", "中文") | |
| self._set_radio_button(self.target_language_tts.buttons, target_lang_tts_value, "中文") | |
| # EdgeTTS声音选择 | |
| edge_tts_voice_value = config.get("edge_tts_voice", "zh-CN-XiaoxiaoNeural") | |
| self._set_radio_button(self.edge_tts_voice.buttons, edge_tts_voice_value, "zh-CN-XiaoxiaoNeural") | |
| # 添加字幕 | |
| add_subtitles_value = config.get("add_subtitles", True) | |
| self._set_radio_button(self.add_subtitles.buttons, add_subtitles_value, True) | |
| # 加速倍数 | |
| self.speed_factor.setValue(config.get("speed_factor", 1.00)) | |
| # 帧率 | |
| self.frame_rate.setValue(config.get("frame_rate", 30)) | |
| # 背景音乐 | |
| if config.get("background_music"): | |
| self.background_music.file_path.setText(config.get("background_music")) | |
| # 背景音乐音量 | |
| self.bg_music_volume.setValue(config.get("bg_music_volume", 0.5)) | |
| # 视频音量 | |
| self.video_volume.setValue(config.get("video_volume", 1.0)) | |
| # 输出分辨率 | |
| output_resolution_value = config.get("output_resolution", "1080p") | |
| self._set_radio_button(self.output_resolution.buttons, output_resolution_value, "1080p") | |
| # 最大工作线程数 | |
| self.max_workers.setValue(config.get("max_workers", 1)) | |
| # 最大重试次数 | |
| self.max_retries.setValue(config.get("max_retries", 3)) | |
| except Exception as e: | |
| QMessageBox.warning(self, "配置加载错误", f"加载配置时出错: {str(e)}") | |
| def _set_radio_button(self, buttons, value, default_value): | |
| """辅助方法:安全地设置单选按钮值""" | |
| try: | |
| # 尝试找到匹配的选项并选中对应的按钮 | |
| for option, button in buttons: | |
| if option == value: | |
| button.setChecked(True) | |
| return | |
| # 如果没找到,使用默认值 | |
| for option, button in buttons: | |
| if option == default_value: | |
| button.setChecked(True) | |
| return | |
| except Exception: | |
| # 如果出现任何错误,尝试使用默认值 | |
| for option, button in buttons: | |
| if option == default_value: | |
| button.setChecked(True) | |
| return | |
| def save_config(self): | |
| """保存配置到JSON文件""" | |
| try: | |
| config = self.get_config() | |
| config_dir = os.path.dirname(os.path.abspath(__file__)) | |
| config_path = os.path.join(config_dir, "config.json") | |
| with open(config_path, 'w', encoding='utf-8') as f: | |
| json.dump(config, f, ensure_ascii=False, indent=4) | |
| QMessageBox.information(self, "保存成功", f"配置已保存到 {config_path}") | |
| # 发送配置变更信号 | |
| self.config_changed.emit(config) | |
| except Exception as e: | |
| QMessageBox.critical(self, "保存失败", f"保存配置时出错: {str(e)}") | |
| def load_config(self): | |
| """从JSON文件加载配置""" | |
| try: | |
| config_dir = os.path.dirname(os.path.abspath(__file__)) | |
| config_path = os.path.join(config_dir, "config.json") | |
| if os.path.exists(config_path): | |
| with open(config_path, 'r', encoding='utf-8') as f: | |
| config = json.load(f) | |
| self.apply_config(config) | |
| except Exception as e: | |
| QMessageBox.warning(self, "加载配置失败", f"加载配置时出错: {str(e)}") | |
| def reset_config(self): | |
| """重置配置为默认值""" | |
| if QMessageBox.question(self, "确认重置", "确定要重置所有配置到默认值吗?") == QMessageBox.Yes: | |
| # 应用默认配置 | |
| default_config = { | |
| "video_folder": "videos", | |
| "resolution": "1080p", | |
| "video_count": 5, | |
| "model": "htdemucs_ft", | |
| "device": "auto", | |
| "shifts": 5, | |
| "asr_model": "WhisperX", | |
| "whisperx_size": "large", | |
| "batch_size": 32, | |
| "separate_speakers": True, | |
| "min_speakers": None, | |
| "max_speakers": None, | |
| "translation_method": "LLM", | |
| "target_language_translation": "简体中文", | |
| "tts_method": "EdgeTTS", | |
| "target_language_tts": "中文", | |
| "edge_tts_voice": "zh-CN-XiaoxiaoNeural", | |
| "add_subtitles": True, | |
| "speed_factor": 1.00, | |
| "frame_rate": 30, | |
| "background_music": None, | |
| "bg_music_volume": 0.5, | |
| "video_volume": 1.0, | |
| "output_resolution": "1080p", | |
| "max_workers": 1, | |
| "max_retries": 3 | |
| } | |
| self.apply_config(default_config) | |
| QMessageBox.information(self, "重置成功", "所有配置已重置为默认值") |