Commit 69305eb1 authored by xuanweiace's avatar xuanweiace

upd 新增对字幕和旁白表格的支持 并支持毫秒级视频运行时间的展示

parent 23b4ef50
# accessibility_movie_2 # accessibility_movie_2
二期的无障碍电影制作工具,主要包含旁白区间检测和旁白及字幕导出两个功能; 二期主要提升用户体验、产品功能与易用性,设计成熟的操作界面进行人机交互,另外为了方便用户使用,使用pyinstaller进行打包。 二期的无障碍电影制作工具,主要包含旁白区间检测和旁白及字幕导出两个功能; 二期主要提升用户体验、产品功能与易用性,设计成熟的操作界面进行人机交互,另外为了方便用户使用,使用pyinstaller进行打包。
\ No newline at end of file
注意要自行下载mp4的解码器,不然无法播放视频
\ No newline at end of file
...@@ -34,6 +34,7 @@ def create_sheet(path: str, sheet_name: str, value: list): ...@@ -34,6 +34,7 @@ def create_sheet(path: str, sheet_name: str, value: list):
""" """
index = len(value) index = len(value)
workbook = openpyxl.Workbook() workbook = openpyxl.Workbook()
sheet = workbook.active sheet = workbook.active
sheet.title = sheet_name sheet.title = sheet_name
# 将字幕对应的那一列扩宽一些 # 将字幕对应的那一列扩宽一些
...@@ -109,6 +110,8 @@ def detect_with_asr(video_path: str, book_path: str, start_time=0, end_time=-1, ...@@ -109,6 +110,8 @@ def detect_with_asr(video_path: str, book_path: str, start_time=0, end_time=-1,
if __name__ == '__main__': if __name__ == '__main__':
create_sheet("./xxxxxx.xlsx", "abc", [["起始时间", "终止时间", "字幕", '建议', '解说脚本']])
# write_to_sheet("./xxx.xlsx", "abc", ["qssj", "zzsj", "zm", 'jy', 'pb'])
pass pass
# start_time = time.time() # start_time = time.time()
# # 给定待处理的视频路径 # # 给定待处理的视频路径
......
...@@ -2,10 +2,11 @@ import time ...@@ -2,10 +2,11 @@ import time
import os import os
import cv2 import cv2
from PyQt5.QtWidgets import QMainWindow, QFileDialog from PyQt5.QtWidgets import QMainWindow, QFileDialog, QTableWidget, QTableWidgetItem
import utils import utils
from management import RunThread from utils import validate_and_get_filepath
from management import RunThread, ProjectContext, Element
from detect_dialog import Detect_Dialog from detect_dialog import Detect_Dialog
from assemble_dialog import Assemble_Dialog from assemble_dialog import Assemble_Dialog
from synthesis import SynthesisProcessor from synthesis import SynthesisProcessor
...@@ -20,6 +21,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -20,6 +21,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
self.setupUi(self) self.setupUi(self)
self.statusbar.showMessage("hello", 5000) self.statusbar.showMessage("hello", 5000)
self.projectContext = ProjectContext()
# 语音合成相关组件 # 语音合成相关组件
# todo:后续改成QThread的组件 # todo:后续改成QThread的组件
...@@ -30,21 +32,24 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -30,21 +32,24 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.detect_dialog.start_detect_signal.connect(self.start_detect) self.detect_dialog.start_detect_signal.connect(self.start_detect)
#合成对话框 #合成对话框
self.assemble_dialog = Assemble_Dialog() self.assemble_dialog = Assemble_Dialog()
self.assemble_dialog.start_assemble_signal.connect(self.synthesis.synthesis_slot) self.assemble_dialog.start_assemble_signal.connect(self.synthesis.synthesis_slot)
# 菜单栏的动作
self.actiona_3.triggered.connect(self.show_detect_dialog) self.actiona_3.triggered.connect(self.show_detect_dialog)
self.actiona_4.triggered.connect(self.show_assemble_dialog) self.actiona_4.triggered.connect(self.show_assemble_dialog)
self.action_save.triggered.connect(self.save_project)
self.import_movie.triggered.connect(self.import_slot)
#视频时长,全局变量 #视频时长,全局变量
self.video_duration = None self.video_duration = None
self.sld_video_pressed=False #判断当前进度条识别否被鼠标点击 self.sld_video_pressed=False #判断当前进度条识别否被鼠标点击
self.videoFullScreen = False # 判断当前widget是否全屏 self.videoFullScreen = False # 判断当前widget是否全屏
self.videoFullScreenWidget = myVideoWidget() # 创建一个全屏的widget self.videoFullScreenWidget = myVideoWidget() # 创建一个全屏的widget
self.player = QMediaPlayer() self.player = QMediaPlayer()
self.player.setVideoOutput(self.wgt_video) # 视频播放输出的widget,就是上面定义的 self.player.setVideoOutput(self.wgt_video) # 视频播放输出的widget,就是上面定义的
self.btn_open.clicked.connect(self.openVideoFile) # 打开视频文件按钮 self.btn_open.clicked.connect(self.open_excel) # 打开视频文件按钮
self.btn_play.clicked.connect(self.playVideo) # play self.btn_play.clicked.connect(self.playVideo) # play
self.btn_stop.clicked.connect(self.pauseVideo) # pause self.btn_stop.clicked.connect(self.pauseVideo) # pause
self.player.positionChanged.connect(self.changeSlide) # change Slide self.player.positionChanged.connect(self.changeSlide) # change Slide
...@@ -75,6 +80,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -75,6 +80,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
replp = QtWidgets.QMessageBox.question(self, u'警告', msg, replp = QtWidgets.QMessageBox.question(self, u'警告', msg,
QtWidgets.QMessageBox.Yes) QtWidgets.QMessageBox.Yes)
def import_slot(self):
video_path = self.openVideoFile()
self.init_ProjectContext_VideoPath(video_path)
def start_detect(self, video_path, book_path): def start_detect(self, video_path, book_path):
...@@ -108,7 +116,6 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -108,7 +116,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
# self.show_warning_msg_box("请确认结束时间是否正确") # self.show_warning_msg_box("请确认结束时间是否正确")
# return # return
print("daozhele")
# 获取视频的时长等信息,初始化开始结束时间 # 获取视频的时长等信息,初始化开始结束时间
startTime = "00:00:00" startTime = "00:00:00"
...@@ -128,7 +135,6 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -128,7 +135,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.show_warning_msg_box("开始时间不得大于等于结束时间,请重新填写") self.show_warning_msg_box("开始时间不得大于等于结束时间,请重新填写")
return return
print("daozhele11111")
video_fps = cv2.VideoCapture(video_path).get(cv2.CAP_PROP_FPS) video_fps = cv2.VideoCapture(video_path).get(cv2.CAP_PROP_FPS)
if (end_time - start_time) * video_fps < 150: if (end_time - start_time) * video_fps < 150:
self.show_warning_msg_box("您想要检测的片段太短,请重新输入开始时间和结束时间!") self.show_warning_msg_box("您想要检测的片段太短,请重新输入开始时间和结束时间!")
...@@ -217,20 +223,25 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -217,20 +223,25 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.player.setVolume(volume) self.player.setVolume(volume)
self.lab_audio.setText("volume:"+str(volume)+"%") self.lab_audio.setText("volume:"+str(volume)+"%")
# postion 取值[0,100]
def clickedSlider(self, position): def clickedSlider(self, position):
if self.player.duration() > 0: # 开始播放后才允许进行跳转 if self.player.duration() > 0: # 开始播放后才允许进行跳转
video_position = int((position / 100) * self.player.duration()) video_position = int((position / 100) * self.player.duration())
self.player.setPosition(video_position) self.player.setPosition(video_position)
self.lab_video.setText("%.2f%%" % position) # print("pos:", position, "总时长:", self.player.duration())
# self.lab_video.setText("%.2f%%" % position)
self.lab_video.setText(utils.transfer_second_to_time(str(video_position)))
else: else:
self.sld_video.setValue(0) self.sld_video.setValue(0)
# position 取值[0,100]
def moveSlider(self, position): def moveSlider(self, position):
self.sld_video_pressed = True self.sld_video_pressed = True
if self.player.duration() > 0: # 开始播放后才允许进行跳转 if self.player.duration() > 0: # 开始播放后才允许进行跳转
video_position = int((position / 100) * self.player.duration()) video_position = int((position / 100) * self.player.duration())
self.player.setPosition(video_position) self.player.setPosition(video_position)
self.lab_video.setText("%.2f%%" % position) # self.lab_video.setText("%.2f%%" % position)
self.lab_video.setText(utils.transfer_second_to_time(str(video_position)))
def pressSlider(self): def pressSlider(self):
self.sld_video_pressed = True self.sld_video_pressed = True
...@@ -239,16 +250,28 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -239,16 +250,28 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def releaseSlider(self): def releaseSlider(self):
self.sld_video_pressed = False self.sld_video_pressed = False
# position 取值[0,总时长]
def changeSlide(self, position): def changeSlide(self, position):
if not self.sld_video_pressed: # 进度条被鼠标点击时不更新 if not self.sld_video_pressed: # 进度条被鼠标点击时不更新
self.vidoeLength = self.player.duration()+0.1 self.vidoeLength = self.player.duration()+0.1
self.sld_video.setValue(round((position/self.vidoeLength)*100)) self.sld_video.setValue(round((position/self.vidoeLength)*100))
self.lab_video.setText("%.2f%%" % ((position/self.vidoeLength)*100)) self.lab_video.setText(utils.transfer_second_to_time(str(position/1000)))
# self.lab_video.setText("%.2f%%" % ((position/self.vidoeLength)*100))
def openVideoFile(self): def openVideoFile(self):
self.player.setMedia(QMediaContent(QFileDialog.getOpenFileUrl()[0])) # 选取视频文件 path = QFileDialog.getOpenFileUrl()[0]
self.player.setMedia(QMediaContent(path)) # 选取视频文件
self.player.play() # 播放视频 self.player.play() # 播放视频
print(self.player.availableMetaData()) print(self.player.availableMetaData())
return path
# 在初始化工程时
def init_ProjectContext_VideoPath(self, path):
# video_dir = os.path.dirname(path)
# video_name = os.path.basename(path)
# self.projectContext.Init(video_dir, video_name)
self.projectContext.setVideoPath(path)
def playVideo(self): def playVideo(self):
self.player.play() self.player.play()
...@@ -268,3 +291,41 @@ class MainWindow(QMainWindow, Ui_MainWindow): ...@@ -268,3 +291,41 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.player.setVideoOutput(self.videoFullScreenWidget) self.player.setVideoOutput(self.videoFullScreenWidget)
self.videoFullScreenWidget.setFullScreen(1) self.videoFullScreenWidget.setFullScreen(1)
self.videoFullScreen = True self.videoFullScreen = True
def open_excel(self):
file_info = QFileDialog.getOpenFileNames(self, '选择表格路径', os.getcwd(), "All Files(*);;Text Files(*.txt)")
file_path, ok = validate_and_get_filepath(file_info)
# path = QFileDialog.getOpenFileUrl()
print("表格路径:" , file_path)
if ok == False:
return
self.projectContext.setExcelPath(file_path)
self.projectContext.load_excel_from_path()
self.set_table_to_window()
def set_table_to_window(self):
header = self.projectContext.header
subtitle_list = self.projectContext.subtitle_list
aside_list = self.projectContext.aside_list
self.zm_tableWidget.setRowCount(len(subtitle_list))
self.zm_tableWidget.setColumnCount(len(header))
self.zm_tableWidget.setHorizontalHeaderLabels(header)
for i in range(len(subtitle_list)):
self.setElememtToTable(self.zm_tableWidget, subtitle_list[i], i)
self.pb_tableWidget.setRowCount(len(aside_list))
self.pb_tableWidget.setColumnCount(len(header))
self.pb_tableWidget.setHorizontalHeaderLabels(header)
for i in range(len(aside_list)):
self.setElememtToTable(self.pb_tableWidget, aside_list[i], i)
def setElememtToTable(self, table: QTableWidget, elem: Element, idx: int):
elem_list = elem.to_list()
for j in range(len(elem_list)):
table.setItem(idx, j, QTableWidgetItem(elem_list[j]))
def save_project(self):
self.projectContext.save_project()
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>939</width> <width>939</width>
<height>755</height> <height>763</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<layout class="QHBoxLayout" name="shuiping" stretch="3,1"> <layout class="QHBoxLayout" name="shuiping" stretch="3,1">
<item> <item>
<widget class="QWidget" name="verticalWidget_3" native="true"> <widget class="QWidget" name="verticalWidget_3" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="8,1"> <layout class="QVBoxLayout" name="verticalLayout_3" stretch="8,0">
<item> <item>
<widget class="myVideoWidget" name="wgt_video" native="true"> <widget class="myVideoWidget" name="wgt_video" native="true">
<property name="minimumSize"> <property name="minimumSize">
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>打开视频文件</string> <string>打开表格文件</string>
</property> </property>
</widget> </widget>
<widget class="QPushButton" name="btn_play"> <widget class="QPushButton" name="btn_play">
...@@ -276,7 +276,7 @@ QPushButton:pressed { ...@@ -276,7 +276,7 @@ QPushButton:pressed {
<enum>QTabWidget::Triangular</enum> <enum>QTabWidget::Triangular</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
...@@ -293,15 +293,25 @@ QPushButton:pressed { ...@@ -293,15 +293,25 @@ QPushButton:pressed {
<property name="tabBarAutoHide"> <property name="tabBarAutoHide">
<bool>false</bool> <bool>false</bool>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="zm_tab">
<attribute name="title"> <attribute name="title">
<string>字幕</string> <string>字幕</string>
</attribute> </attribute>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QTableWidget" name="zm_tableWidget"/>
</item>
</layout>
</widget> </widget>
<widget class="QWidget" name="tab_2"> <widget class="QWidget" name="pb_tab">
<attribute name="title"> <attribute name="title">
<string>旁白</string> <string>旁白</string>
</attribute> </attribute>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QTableWidget" name="pb_tableWidget"/>
</item>
</layout>
</widget> </widget>
</widget> </widget>
</item> </item>
...@@ -455,10 +465,10 @@ QPushButton:pressed { ...@@ -455,10 +465,10 @@ QPushButton:pressed {
<addaction name="actionxinjian"/> <addaction name="actionxinjian"/>
<addaction name="actiona"/> <addaction name="actiona"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actiona_2"/> <addaction name="import_movie"/>
<addaction name="actions"/> <addaction name="actions"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actions_2"/> <addaction name="action_save"/>
</widget> </widget>
<widget class="QMenu" name="menu_2"> <widget class="QMenu" name="menu_2">
<property name="title"> <property name="title">
...@@ -489,7 +499,7 @@ QPushButton:pressed { ...@@ -489,7 +499,7 @@ QPushButton:pressed {
<string>打开</string> <string>打开</string>
</property> </property>
</action> </action>
<action name="actiona_2"> <action name="import_movie">
<property name="text"> <property name="text">
<string>视频导入</string> <string>视频导入</string>
</property> </property>
...@@ -499,7 +509,7 @@ QPushButton:pressed { ...@@ -499,7 +509,7 @@ QPushButton:pressed {
<string>内容导出</string> <string>内容导出</string>
</property> </property>
</action> </action>
<action name="actions_2"> <action name="action_save">
<property name="text"> <property name="text">
<string>工程保存</string> <string>工程保存</string>
</property> </property>
......
...@@ -12,7 +12,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets ...@@ -12,7 +12,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object): class Ui_MainWindow(object):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow") MainWindow.setObjectName("MainWindow")
MainWindow.resize(939, 755) MainWindow.resize(939, 763)
MainWindow.setStyleSheet("QMainWindow:{\n" MainWindow.setStyleSheet("QMainWindow:{\n"
" border: 2px groove gray;\n" " border: 2px groove gray;\n"
" border-radius: 25px;\n" " border-radius: 25px;\n"
...@@ -141,7 +141,6 @@ class Ui_MainWindow(object): ...@@ -141,7 +141,6 @@ class Ui_MainWindow(object):
self.label_2.setObjectName("label_2") self.label_2.setObjectName("label_2")
self.verticalLayout_3.addWidget(self.splitter) self.verticalLayout_3.addWidget(self.splitter)
self.verticalLayout_3.setStretch(0, 8) self.verticalLayout_3.setStretch(0, 8)
self.verticalLayout_3.setStretch(1, 1)
self.shuiping.addWidget(self.verticalWidget_3) self.shuiping.addWidget(self.verticalWidget_3)
self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
self.tabWidget.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu) self.tabWidget.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
...@@ -153,12 +152,26 @@ class Ui_MainWindow(object): ...@@ -153,12 +152,26 @@ class Ui_MainWindow(object):
self.tabWidget.setMovable(False) self.tabWidget.setMovable(False)
self.tabWidget.setTabBarAutoHide(False) self.tabWidget.setTabBarAutoHide(False)
self.tabWidget.setObjectName("tabWidget") self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget() self.zm_tab = QtWidgets.QWidget()
self.tab.setObjectName("tab") self.zm_tab.setObjectName("zm_tab")
self.tabWidget.addTab(self.tab, "") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.zm_tab)
self.tab_2 = QtWidgets.QWidget() self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.tab_2.setObjectName("tab_2") self.zm_tableWidget = QtWidgets.QTableWidget(self.zm_tab)
self.tabWidget.addTab(self.tab_2, "") self.zm_tableWidget.setObjectName("zm_tableWidget")
self.zm_tableWidget.setColumnCount(0)
self.zm_tableWidget.setRowCount(0)
self.horizontalLayout_2.addWidget(self.zm_tableWidget)
self.tabWidget.addTab(self.zm_tab, "")
self.pb_tab = QtWidgets.QWidget()
self.pb_tab.setObjectName("pb_tab")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.pb_tab)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.pb_tableWidget = QtWidgets.QTableWidget(self.pb_tab)
self.pb_tableWidget.setObjectName("pb_tableWidget")
self.pb_tableWidget.setColumnCount(0)
self.pb_tableWidget.setRowCount(0)
self.horizontalLayout_3.addWidget(self.pb_tableWidget)
self.tabWidget.addTab(self.pb_tab, "")
self.shuiping.addWidget(self.tabWidget) self.shuiping.addWidget(self.tabWidget)
self.shuiping.setStretch(0, 3) self.shuiping.setStretch(0, 3)
self.shuiping.setStretch(1, 1) self.shuiping.setStretch(1, 1)
...@@ -248,12 +261,12 @@ class Ui_MainWindow(object): ...@@ -248,12 +261,12 @@ class Ui_MainWindow(object):
self.actionxinjian.setObjectName("actionxinjian") self.actionxinjian.setObjectName("actionxinjian")
self.actiona = QtWidgets.QAction(MainWindow) self.actiona = QtWidgets.QAction(MainWindow)
self.actiona.setObjectName("actiona") self.actiona.setObjectName("actiona")
self.actiona_2 = QtWidgets.QAction(MainWindow) self.import_movie = QtWidgets.QAction(MainWindow)
self.actiona_2.setObjectName("actiona_2") self.import_movie.setObjectName("import_movie")
self.actions = QtWidgets.QAction(MainWindow) self.actions = QtWidgets.QAction(MainWindow)
self.actions.setObjectName("actions") self.actions.setObjectName("actions")
self.actions_2 = QtWidgets.QAction(MainWindow) self.action_save = QtWidgets.QAction(MainWindow)
self.actions_2.setObjectName("actions_2") self.action_save.setObjectName("action_save")
self.actionchexiao = QtWidgets.QAction(MainWindow) self.actionchexiao = QtWidgets.QAction(MainWindow)
self.actionchexiao.setObjectName("actionchexiao") self.actionchexiao.setObjectName("actionchexiao")
self.actionchongzuo = QtWidgets.QAction(MainWindow) self.actionchongzuo = QtWidgets.QAction(MainWindow)
...@@ -265,10 +278,10 @@ class Ui_MainWindow(object): ...@@ -265,10 +278,10 @@ class Ui_MainWindow(object):
self.menu.addAction(self.actionxinjian) self.menu.addAction(self.actionxinjian)
self.menu.addAction(self.actiona) self.menu.addAction(self.actiona)
self.menu.addSeparator() self.menu.addSeparator()
self.menu.addAction(self.actiona_2) self.menu.addAction(self.import_movie)
self.menu.addAction(self.actions) self.menu.addAction(self.actions)
self.menu.addSeparator() self.menu.addSeparator()
self.menu.addAction(self.actions_2) self.menu.addAction(self.action_save)
self.menu_2.addAction(self.actionchexiao) self.menu_2.addAction(self.actionchexiao)
self.menu_2.addAction(self.actionchongzuo) self.menu_2.addAction(self.actionchongzuo)
self.menu_3.addAction(self.actiona_3) self.menu_3.addAction(self.actiona_3)
...@@ -278,19 +291,19 @@ class Ui_MainWindow(object): ...@@ -278,19 +291,19 @@ class Ui_MainWindow(object):
self.menubar.addAction(self.menu_3.menuAction()) self.menubar.addAction(self.menu_3.menuAction())
self.retranslateUi(MainWindow) self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(1) self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow): def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.btn_open.setText(_translate("MainWindow", "打开视频文件")) self.btn_open.setText(_translate("MainWindow", "打开表格文件"))
self.btn_play.setText(_translate("MainWindow", "播放")) self.btn_play.setText(_translate("MainWindow", "播放"))
self.btn_stop.setText(_translate("MainWindow", "暂停")) self.btn_stop.setText(_translate("MainWindow", "暂停"))
self.lab_audio.setText(_translate("MainWindow", "volume:100%")) self.lab_audio.setText(_translate("MainWindow", "volume:100%"))
self.label_2.setText(_translate("MainWindow", "00:00/12:34")) self.label_2.setText(_translate("MainWindow", "00:00/12:34"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "字幕")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.zm_tab), _translate("MainWindow", "字幕"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "旁白")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.pb_tab), _translate("MainWindow", "旁白"))
self.zm_label.setText(_translate("MainWindow", "字幕时间轴")) self.zm_label.setText(_translate("MainWindow", "字幕时间轴"))
self.lab_video.setText(_translate("MainWindow", "0%")) self.lab_video.setText(_translate("MainWindow", "0%"))
self.pb_label.setText(_translate("MainWindow", "旁白时间轴")) self.pb_label.setText(_translate("MainWindow", "旁白时间轴"))
...@@ -299,9 +312,9 @@ class Ui_MainWindow(object): ...@@ -299,9 +312,9 @@ class Ui_MainWindow(object):
self.menu_3.setTitle(_translate("MainWindow", "功能按键")) self.menu_3.setTitle(_translate("MainWindow", "功能按键"))
self.actionxinjian.setText(_translate("MainWindow", "新建")) self.actionxinjian.setText(_translate("MainWindow", "新建"))
self.actiona.setText(_translate("MainWindow", "打开")) self.actiona.setText(_translate("MainWindow", "打开"))
self.actiona_2.setText(_translate("MainWindow", "视频导入")) self.import_movie.setText(_translate("MainWindow", "视频导入"))
self.actions.setText(_translate("MainWindow", "内容导出")) self.actions.setText(_translate("MainWindow", "内容导出"))
self.actions_2.setText(_translate("MainWindow", "工程保存")) self.action_save.setText(_translate("MainWindow", "工程保存"))
self.actionchexiao.setText(_translate("MainWindow", "撤销")) self.actionchexiao.setText(_translate("MainWindow", "撤销"))
self.actionchongzuo.setText(_translate("MainWindow", "重做")) self.actionchongzuo.setText(_translate("MainWindow", "重做"))
self.actiona_3.setText(_translate("MainWindow", "旁白区间检测")) self.actiona_3.setText(_translate("MainWindow", "旁白区间检测"))
......
import os.path
import threading import threading
import traceback import traceback
import sys import sys
from enum import Enum
import openpyxl
from openpyxl.styles import PatternFill, Alignment
from utils import replace_path_suffix
class RunThread(threading.Thread): class RunThread(threading.Thread):
"""复写线程类,用于解决主线程无法捕捉子线程中异常的问题 """复写线程类,用于解决主线程无法捕捉子线程中异常的问题
""" """
...@@ -42,4 +51,148 @@ class RunThread(threading.Thread): ...@@ -42,4 +51,148 @@ class RunThread(threading.Thread):
try: try:
self._funcName(*self._args) self._funcName(*self._args)
except Exception as e: except Exception as e:
raise e raise e
\ No newline at end of file
# 计划支持两种操作符,修改和删除(目前还是仅支持修改)
# todo:删除是指对字幕Element的删除(比如重复的进行合并)
class Operation(Enum):
Modify = 0
# Delete = 1
# 维护一条历史记录
# 目前仅支持对旁白做修改
class OperateRecord:
def __init__(self, operation: Operation, old: str, new: str):
self.operation = operation
self.old_str = old
self.new_str = new
# 每一行的具体信息,"起始时间", "终止时间", "字幕", '建议', '解说脚本'
class Element:
def __init__(self, st_time_sec: float, ed_time_sec: float, subtitle, suggest, aside):
self.st_time_sec = st_time_sec
self.ed_time_sec = ed_time_sec
self.subtitle = subtitle
self.suggest = suggest
self.aside = aside
self.history_records = []
# 判断当前元素是否是字幕
def is_subtitle(self):
return self.subtitle != None and self.subtitle != ""
# 判断当前元素是否是旁白
def is_aside(self):
return not self.is_subtitle()
def to_list(self):
return [self.st_time_sec, self.ed_time_sec, self.subtitle, self.suggest, self.aside]
class ProjectContext:
def __init__(self):
self.project_base_dir = None
self.video_path = None
self.excel_path = None
self.subtitle_list = []
self.aside_list = []
# 一些常量
self.header = ["起始时间", "终止时间", "字幕", '建议', '解说脚本']
self.excel_sheet_name = "旁白插入位置建议"
def Init(self, project_dir, video_name):
self.project_base_dir = project_dir
self.video_path = os.path.join(project_dir, video_name)
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 setVideoPath(self, video_path):
self.video_path = video_path
def setExcelPath(self, excel_path):
self.excel_path = excel_path
# 目前只是把excel保存到文件中
def save_project(self):
all_element = self.subtitle_list + self.aside_list
all_element.sort(lambda x, y: (x.st_time_sec < y.st_time_sec))
for element in all_element:
write_to_sheet(self.excel_path, self.excel_sheet_name, element.to_list)
# 加载整个工程,填充到ProjectContext上下文中
def load_project(self):
pass
def load_excel_from_path(self):
d = read_sheet(self.excel_path)
# todo:现在是只用None判断是否是字幕,后续是否也需要用""来?
for i in range(len(d["字幕"])):
st_time_sec, ed_time_sec, subtitle, suggest, aside = [d[x][i] for x in self.header]
if d["字幕"][i] != None:
self.subtitle_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside))
else:
self.aside_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside))
def write_to_sheet(path: str, sheet_name: str, value: list):
"""向已存在的表格中写入一行数据
Args:
path (str): 表格(book)的存储位置
sheet_name (str): excel表内的表(sheet)的名字
value (list): 要插入表内的一行数据
"""
index = len(value)
workbook = openpyxl.load_workbook(path)
sheet = workbook.get_sheet_by_name(sheet_name)
cur_row = sheet.max_row
for j in range(0, index):
sheet.cell(row=cur_row + 1, column=j + 1, value=str(value[j]))
if value[j] == '' or '插入旁白' in str(value[j]):
sheet.cell(row=cur_row + 1, column=j + 1).fill = PatternFill(fill_type='solid', fgColor='ffff00')
if j == 2:
sheet.cell(row=cur_row + 1, column=j + 1).alignment = Alignment(wrapText=True)
workbook.save(path)
def read_sheet(book_path: str, sheet_name: str = "") -> dict:
"""读表
从表格中读出所有的内容,用dict保存(表格的格式固定,第一行为表头(起始时间|终止时间|字幕|建议|解说脚本))
Args:
book_path (str): 表格的存储路径
sheet_name (str, optional): 想要读取的表在excel表格中的名字. Defaults to "".
Returns:
dict: 表格中的所有内容,key为该列表头,value为列中的数据
"""
workbook = openpyxl.load_workbook(book_path)
sheet = workbook.active
rows = sheet.max_row
cols = sheet.max_column
sheet_content = {}
# 读取xlsx中每列的内容,默认第一行是各列的列名
for i in range(1, rows + 1):
for j in range(1, cols + 1):
if i == 1:
sheet_content[sheet.cell(1, j).value] = []
else:
sheet_content[sheet.cell(1, j).value].append(
sheet.cell(i, j).value)
return sheet_content
if __name__ == '__main__':
# d = read_sheet("test37second.xlsx")
# print(d["字幕"])
# print(d.keys())
ctx = ProjectContext()
ctx.setExcelPath("d:/123")
print(ctx.excel_path)
\ No newline at end of file
import sys
from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem, QAbstractItemView)
class myTableWidget(QWidget):
def __init__(self):
super(myTableWidget,self).__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("QTableWidget演示")
self.resize(430, 230);
layout = QHBoxLayout()
tablewidget = QTableWidget()
tablewidget.setRowCount(4)
tablewidget.setColumnCount(6)
layout.addWidget(tablewidget)
tablewidget.setHorizontalHeaderLabels(['时间','文字'])
nameItem = QTableWidgetItem("0:00")
tablewidget.setItem(0,0,nameItem)
ageItem = QTableWidgetItem("24")
tablewidget.setItem(0,1,ageItem)
jgItem = QTableWidgetItem("北京")
tablewidget.setItem(0,2,jgItem)
# 禁止编辑
# tablewidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 整行选择
tablewidget.setSelectionBehavior(QAbstractItemView.SelectRows)
# 调整列和行
tablewidget.resizeColumnsToContents()
tablewidget.resizeRowsToContents()
# tablewidget.horizontalHeader().setVisible(False)
# tablewidget.verticalHeader().setVisible(False)
tablewidget.setVerticalHeaderLabels(["a","b"])
# 隐藏表格线
tablewidget.setShowGrid(False)
self.setLayout(layout)
tablewidget.itemClicked.connect(self.show_data)
def show_data(self, Item):
# 如果单元格对象为空
if Item is None:
return
else:
row = Item.row() # 获取行数
col = Item.column() # 获取列数 注意是column而不是col哦
text = Item.text() # 获取内容
# 输出测试
print('row = ', row)
print('col =', col)
print('text = ', text)
if __name__ == '__main__':
app = QApplication(sys.argv)
example = myTableWidget()
example.show()
sys.exit(app.exec_())
...@@ -7,4 +7,15 @@ def f(a,b,c,d): ...@@ -7,4 +7,15 @@ def f(a,b,c,d):
data = [ 'ACME', 50, 91.1, (2012, 12, 21) ] data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]
name, shares, price, date = data name, shares, price, date = data
print(name) print(name)
\ No newline at end of file
from enum import Enum
class Operation(Enum):
Modify = 0
Delete = 1
# print(Operation.Delete)
print(Operation(('修改', "xiugai")))
\ No newline at end of file
...@@ -403,10 +403,13 @@ def ss_and_export(video_path: str, sheet_path: str, output_dir: str, speed: floa ...@@ -403,10 +403,13 @@ def ss_and_export(video_path: str, sheet_path: str, output_dir: str, speed: floa
if __name__ == '__main__': if __name__ == '__main__':
video_path = r'D:/Downloads/zhanlang.rmvb' # video_path = r'D:/Downloads/zhanlang.rmvb'
sheet_path = r'D:/Downloads/战狼.xlsx' # sheet_path = r'D:/Downloads/战狼.xlsx'
output_dir = r'D:/AddCaption/last_version/accessibility_movie/zhanlang' # output_dir = r'D:/AddCaption/last_version/accessibility_movie/zhanlang'
speed = 1.25 # speed = 1.25
caption_file = './zhanlang/zhanlang.srt' # caption_file = './zhanlang/zhanlang.srt'
speaker_name = '晓秋' # speaker_name = '晓秋'
ss_and_export(video_path, sheet_path, output_dir, speed, caption_file, speaker_name) # ss_and_export(video_path, sheet_path, output_dir, speed, caption_file, speaker_name)
import pprint
d = read_sheet("./test37second.xlsx")
pprint.pprint(d)
\ No newline at end of file
import sys
from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem, QAbstractItemView)
from PyQt5.QtCore import Qt
class TableWidget(QWidget):
def __init__(self):
super(TableWidget,self).__init__()
self.initUI()
def initUI(self):
self.setWindowTitle("QTableWidget演示")
self.resize(430, 230);
layout = QHBoxLayout()
tablewidget = QTableWidget()
tablewidget.setRowCount(4)
tablewidget.setColumnCount(6)
layout.addWidget(tablewidget)
tablewidget.setHorizontalHeaderLabels(['时间','文字'])
nameItem = QTableWidgetItem("0:00")
# nameItem.setFlags()
tablewidget.setItem(0,0,nameItem)
ageItem = QTableWidgetItem("24")
tablewidget.setItem(0,1,ageItem)
jgItem = QTableWidgetItem("北京")
# jgItem.setFlags(Qt.ItemIsEnabled)
jgItem.setFlags(Qt.ItemFlags(32))
# jgItem.checkState()
tablewidget.setItem(0,2,jgItem)
# 禁止编辑
# tablewidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 整行选择
tablewidget.setSelectionBehavior(QAbstractItemView.SelectRows)
# 调整列和行
tablewidget.resizeColumnsToContents()
tablewidget.resizeRowsToContents()
# tablewidget.horizontalHeader().setVisible(False)
# tablewidget.verticalHeader().setVisible(False)
tablewidget.setVerticalHeaderLabels(["a","b"])
# 隐藏表格线
tablewidget.setShowGrid(False)
self.setLayout(layout)
tablewidget.itemClicked.connect(self.show_data)
def show_data(self, Item):
# 如果单元格对象为空
if Item is None:
return
else:
print(Item.checkState())
row = Item.row() # 获取行数
col = Item.column() # 获取列数 注意是column而不是col哦
text = Item.text() # 获取内容
# 输出测试
print('row = ', row)
print('col =', col)
print('text = ', text)
if __name__ == '__main__':
app = QApplication(sys.argv)
example = TableWidget()
example.show()
sys.exit(app.exec_())
...@@ -25,7 +25,15 @@ def trans_to_seconds(timePoint: str) -> float: ...@@ -25,7 +25,15 @@ def trans_to_seconds(timePoint: str) -> float:
units *= 60 units *= 60
return time_in_seconds return time_in_seconds
def transfer_second_to_time(sec: str) -> str:
duration = int(float(sec))
minutes = int(duration / 60)
seconds = int(duration - 60 * minutes)
idx = sec.find('.')
if(idx == -1):
idx = len(sec)
time = "%02d:%02d%s" % (minutes, seconds, sec[idx:])
return time
def replace_path_suffix(path, new_suffix): def replace_path_suffix(path, new_suffix):
return path.replace(os.path.splitext(path)[-1], new_suffix) return path.replace(os.path.splitext(path)[-1], new_suffix)
...@@ -66,4 +74,9 @@ def get_sheetHead(book_path: str) -> list: ...@@ -66,4 +74,9 @@ def get_sheetHead(book_path: str) -> list:
if rows > 1: if rows > 1:
for j in range(1, cols + 1): for j in range(1, cols + 1):
sheet_head.append(sheet.cell(1, j).value) sheet_head.append(sheet.cell(1, j).value)
return sheet_head return sheet_head
\ No newline at end of file
if __name__ == '__main__':
x = transfer_second_to_time("12000.923")
print(x)
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