mirror of
https://github.com/YaoFANGUK/video-subtitle-remover.git
synced 2026-05-05 16:57:31 +08:00
支持设置视频保存路径
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from qfluentwidgets import (qconfig, ConfigItem, QConfig, OptionsValidator, BoolValidator, OptionsConfigItem,
|
||||
EnumSerializer, RangeValidator, RangeConfigItem)
|
||||
EnumSerializer, RangeValidator, RangeConfigItem, ConfigValidator)
|
||||
from backend.tools.constant import InpaintMode, SubtitleDetectMode
|
||||
import configparser
|
||||
|
||||
@@ -105,6 +105,9 @@ class Config(QConfig):
|
||||
# 启动时检查应用更新
|
||||
checkUpdateOnStartup = ConfigItem("Main", "CheckUpdateOnStartup", True, BoolValidator())
|
||||
|
||||
# 视频保存目录
|
||||
saveDirectory = ConfigItem("Main", "SaveDirectory", "", ConfigValidator())
|
||||
|
||||
CONFIG_FILE = 'config/config.json'
|
||||
config = Config()
|
||||
qconfig.load(CONFIG_FILE, config)
|
||||
|
||||
@@ -43,6 +43,9 @@ UpdatesAvailableTitle = 有可用更新
|
||||
UpdatesAvailableDesc = 发现新版本 {}, 是否更新?
|
||||
NoUpdatesAvailableTitle = 无可用更新
|
||||
NoUpdatesAvailableDesc = 软件已是最新版本
|
||||
ChooseDirectory = 选择文件夹
|
||||
SaveDirectory = 视频保存目录
|
||||
SaveDirectoryDefault = 默认保存到输入视频当前目录
|
||||
|
||||
[SubtitleExtractorGUI]
|
||||
Title = 字幕去除器
|
||||
|
||||
@@ -43,6 +43,9 @@ UpdatesAvailableTitle = 有可用更新
|
||||
UpdatesAvailableDesc = 發現新版本 {},是否更新?
|
||||
NoUpdatesAvailableTitle = 無可用更新
|
||||
NoUpdatesAvailableDesc = 軟體已是最新版本
|
||||
ChooseDirectory = 選擇資料夾
|
||||
SaveDirectory = 影片保存目錄
|
||||
SaveDirectoryDefault = 預設保存到輸入影片的當前目錄
|
||||
|
||||
[SubtitleExtractorGUI]
|
||||
Title = 字幕去除器
|
||||
|
||||
@@ -42,7 +42,10 @@ CheckUpdateOnStartupDesc = New versions offer improved stability and features (r
|
||||
UpdatesAvailableTitle = Update Available
|
||||
UpdatesAvailableDesc = New version {} found. Update now?
|
||||
NoUpdatesAvailableTitle = No Updates Available
|
||||
NoUpdatesAvailableDesc = Software is up-to-date.
|
||||
NoUpdatesAvailableDesc = Software is up-to-date.
|
||||
ChooseDirectory = Choose Folder
|
||||
SaveDirectory = Video save directory
|
||||
SaveDirectoryDefault = Default save to the current directory of the input video
|
||||
|
||||
[SubtitleExtractorGUI]
|
||||
Title = Subtitle Remover
|
||||
|
||||
@@ -43,6 +43,9 @@ UpdatesAvailableTitle = Actualización disponible
|
||||
UpdatesAvailableDesc = Nueva versión {} disponible. ¿Actualizar ahora?
|
||||
NoUpdatesAvailableTitle = Sin actualizaciones
|
||||
NoUpdatesAvailableDesc = El software está actualizado.
|
||||
ChooseDirectory = Seleccionar Carpeta
|
||||
SaveDirectory = Directorio de guardado de video
|
||||
SaveDirectoryDefault = Guardar por defecto en el directorio actual del video de entrada
|
||||
|
||||
[SubtitleExtractorGUI]
|
||||
Title = Eliminador de subtítulos
|
||||
|
||||
@@ -43,6 +43,9 @@ UpdatesAvailableTitle = 利用可能なアップデート
|
||||
UpdatesAvailableDesc = 新バージョン {} を発見。更新しますか?
|
||||
NoUpdatesAvailableTitle = 利用可能なアップデートなし
|
||||
NoUpdatesAvailableDesc = 最新バージョンです
|
||||
ChooseDirectory = フォルダを選択
|
||||
SaveDirectory = 動画保存ディレクトリ
|
||||
SaveDirectoryDefault = 入力動画の現在ディレクトリにデフォルトで保存
|
||||
|
||||
[SubtitleExtractorGUI]
|
||||
Title = 字幕除去ツール
|
||||
|
||||
@@ -43,6 +43,9 @@ UpdatesAvailableTitle = 업데이트 가능
|
||||
UpdatesAvailableDesc = 새 버전 {} 발견. 업데이트할까요?
|
||||
NoUpdatesAvailableTitle = 사용 가능한 업데이트 없음
|
||||
NoUpdatesAvailableDesc = 최신 버전입니다.
|
||||
ChooseDirectory = 폴더 선택
|
||||
SaveDirectory = 동영상 저장 디렉터리
|
||||
SaveDirectoryDefault = 입력 동영상의 현재 디렉터리에 기본 저장
|
||||
|
||||
[SubtitleExtractorGUI]
|
||||
Title = 자막 제거 도구
|
||||
|
||||
@@ -43,6 +43,9 @@ UpdatesAvailableTitle = Có bản cập nhật
|
||||
UpdatesAvailableDesc = Phát hiện phiên bản mới {}, cập nhật?
|
||||
NoUpdatesAvailableTitle = Không có cập nhật
|
||||
NoUpdatesAvailableDesc = Đang dùng phiên bản mới nhất
|
||||
ChooseDirectory = Chọn Thư Mục
|
||||
SaveDirectory = Thư mục lưu video
|
||||
SaveDirectoryDefault = Mặc định lưu vào thư mục hiện tại của video đầu vào
|
||||
|
||||
[SubtitleExtractorGUI]
|
||||
Title = Công cụ xóa phụ đề
|
||||
|
||||
@@ -337,6 +337,7 @@ class SubtitleRemover:
|
||||
self.append_output(tr['Main']['SubtitleDetectionAcceleratorON'].format(accelerator_name))
|
||||
if accelerator_name == 'DirectML' and config.inpaintMode.value not in [InpaintMode.STTN_AUTO, InpaintMode.STTN_DET]:
|
||||
self.append_output(tr['Main']['DirectMLWarning'])
|
||||
os.makedirs(os.path.dirname(self.video_out_path), exist_ok=True)
|
||||
# 重置进度条
|
||||
self.progress_total = 0
|
||||
tbar = tqdm(total=int(self.frame_count), unit='frame', position=0, file=sys.__stdout__,
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
"""
|
||||
|
||||
from PySide6 import QtWidgets, QtCore, QtGui
|
||||
from PySide6.QtWidgets import QFileDialog
|
||||
from qfluentwidgets import (ScrollArea, ExpandLayout, CardWidget, SubtitleLabel,
|
||||
FluentIcon, NavigationWidget, NavigationItemPosition,
|
||||
SettingCardGroup, RangeSettingCard, SwitchSettingCard,
|
||||
HyperlinkCard, PrimaryPushSettingCard, ComboBoxSettingCard,
|
||||
HyperlinkCard, PrimaryPushSettingCard, PushSettingCard,
|
||||
MessageBox)
|
||||
from backend.config import config, tr, VERSION, PROJECT_HOME_URL, PROJECT_ISSUES_URL, PROJECT_RELEASES_URL
|
||||
from backend.tools.version_service import VersionService
|
||||
@@ -58,6 +59,7 @@ class AdvancedSettingInterface(ScrollArea):
|
||||
self.propainter_group.addSettingCard(self.propainter_max_load_num)
|
||||
self.expandLayout.addWidget(self.propainter_group)
|
||||
|
||||
self.advanced_group.addSettingCard(self.save_directory)
|
||||
self.advanced_group.addSettingCard(self.check_update_on_startup)
|
||||
self.expandLayout.addWidget(self.advanced_group)
|
||||
|
||||
@@ -170,6 +172,16 @@ class AdvancedSettingInterface(ScrollArea):
|
||||
parent=self.propainter_group
|
||||
)
|
||||
|
||||
# 视频保存路径
|
||||
self.save_directory = PushSettingCard(
|
||||
text=tr["Setting"]["ChooseDirectory"],
|
||||
icon=FluentIcon.DOWNLOAD,
|
||||
title=tr["Setting"]["SaveDirectory"],
|
||||
content=tr["Setting"]["SaveDirectoryDefault"] if not config.saveDirectory.value else config.saveDirectory.value,
|
||||
parent=self.advanced_group
|
||||
)
|
||||
self.save_directory.clicked.connect(self.choose_save_directory)
|
||||
|
||||
self.check_update_on_startup = SwitchSettingCard(
|
||||
configItem=config.checkUpdateOnStartup,
|
||||
icon=FluentIcon.UPDATE,
|
||||
@@ -244,4 +256,15 @@ class AdvancedSettingInterface(ScrollArea):
|
||||
self.show_message_box(
|
||||
tr["Setting"]["NoUpdatesAvailableTitle"],
|
||||
tr["Setting"]["NoUpdatesAvailableDesc"],
|
||||
)
|
||||
)
|
||||
|
||||
def choose_save_directory(self):
|
||||
"""选择保存目录"""
|
||||
last_save_directory = "./" if not config.saveDirectory.value else config.saveDirectory.value
|
||||
folder = QFileDialog.getExistingDirectory(
|
||||
self, tr['Setting']['ChooseDirectory'], last_save_directory)
|
||||
if not folder:
|
||||
folder = ""
|
||||
|
||||
config.set(config.saveDirectory, folder)
|
||||
self.save_directory.setContent(tr["Setting"]["SaveDirectoryDefault"] if not config.saveDirectory.value else config.saveDirectory.value)
|
||||
@@ -1,13 +1,17 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from enum import Enum, unique
|
||||
from dataclasses import dataclass
|
||||
from functools import cached_property
|
||||
|
||||
from PySide6.QtWidgets import QWidget, QVBoxLayout, QMenu, QAbstractItemView, QTableWidgetItem, QHeaderView
|
||||
from PySide6.QtCore import Qt, Signal, QModelIndex, QUrl
|
||||
from qfluentwidgets import TableWidget, BodyLabel, FluentIcon, InfoBar, InfoBarPosition
|
||||
from PySide6.QtGui import QAction, QColor, QBrush
|
||||
from showinfm import show_in_file_manager
|
||||
|
||||
from backend.config import tr
|
||||
from backend.config import config, tr
|
||||
from backend.tools.common_tools import is_image_file
|
||||
|
||||
@unique
|
||||
class TaskStatus(Enum):
|
||||
@@ -28,8 +32,30 @@ class Task:
|
||||
name: str
|
||||
progress: int
|
||||
status: TaskStatus
|
||||
output_path: str
|
||||
options: dict
|
||||
# 用于储存只读的输出路径, 在任务完成后设置
|
||||
_output_path: str = None
|
||||
|
||||
@property
|
||||
def output_path(self):
|
||||
"""获取输出路径"""
|
||||
if self._output_path is not None:
|
||||
return self._output_path
|
||||
save_directory = os.path.dirname(self.path) if not config.saveDirectory.value else config.saveDirectory.value
|
||||
if self.is_image:
|
||||
output_path = os.path.abspath(os.path.join(save_directory, f'{Path(self.path).stem}_no_sub.png'))
|
||||
else:
|
||||
output_path = os.path.abspath(os.path.join(save_directory, f'{Path(self.path).stem}_no_sub.mp4'))
|
||||
return output_path
|
||||
|
||||
@output_path.setter
|
||||
def output_path(self, value):
|
||||
self._output_path = value
|
||||
|
||||
@cached_property
|
||||
def is_image(self):
|
||||
"""判断是否是图片文件"""
|
||||
return is_image_file(self.path)
|
||||
|
||||
class TaskListComponent(QWidget):
|
||||
"""任务列表组件"""
|
||||
@@ -81,7 +107,7 @@ class TaskListComponent(QWidget):
|
||||
|
||||
layout.addWidget(self.table)
|
||||
|
||||
def add_task(self, video_path, output_path):
|
||||
def add_task(self, video_path):
|
||||
"""添加任务到列表
|
||||
|
||||
Args:
|
||||
@@ -102,7 +128,6 @@ class TaskListComponent(QWidget):
|
||||
name=file_name,
|
||||
progress=0,
|
||||
status=TaskStatus.PENDING,
|
||||
output_path=output_path,
|
||||
options={},
|
||||
)
|
||||
self.tasks.append(task)
|
||||
|
||||
@@ -4,7 +4,6 @@ import threading
|
||||
import multiprocessing
|
||||
import time
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
from PySide6.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout
|
||||
from PySide6.QtCore import Slot, QRect, Signal
|
||||
from PySide6 import QtWidgets
|
||||
@@ -13,7 +12,7 @@ from ui.setting_interface import SettingInterface
|
||||
from ui.component.video_display_component import VideoDisplayComponent
|
||||
from ui.component.task_list_component import TaskListComponent, TaskStatus, TaskOptions
|
||||
from ui.icon.my_fluent_icon import MyFluentIcon
|
||||
from backend.config import tr
|
||||
from backend.config import config, tr
|
||||
from backend.tools.subtitle_remover_remote_call import SubtitleRemoverRemoteCall
|
||||
from backend.tools.process_manager import ProcessManager
|
||||
from backend.tools.common_tools import get_readable_path, is_image_file, read_image
|
||||
@@ -344,12 +343,17 @@ class HomeInterface(QWidget):
|
||||
if key == TaskOptions.SUB_AREAS.value:
|
||||
value = self.video_display_component.preview_coordinates_to_video_coordinates(value)
|
||||
options[key] = value
|
||||
process = self.run_subtitle_remover_process(task.path, task.output_path, options)
|
||||
# 清理缓存, 使用动态路径
|
||||
task.output_path = None
|
||||
output_path = task.output_path
|
||||
process = self.run_subtitle_remover_process(task.path, output_path, options)
|
||||
|
||||
# 更新任务状态为已完成
|
||||
task = self.task_list_component.get_task(self.current_processing_task_index)
|
||||
if process.exitcode == 0 and task and task.status == TaskStatus.PROCESSING:
|
||||
self.progress_signal.emit(100, True)
|
||||
# 任务完成, 更新输出路径为只读
|
||||
task.output_path = output_path
|
||||
self.task_list_component.update_task_status(self.current_processing_task_index, TaskStatus.COMPLETED)
|
||||
else:
|
||||
self.task_list_component.update_task_status(self.current_processing_task_index, TaskStatus.FAILED)
|
||||
@@ -584,11 +588,7 @@ class HomeInterface(QWidget):
|
||||
# 正序添加, 确保任务列表顺序一致
|
||||
for path in reversed(files_loaded):
|
||||
# 添加到任务列表
|
||||
if is_image_file(path):
|
||||
output_path = os.path.abspath(os.path.join(os.path.dirname(path), f'{Path(path).stem}_no_sub.png'))
|
||||
else:
|
||||
output_path = os.path.abspath(os.path.join(os.path.dirname(path), f'{Path(path).stem}_no_sub.mp4'))
|
||||
self.task_list_component.add_task(path, output_path)
|
||||
self.task_list_component.add_task(path)
|
||||
index = max(0, self.task_list_component.find_task_index_by_path(path))
|
||||
self.task_list_component.select_task(index)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user