Commit b032bd2f authored by xuanweiace's avatar xuanweiace

upd done

parent af1d5209
云扬,男,年轻人
2.50(10字/秒)
\ No newline at end of file
......@@ -5,8 +5,7 @@ from PyQt5.QtGui import *;
from PyQt5.QtWidgets import *;
from detect_dialog_ui import Ui_Dialog
from utils import validate_and_get_filepath
from utils import validate_and_get_filepath, replace_path_suffix
class Detect_Dialog(QDialog, Ui_Dialog):
......@@ -22,10 +21,11 @@ class Detect_Dialog(QDialog, Ui_Dialog):
self.pushButton_2.clicked.connect(self.openTableFile)
self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).clicked.connect(self.start_detect)
def openFile(self):
file_info = QFileDialog.getOpenFileNames(self, '选择视频', os.getcwd(), "All Files(*);;Text Files(*.txt)")
file_info = QFileDialog.getOpenFileNames(self, '选择视频', os.getcwd(), "MP4(*.mp4);;Text Files(*.txt)")
file_name, ok = validate_and_get_filepath(file_info)
if ok:
self.lineEdit.setText(file_name)
self.lineEdit_2.setText(replace_path_suffix(file_info[0][0], ".xlsx"))
def openTableFile(self):
now_path = os.path.join(os.getcwd(), self.lineEdit.text())
now_path = now_path.replace(os.path.splitext(now_path)[-1], ".xlsx")
......
......@@ -27,7 +27,7 @@ import re
from typing import Tuple, Union
from detect_with_asr import create_sheet, write_to_sheet
from main_window import MainWindow, Element
# 字幕的上下边界
up_b, down_b = 0, 0
......@@ -186,8 +186,7 @@ def detect_subtitle(img: np.ndarray) -> Union[str, None]:
subTitle = ''
height = down_b - up_b
img = img[int(up_b - height * 0.7):int(down_b + height * 0.7)]
# todo:这里怎么做
img = cv2.resize(img, (int(img.shape[1] * 0.5), int(img.shape[0] * 0.5)))
# img = cv2.resize(img, (int(img.shape[1] * 0.5), int(img.shape[0] * 0.5)))
res = ocr.ocr(img, cls=True)
sorted(res, key=lambda text: text[0][0][1])
if len(res) == 0:
......@@ -217,7 +216,7 @@ def detect_subtitle(img: np.ndarray) -> Union[str, None]:
return None
def process_video(video_path: str, begin: float, end: float, book_path: str, sheet_name: str, state=None):
def process_video(video_path: str, begin: float, end: float, book_path: str, sheet_name: str, state=None, mainWindow: MainWindow=None):
"""处理视频,主要完成对字幕的捕捉以及根据字幕分析得出旁白可能位置的任务
Args:
......@@ -249,10 +248,13 @@ def process_video(video_path: str, begin: float, end: float, book_path: str, she
if video.get(cv2.CAP_PROP_POS_MSEC) / 1000 - end_time > 1:
print('--------------------------------------------------')
recommend_lens = int((video.get(cv2.CAP_PROP_POS_MSEC) / 1000 - end_time) * normal_speed)
write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
# write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
# 判断当前是否有字幕需要被保存下来
if end_time < start_time:
write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end, 2), lastSubTitle, ''])
# write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end, 2), lastSubTitle, ''])
add_to_list(mainWindow, "字幕", [round(start_time, 2), round(end, 2), lastSubTitle, ''])
break
# 每秒取4帧画面左右
if cnt % int(fps / 4) == 0:
......@@ -272,12 +274,13 @@ def process_video(video_path: str, begin: float, end: float, book_path: str, she
print('--------------------------------------------------')
recommend_lens = int(res[-1][0] * normal_speed) if len(res) == 1 else int(
(res[-1][0] - res[-2][1]) * normal_speed)
# narratage_recommend.append(['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
# write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
print(start_time, end_time, lastSubTitle)
# narratage_recommend.append([round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
# 两句话连在一起,但是两句话不一样
# write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
add_to_list(mainWindow,"字幕", [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
# 两句话连在一起,但是两句话不一样
elif lastSubTitle is not None and subTitle is not None:
if string_similar(lastSubTitle, subTitle) < 0.7:
end_time = video.get(cv2.CAP_PROP_POS_MSEC) / 1000
......@@ -286,11 +289,11 @@ def process_video(video_path: str, begin: float, end: float, book_path: str, she
print('--------------------------------------------------')
recommend_lens = int(res[-1][0] * normal_speed) if len(res) == 1 else int(
(res[-1][0] - res[-2][1]) * normal_speed)
# narratage_recommend.append(['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
# write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
print(start_time, end_time, lastSubTitle)
# narratage_recommend.append([round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
# write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
add_to_list(mainWindow, "字幕", [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
start_time = end_time
else:
lastSubTitle = subTitle if len(subTitle) > len(lastSubTitle) else lastSubTitle
......@@ -298,8 +301,29 @@ def process_video(video_path: str, begin: float, end: float, book_path: str, she
# 当前字幕与上一段字幕不一样
lastSubTitle = subTitle
def add_to_list(mainWindow: MainWindow, element_type: str, li: list):
st_time_sec, ed_time_sec, subtitle, suggest = li
st_time_sec, ed_time_sec = str(st_time_sec), str(ed_time_sec)
aside = ""
i = len(mainWindow.projectContext.all_elements)
if element_type == "字幕":
mainWindow.projectContext.subtitle_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside))
mainWindow.projectContext.all_elements.append(mainWindow.projectContext.subtitle_list[-1])
else:
if i == 0:
st_time_sec = "0.01"
else:
st_time_sec = "%.2f" % (float(mainWindow.projectContext.all_elements[i - 1].ed_time_sec) + 0.01)
# 因为暂时没有用到ed_time_sec,所以直接赋值空吧
ed_time_sec = ""
mainWindow.projectContext.aside_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside))
mainWindow.projectContext.all_elements.append(mainWindow.projectContext.aside_list[-1])
def detect_with_ocr(video_path: str, book_path: str, start_time: float, end_time: float, state=None):
def detect_with_ocr(video_path: str, book_path: str, start_time: float, end_time: float, state=None, mainWindow: MainWindow=None):
"""使用ocr检测视频获取字幕并输出旁白推荐
Args:
......@@ -321,14 +345,14 @@ def detect_with_ocr(video_path: str, book_path: str, start_time: float, end_time
global up_b, down_b
# print("get the bounding of the narratage at time: ", datetime.datetime.now())
# 此处start_time + 300是为了节省用户调整视频开始时间的功夫(强行跳过前5分钟)
up_b, down_b = get_position(video_path, start_time+300)
up_b, down_b = get_position(video_path, start_time)
# 获取并构建输出信息
table_head = [["起始时间", "终止时间", "字幕", '建议', '解说脚本']]
# print("create sheet at time: ", datetime.datetime.now())
create_sheet(book_name_xlsx, sheet_name_xlsx, table_head)
# print("process the total video at time: ", datetime.datetime.now())
process_video(video_path, start_time, end_time, book_name_xlsx, sheet_name_xlsx, state)
process_video(video_path, start_time, end_time, book_name_xlsx, sheet_name_xlsx, state, mainWindow)
if __name__ == '__main__':
......
......@@ -11,6 +11,7 @@ from detect_dialog import Detect_Dialog
from assemble_dialog import Assemble_Dialog
from prompt_dialog import Prompt_Dialog
from setting_dialog import Setting_Dialog
from operation_dialog import Operation_Dialog
from synthesis import SynthesisProcessor
from myVideoWidget import myVideoWidget
from myvideoslider import myVideoSlider
......@@ -45,6 +46,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
#提示框
self.prompt_dialog = Prompt_Dialog()
#操作框
self.operation_dialog = Operation_Dialog(self)
self.operation_dialog.start_add_signal.connect(self.add_line_operation_slot)
self.operation_dialog.start_del_signal.connect(self.del_line_operation_slot)
#所有QTimer集中管理
self.detect_timer = QTimer()
self.detect_timer.timeout.connect(self.check_if_detect_over_slot)
......@@ -87,10 +94,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.action_save.triggered.connect(self.save_project)
self.import_movie.triggered.connect(self.import_slot)
self.action_open_project.triggered.connect(self.open_project_slot)
self.action_refresh_tab.triggered.connect(self.refresh_tab_slot)
self.action_undo.triggered.connect(self.undo_slot)
self.action_redo.triggered.connect(self.redo_slot)
self.action_view_history.triggered.connect(self.view_history_slot)
self.action_operate.triggered.connect(self.operate_slot)
# 状态栏的动作
# self.statusbar.addPermanentWidget(self.statusbarButton, stretch=0)
......@@ -212,6 +222,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# self.show_warning_msg_box("请确认结束时间是否正确")
# return
self.projectContext.Init(os.path.dirname(book_path), os.path.basename(book_path))
# 获取视频的时长等信息,初始化开始结束时间
startTime = "00:00:00"
......@@ -248,10 +260,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# threads.append(t)
from narratage_detection import detect
# todo:先只支持有字幕的
t = RunThread(funcName=detect,
args=(video_path, start_time, end_time,
book_path, state, 1),
book_path, state, 1,self),
name="detect")
t.setDaemon(True)
self.threads.append(t)
......@@ -384,6 +396,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
args=(audio_path, self.previewed_audio),
name="play_audio").start()
@staticmethod
#一条语音的最长播放时间是10秒
def play_audio(path, previewed_audio):
......@@ -515,7 +528,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
return False
def save_project(self):
err_info = self.projectContext.save_project()
err_info = self.projectContext.save_project(True)
if err_info == None:
self.prompt_dialog.show_dialog_signal.emit("保存工程成功")
else:
......@@ -572,7 +585,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def rewriteHistory(self, item):
if self.projectContext.initial_ing == True:
return
# 合成这一段语音
from speech_synthesis import speech_synthesis, Speaker, choose_speaker
print("self.projectContext.excel_path:", self.projectContext.excel_path)
audio_dir = os.path.dirname(self.projectContext.excel_path)
print("self.pb_tableWidget.itemAt(item.row(), 0).text()", self.projectContext.aside_list[item.row()].st_time_sec)
wav_path = audio_dir + '/tmp/%.2f.wav' % float(self.projectContext.aside_list[item.row()].st_time_sec)
......@@ -654,8 +670,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.projectContext.refresh_aside(row, text)
# 更新【字幕旁白】这个tab里的字
start_time = self.pb_tableWidget.item(int(row), constant.Aside.StartTimeColumn).text()
idx = self.projectContext.aside2contentId(Element(str(start_time),0,0,0,0))
# self.projectContext.refresh_element(idx, text)
idx = self.projectContext.aside_subtitle_2contentId(Element(str(start_time),0,0,0,0))
self.all_tableWidget.setItem(int(row), constant.Content.ActivateColumn, QTableWidgetItem(text))
def write2ProjectFromContent(self, item):
print("write2ProjectFromContent")
......@@ -723,4 +738,54 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# 在【打开工程】操作的时候,设置sld_video的最大值为电影秒数。
print("打开工程:self.player.duration()", self.player.duration())
print("设置最大值为:", self.player.duration()/1000 + 1)
self.sld_video.setMaximum(self.player.duration()/1000 + 1)
\ No newline at end of file
self.sld_video.setMaximum(self.player.duration()/1000 + 1)
def refresh_tab_slot(self):
self.set_table_to_window()
self.projectContext.save_project(False)
def operate_slot(self):
self.operation_dialog.show()
def add_line_operation_slot(self, row, start_time, end_time, subtitle, suggest, aside):
# 注意,这里需要用同一对象,不能生成多个Element
new_element = Element(start_time, end_time, subtitle, suggest, aside)
self.projectContext.all_elements.insert(int(row), new_element)
if suggest is not None and "插入旁白,推荐字数为" in suggest:
idx = 0
while idx < len(self.projectContext.aside_list):
if float(start_time) < float(self.projectContext.aside_list[idx].st_time_sec):
break
idx += 1
self.projectContext.aside_list.insert(idx, new_element)
else:
idx = 0
while idx < len(self.projectContext.subtitle_list):
if float(start_time) < float(self.projectContext.subtitle_list[idx].st_time_sec):
break
idx += 1
self.projectContext.subtitle_list.insert(idx, new_element)
self.prompt_dialog.show_with_msg("操作成功!!请刷新表格查看变化")
def del_line_operation_slot(self, row, start_time, end_time, subtitle, suggest, aside):
to_be_delete_element = self.projectContext.all_elements[int(row) - 1]
if self.projectContext.all_elements[int(row)-1].suggest is not None \
and "插入旁白,推荐字数为" in self.projectContext.all_elements[int(row)-1].suggest:
for i in range(len(self.projectContext.aside_list)):
if to_be_delete_element.equalTo(self.projectContext.aside_list[i]):
self.projectContext.aside_list.pop(i)
break
else:
for i in range(len(self.projectContext.subtitle_header)):
if to_be_delete_element.equalTo(self.projectContext.subtitle_list[i]):
self.projectContext.subtitle_list.pop(i)
break
self.projectContext.all_elements.pop(int(row)-1)
self.prompt_dialog.show_with_msg("操作成功!!请刷新表格查看变化")
......@@ -515,6 +515,8 @@ QPushButton:pressed {
<addaction name="action_undo"/>
<addaction name="action_redo"/>
<addaction name="action_view_history"/>
<addaction name="separator"/>
<addaction name="action_operate"/>
</widget>
<widget class="QMenu" name="menu_3">
<property name="title">
......@@ -522,6 +524,8 @@ QPushButton:pressed {
</property>
<addaction name="actiona_3"/>
<addaction name="actiona_4"/>
<addaction name="separator"/>
<addaction name="action_refresh_tab"/>
</widget>
<addaction name="menu"/>
<addaction name="menu_2"/>
......@@ -550,7 +554,7 @@ QPushButton:pressed {
</action>
<action name="action_save">
<property name="text">
<string>工程保存</string>
<string>保存并备份</string>
</property>
</action>
<action name="action_undo">
......@@ -578,6 +582,16 @@ QPushButton:pressed {
<string>history</string>
</property>
</action>
<action name="action_refresh_tab">
<property name="text">
<string>刷新且保存表格</string>
</property>
</action>
<action name="action_operate">
<property name="text">
<string>增删行</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
......
......@@ -293,6 +293,10 @@ class Ui_MainWindow(object):
self.actiona_4.setObjectName("actiona_4")
self.action_view_history = QtWidgets.QAction(MainWindow)
self.action_view_history.setObjectName("action_view_history")
self.action_refresh_tab = QtWidgets.QAction(MainWindow)
self.action_refresh_tab.setObjectName("action_refresh_tab")
self.action_operate = QtWidgets.QAction(MainWindow)
self.action_operate.setObjectName("action_operate")
self.menu.addAction(self.actionxinjian)
self.menu.addAction(self.action_open_project)
self.menu.addSeparator()
......@@ -302,8 +306,12 @@ class Ui_MainWindow(object):
self.menu_2.addAction(self.action_undo)
self.menu_2.addAction(self.action_redo)
self.menu_2.addAction(self.action_view_history)
self.menu_2.addSeparator()
self.menu_2.addAction(self.action_operate)
self.menu_3.addAction(self.actiona_3)
self.menu_3.addAction(self.actiona_4)
self.menu_3.addSeparator()
self.menu_3.addAction(self.action_refresh_tab)
self.menubar.addAction(self.menu.menuAction())
self.menubar.addAction(self.menu_2.menuAction())
self.menubar.addAction(self.menu_3.menuAction())
......@@ -333,12 +341,14 @@ class Ui_MainWindow(object):
self.action_open_project.setText(_translate("MainWindow", "打开"))
self.import_movie.setText(_translate("MainWindow", "视频导入"))
self.actions.setText(_translate("MainWindow", "内容导出"))
self.action_save.setText(_translate("MainWindow", "工程保存"))
self.action_save.setText(_translate("MainWindow", "保存并备份"))
self.action_undo.setText(_translate("MainWindow", "撤销"))
self.action_redo.setText(_translate("MainWindow", "重做"))
self.actiona_3.setText(_translate("MainWindow", "旁白区间检测"))
self.actiona_4.setText(_translate("MainWindow", "旁白音频合成"))
self.action_view_history.setText(_translate("MainWindow", "history"))
self.action_refresh_tab.setText(_translate("MainWindow", "刷新且保存表格"))
self.action_operate.setText(_translate("MainWindow", "增删行"))
from myVideoWidget import myVideoWidget
......
......@@ -120,8 +120,11 @@ class ProjectContext:
self.subtitle_list = []
self.aside_list = []
self.all_elements = []
self.speaker_info = '晓辰,女,年轻人'
self.speaker_speed = '1.00(4字/秒)'
f = open("./conf.ini", "r", encoding='utf-8')
rl = f.readlines()
f.close()
self.speaker_info = rl[0].strip()
self.speaker_speed = rl[1].strip()
# 一些常量
self.header = ["起始时间", "终止时间", "字幕", '建议', '解说脚本']
self.aside_header = ["起始时间", "终止时间", '建议', '解说脚本']
......@@ -145,28 +148,38 @@ class ProjectContext:
self.history_records = []
self.records_pos = 0
def Init(self, project_dir, video_name):
# 有的时候路径是 '/F:/out1/test.xlsx',有的时候是'F:/out1/test.xlsx'
if project_dir[0] == '/':
project_dir = project_dir[1:]
self.project_base_dir = project_dir
# self.video_path = os.path.join(project_dir, video_name)
self.video_path = project_dir[1:] + "/" + video_name
self.video_path = project_dir + "/" + video_name
print("video_pathvideo_path: ", self.video_path)
self.excel_path = replace_path_suffix(self.video_path, ".xlsx")
# def Init(self, project_dir, video_path, excel_path):
# self.project_base_dir = project_dir
# self.video_path = video_path
# self.excel_path = excel_path
def save_conf(self):
with open('./conf.ini', 'w', encoding='utf-8') as f:
f.writelines([self.speaker_info + '\n', self.speaker_speed])
def setVideoPath(self, video_path):
self.video_path = video_path
def setExcelPath(self, excel_path):
self.excel_path = excel_path
# 目前只是把excel保存到文件中
# 先备份文件,再覆盖主文件
def save_project(self) -> str:
# 先备份文件,再覆盖主文件,可选是否需要备份,默认需要备份
def save_project(self, need_save_new: bool=False) -> str:
# all_element = sorted(all_element, key=lambda x: float(x.st_time_sec))
new_excel_path = replace_path_suffix(self.excel_path, datetime.datetime.now().strftime('%Y%m%d%H%M%S')+'.xlsx')
err_info = save_excel_to_to_path(self.all_elements, new_excel_path, self.header, self.excel_sheet_name)
if err_info != None:
return err_info
print("current excel_path:", self.excel_path)
if need_save_new:
new_excel_path = replace_path_suffix(self.excel_path, datetime.datetime.now().strftime('%Y%m%d%H%M%S')+'.xlsx')
err_info = save_excel_to_to_path(self.all_elements, new_excel_path, self.header, self.excel_sheet_name)
if err_info != None:
return err_info
err_info = save_excel_to_to_path(self.all_elements, self.excel_path, self.header, self.excel_sheet_name)
if err_info != None:
return err_info
......@@ -229,7 +242,8 @@ class ProjectContext:
self.records_pos += 1
return res
def aside2contentId(self, aside_element: Element)->int:
# 把【字幕id】或者【旁白id】转化成【内容id】
def aside_subtitle_2contentId(self, aside_element: Element)->int:
for i in range(len(self.all_elements)):
if aside_element.equalTo(self.all_elements[i]):
return i
......
......@@ -11,9 +11,9 @@
"""
import os.path
import argparse
from main_window import MainWindow
def detect(video_path: str, start_time: float, end_time: float, book_path: str, state=None, subtitle: int = 0):
def detect(video_path: str, start_time: float, end_time: float, book_path: str, state=None, subtitle: int = 0, mainWindow: MainWindow=None):
"""字幕及旁白区间检测
Args:
......@@ -44,10 +44,10 @@ def detect(video_path: str, start_time: float, end_time: float, book_path: str,
if has_subtitle:
from detect_with_ocr import detect_with_ocr
detect_with_ocr(video_path, book_path, start_time, end_time, state)
else:
from detect_with_asr import detect_with_asr
detect_with_asr(video_path, book_path, start_time, end_time, state)
detect_with_ocr(video_path, book_path, start_time, end_time, state, mainWindow)
# else:
# from detect_with_asr import detect_with_asr
# detect_with_asr(video_path, book_path, start_time, end_time, state)
if __name__ == '__main__':
......@@ -64,4 +64,4 @@ if __name__ == '__main__':
args = parser.parse_args()
detect(args.video_path, args.start_time, args.end_time, args.book_path)
detect(args.video_path, args.start_time, args.end_time, args.book_path,None)
import sys
import os
from PyQt5.QtCore import *;
from PyQt5.QtGui import *;
from PyQt5.QtWidgets import *;
from operation_dialog_ui import Ui_Dialog
from utils import validate_and_get_filepath, replace_path_suffix
#todo 注意,删除行,添加行,暂不支持【撤销与重做】功能!!!
class Operation_Dialog(QDialog, Ui_Dialog):
#开始检测信号,传参分别是movie路径和输出表格路径
start_add_signal = pyqtSignal(str, str, str, str, str, str)
start_del_signal = pyqtSignal(str, str, str, str, str, str)
def __init__(self, mainWindow):
super(Operation_Dialog, self).__init__()
self.setupUi(self)
self.setWindowTitle("操作表格")
self.mainWindow = mainWindow
self.pushButton.clicked.connect(self.check_validate_slot)
self.pushButton_2.clicked.connect(self.remake_slot)
self.buttonBox.setEnabled(False)
self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).clicked.connect(self.start_operation_slot)
# 字幕/旁白 选择框
self.comboBox.currentIndexChanged.connect(self.zmpb_change_slot)
# 增加一行/删除一行 选择框
self.comboBox_2.currentIndexChanged.connect(self.adddel_change_slot)
self.lineEdits = [self.lineEdit, self.lineEdit_2, self.lineEdit_3, self.lineEdit_4, self.lineEdit_5, self.lineEdit_6]
self.zmpb_change_slot()
self.adddel_change_slot()
def zmpb_change_slot(self):
# 如果是删除,则直接return
if self.comboBox_2.currentText() == "删除一行":
return
self.set_all_user_component_status(True)
if self.comboBox.currentText() == "字幕":
self.lineEdit_5.setEnabled(False)
self.lineEdit_6.setEnabled(False)
else:
self.lineEdit_3.setEnabled(False)
self.lineEdit_4.setEnabled(False)
# 如果是删除,则只需要【行数】即可
def adddel_change_slot(self):
if self.comboBox_2.currentText() == "增加一行":
self.zmpb_change_slot()
else:
for i in range(1,len(self.lineEdits)):
self.lineEdits[i].setEnabled(False)
# 修改完后需要重新检测
def remake_slot(self):
self.buttonBox.setEnabled(False)
self.set_all_user_component_status(True)
def check_validate_slot(self):
# 校验行数
rowCount = self.mainWindow.all_tableWidget.rowCount()
try:
cnt = int(self.lineEdit.text())
assert cnt <= rowCount
except Exception as e:
self.mainWindow.prompt_dialog.show_with_msg("校验失败!总行数为[%d],你的输入为[%s]!!"%(rowCount, self.lineEdit.text()))
return
# 这些是只有【add】才需要检测的
if self.comboBox_2.currentText() == "增加一行":
#校验起始时间、结束时间
start_time_f, end_time_f = 0.0, 0.0
try:
start_time_f = float(self.lineEdit_2.text())
if self.comboBox.currentText() == "字幕":
end_time_f = float(self.lineEdit_3.text())
assert start_time_f < end_time_f
except Exception as e:
self.mainWindow.prompt_dialog.show_with_msg("校验失败!起始时间或结束时间输入有误!!" )
return
# 校验推荐字数
if self.comboBox.currentText() == "旁白":
try:
suggest_words_count = int(self.lineEdit_5.text())
assert suggest_words_count <= 100
except Exception as e:
self.mainWindow.prompt_dialog.show_with_msg("校验失败!推荐字数填入有误!!")
return
# 检测通过
self.mainWindow.prompt_dialog.show_with_msg("校验成功!!")
self.buttonBox.setEnabled(True)
self.set_all_user_component_status(False)
def set_all_user_component_status(self, status: bool):
for lineEdit in self.lineEdits:
lineEdit.setEnabled(status)
self.comboBox.setEnabled(status)
self.comboBox_2.setEnabled(status)
def start_operation_slot(self):
row, start_time, end_time, subtitle, suggest, aside = [x.text() for x in self.lineEdits]
if self.comboBox.currentText() == "字幕":
suggest = ""
aside = ""
else: # 如果是旁白
end_time = ""
subtitle = ""
suggest = "插入旁白,推荐字数为" + suggest
# 别忘复原
self.buttonBox.setEnabled(False)
self.zmpb_change_slot()
self.adddel_change_slot()
# 根据增删两种操作,分别触发不同信号。
if self.comboBox_2.currentText() == "增加一行":
self.start_add_signal.emit(row, start_time, end_time, subtitle, suggest, aside)
else:
self.start_del_signal.emit(row, start_time, end_time, subtitle, suggest, aside)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./images/eagle_2.ico"))
dialog = Operation_Dialog()
dialog.show()
sys.exit(app.exec_())
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>635</width>
<height>395</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>470</x>
<y>340</y>
<width>101</width>
<height>32</height>
</rect>
</property>
<property name="toolTip">
<string/>
</property>
<property name="toolTipDuration">
<number>-1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>60</x>
<y>70</y>
<width>81</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>我想操作第</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>140</x>
<y>70</y>
<width>101</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>250</x>
<y>70</y>
<width>311</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>行(如果操作是增加,则在该行后面增加)</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_2">
<property name="geometry">
<rect>
<x>140</x>
<y>120</y>
<width>101</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>60</x>
<y>120</y>
<width>71</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>起始时间:</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>60</x>
<y>170</y>
<width>71</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>结束时间:</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_3">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>140</x>
<y>170</y>
<width>101</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_4">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>140</x>
<y>220</y>
<width>231</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>140</x>
<y>20</y>
<width>87</width>
<height>22</height>
</rect>
</property>
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>字幕</string>
</property>
</item>
<item>
<property name="text">
<string>旁白</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="comboBox_2">
<property name="geometry">
<rect>
<x>260</x>
<y>20</y>
<width>87</width>
<height>22</height>
</rect>
</property>
<item>
<property name="text">
<string>增加一行</string>
</property>
</item>
<item>
<property name="text">
<string>删除一行</string>
</property>
</item>
</widget>
<widget class="QLineEdit" name="lineEdit_5">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>140</x>
<y>260</y>
<width>101</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_6">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>140</x>
<y>300</y>
<width>231</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_5">
<property name="geometry">
<rect>
<x>60</x>
<y>220</y>
<width>71</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>字幕:</string>
</property>
</widget>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>60</x>
<y>260</y>
<width>71</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>推荐字数:</string>
</property>
</widget>
<widget class="QLabel" name="label_7">
<property name="geometry">
<rect>
<x>60</x>
<y>300</y>
<width>71</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>旁白:</string>
</property>
</widget>
<widget class="QLabel" name="label_8">
<property name="geometry">
<rect>
<x>250</x>
<y>120</y>
<width>251</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>*请填数字,最多保留两位小数</string>
</property>
</widget>
<widget class="QLabel" name="label_9">
<property name="geometry">
<rect>
<x>250</x>
<y>170</y>
<width>251</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>*请填数字,最多保留两位小数</string>
</property>
</widget>
<widget class="QLabel" name="label_10">
<property name="geometry">
<rect>
<x>380</x>
<y>220</y>
<width>81</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>*请填文字</string>
</property>
</widget>
<widget class="QLabel" name="label_11">
<property name="geometry">
<rect>
<x>380</x>
<y>300</y>
<width>81</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>*请填文字</string>
</property>
</widget>
<widget class="QLabel" name="label_12">
<property name="geometry">
<rect>
<x>250</x>
<y>260</y>
<width>251</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>*请填数字,必须是不超过100的正整数</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>350</x>
<y>340</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>检测</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>230</x>
<y>340</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>修改</string>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'operation_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.12
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(635, 395)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setEnabled(False)
self.buttonBox.setGeometry(QtCore.QRect(470, 340, 101, 32))
self.buttonBox.setToolTip("")
self.buttonBox.setToolTipDuration(-1)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setCenterButtons(False)
self.buttonBox.setObjectName("buttonBox")
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(60, 70, 81, 20))
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(140, 70, 101, 21))
self.lineEdit.setObjectName("lineEdit")
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setGeometry(QtCore.QRect(250, 70, 311, 21))
self.label_2.setObjectName("label_2")
self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_2.setGeometry(QtCore.QRect(140, 120, 101, 21))
self.lineEdit_2.setObjectName("lineEdit_2")
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setGeometry(QtCore.QRect(60, 120, 71, 16))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setGeometry(QtCore.QRect(60, 170, 71, 16))
self.label_4.setObjectName("label_4")
self.lineEdit_3 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_3.setEnabled(True)
self.lineEdit_3.setGeometry(QtCore.QRect(140, 170, 101, 21))
self.lineEdit_3.setObjectName("lineEdit_3")
self.lineEdit_4 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_4.setEnabled(True)
self.lineEdit_4.setGeometry(QtCore.QRect(140, 220, 231, 21))
self.lineEdit_4.setObjectName("lineEdit_4")
self.comboBox = QtWidgets.QComboBox(Dialog)
self.comboBox.setEnabled(True)
self.comboBox.setGeometry(QtCore.QRect(140, 20, 87, 22))
self.comboBox.setEditable(False)
self.comboBox.setObjectName("comboBox")
self.comboBox.addItem("")
self.comboBox.addItem("")
self.comboBox_2 = QtWidgets.QComboBox(Dialog)
self.comboBox_2.setGeometry(QtCore.QRect(260, 20, 87, 22))
self.comboBox_2.setObjectName("comboBox_2")
self.comboBox_2.addItem("")
self.comboBox_2.addItem("")
self.lineEdit_5 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_5.setEnabled(True)
self.lineEdit_5.setGeometry(QtCore.QRect(140, 260, 101, 21))
self.lineEdit_5.setObjectName("lineEdit_5")
self.lineEdit_6 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_6.setEnabled(True)
self.lineEdit_6.setGeometry(QtCore.QRect(140, 300, 231, 21))
self.lineEdit_6.setObjectName("lineEdit_6")
self.label_5 = QtWidgets.QLabel(Dialog)
self.label_5.setGeometry(QtCore.QRect(60, 220, 71, 16))
self.label_5.setObjectName("label_5")
self.label_6 = QtWidgets.QLabel(Dialog)
self.label_6.setGeometry(QtCore.QRect(60, 260, 71, 16))
self.label_6.setObjectName("label_6")
self.label_7 = QtWidgets.QLabel(Dialog)
self.label_7.setGeometry(QtCore.QRect(60, 300, 71, 16))
self.label_7.setObjectName("label_7")
self.label_8 = QtWidgets.QLabel(Dialog)
self.label_8.setGeometry(QtCore.QRect(250, 120, 251, 20))
self.label_8.setObjectName("label_8")
self.label_9 = QtWidgets.QLabel(Dialog)
self.label_9.setGeometry(QtCore.QRect(250, 170, 251, 20))
self.label_9.setObjectName("label_9")
self.label_10 = QtWidgets.QLabel(Dialog)
self.label_10.setGeometry(QtCore.QRect(380, 220, 81, 20))
self.label_10.setObjectName("label_10")
self.label_11 = QtWidgets.QLabel(Dialog)
self.label_11.setGeometry(QtCore.QRect(380, 300, 81, 20))
self.label_11.setObjectName("label_11")
self.label_12 = QtWidgets.QLabel(Dialog)
self.label_12.setGeometry(QtCore.QRect(250, 260, 251, 20))
self.label_12.setObjectName("label_12")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(350, 340, 93, 28))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(Dialog)
self.pushButton_2.setGeometry(QtCore.QRect(230, 340, 93, 28))
self.pushButton_2.setObjectName("pushButton_2")
self.retranslateUi(Dialog)
self.buttonBox.rejected.connect(Dialog.reject)
self.buttonBox.accepted.connect(Dialog.accept)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "我想操作第"))
self.label_2.setText(_translate("Dialog", "行(如果操作是增加,则在该行后面增加)"))
self.label_3.setText(_translate("Dialog", "起始时间:"))
self.label_4.setText(_translate("Dialog", "结束时间:"))
self.comboBox.setItemText(0, _translate("Dialog", "字幕"))
self.comboBox.setItemText(1, _translate("Dialog", "旁白"))
self.comboBox_2.setItemText(0, _translate("Dialog", "增加一行"))
self.comboBox_2.setItemText(1, _translate("Dialog", "删除一行"))
self.label_5.setText(_translate("Dialog", "字幕:"))
self.label_6.setText(_translate("Dialog", "推荐字数:"))
self.label_7.setText(_translate("Dialog", "旁白:"))
self.label_8.setText(_translate("Dialog", "*请填数字,最多保留两位小数"))
self.label_9.setText(_translate("Dialog", "*请填数字,最多保留两位小数"))
self.label_10.setText(_translate("Dialog", "*请填文字"))
self.label_11.setText(_translate("Dialog", "*请填文字"))
self.label_12.setText(_translate("Dialog", "*请填数字,必须是不超过100的正整数"))
self.pushButton.setText(_translate("Dialog", "检测"))
self.pushButton_2.setText(_translate("Dialog", "修改"))
......@@ -7,6 +7,9 @@ from PyQt5.QtWidgets import *;
from setting_dialog_ui import Ui_Dialog
from utils import validate_and_get_filepath, replace_path_suffix
import winsound
audioPlayed = winsound.PlaySound(None, winsound.SND_NODEFAULT)
class Setting_Dialog(QDialog, Ui_Dialog):
......@@ -23,18 +26,62 @@ class Setting_Dialog(QDialog, Ui_Dialog):
li = self.projectContext.get_all_speaker_info()
for i in li:
self.comboBox.addItem(i)
# self.comboBox.addItem('晓秋,女,年轻人')
self.comboBox_2.addItems(["1.00(4字/秒)", "1.10(4.5字/秒)", "1.25(5字/秒)", "1.50(6字/秒)", "1.75(7字/秒)", "2.00(8字/秒)", "2.50(10字/秒)"])
li_2 = ["1.00(4字/秒)", "1.10(4.5字/秒)", "1.25(5字/秒)", "1.50(6字/秒)", "1.75(7字/秒)", "2.00(8字/秒)", "2.50(10字/秒)"]
self.comboBox_2.addItems(li_2)
self.comboBox.setCurrentIndex(li.index(self.projectContext.speaker_info))
self.comboBox_2.setCurrentIndex(li_2.index(self.projectContext.speaker_speed))
self.comboBox.currentIndexChanged.connect(self.speaker_change_slot)
self.comboBox_2.currentIndexChanged.connect(self.speed_change_slot)
self.pushButton.clicked.connect(self.play_audio_slot)
def speaker_change_slot(self):
self.projectContext.speaker_info = self.comboBox.currentText()
self.projectContext.save_conf()
# print("self.projectContext.speaker_info:", self.projectContext.speaker_info)
def speed_change_slot(self):
self.projectContext.speaker_speed = self.comboBox_2.currentText()
self.projectContext.save_conf()
def play_audio_slot(self):
"""播放说话人的样例音频
根据用户选择的说话人更新对应样例音频
停止上一个说话人的音频
播放当前说话人的音频
"""
def f():
chosenSpeaker = self.projectContext.choose_speaker(self.projectContext.speaker_info.split(",")[0])
# 停止音频
global audioPlayed
winsound.PlaySound(audioPlayed, winsound.SND_PURGE)
# 播放音频
audioPlayed = winsound.PlaySound(chosenSpeaker.voice_example, winsound.SND_ASYNC)
thread_it(f, name="playAudio")
# 重写关闭窗口事件,使得可以停止播放样例视频
def closeEvent(self, event):
global audioPlayed
winsound.PlaySound(audioPlayed, winsound.SND_PURGE)
event.accept()
def thread_it(func, *args, name):
"""创建守护线程
Args:
func: 待执行的函数名
args: 函数所需的参数
name: 线程名
"""
# 创建线程
import threading
t = threading.Thread(target=func, args=args, name=name)
# 守护
t.setDaemon(True)
# 启动
t.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./images/eagle_2.ico"))
......
......@@ -65,6 +65,19 @@
<string/>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>350</x>
<y>140</y>
<width>121</width>
<height>71</height>
</rect>
</property>
<property name="text">
<string>播放样例音频</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
......
......@@ -27,6 +27,9 @@ class Ui_Dialog(object):
self.comboBox_2.setGeometry(QtCore.QRect(130, 190, 151, 31))
self.comboBox_2.setCurrentText("")
self.comboBox_2.setObjectName("comboBox_2")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(350, 140, 121, 71))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
......@@ -36,5 +39,6 @@ class Ui_Dialog(object):
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label_3.setText(_translate("Dialog", "旁白说话人:"))
self.label_4.setText(_translate("Dialog", "旁白语速:"))
self.pushButton.setText(_translate("Dialog", "播放样例音频"))
......@@ -100,7 +100,9 @@ def speech_synthesis(text: str, output_file: str, speaker: Speaker, speed: float
speech_config.speech_synthesis_voice_name = speaker.speaker_code
# 先把合成的语音文件输出得到tmp.wav中,便于可能的调速需求
if not os.path.exists(os.path.dirname(audio_path)): # 如果路径不存在
print("路径不存在,创建:", os.path.dirname(audio_path))
os.makedirs(os.path.dirname(audio_path))
audio_config = AudioOutputConfig(filename=audio_path)
synthesizer = SpeechSynthesizer(
speech_config=speech_config, audio_config=audio_config)
......
......@@ -10,6 +10,7 @@ from main_window import MainWindow
if __name__ == '__main__':
try:
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./images/eagle_2.ico"))
mainWindow = MainWindow()
......
No preview for this file type
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment