Commit 8142abd4 authored by 翟艳秋(20软)'s avatar 翟艳秋(20软)

fix some bugs and fit ocr with low quality films

parent ad04a182
...@@ -13,155 +13,72 @@ ...@@ -13,155 +13,72 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Dialog</string>
</property> </property>
<widget class="QDialogButtonBox" name="buttonBox"> <layout class="QGridLayout" name="gridLayout">
<property name="geometry"> <item row="0" column="2">
<rect> <widget class="QPushButton" name="pushButton_2">
<x>220</x> <property name="text">
<y>250</y> <string>表格路径</string>
<width>341</width> </property>
<height>32</height> </widget>
</rect> </item>
</property> <item row="1" column="1">
<property name="toolTip"> <widget class="QLineEdit" name="lineEdit_3">
<string/> <property name="enabled">
</property> <bool>false</bool>
<property name="toolTipDuration"> </property>
<number>-1</number> </widget>
</property> </item>
<property name="orientation"> <item row="2" column="1">
<enum>Qt::Horizontal</enum> <widget class="QLineEdit" name="lineEdit_4">
</property> <property name="enabled">
<property name="standardButtons"> <bool>false</bool>
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> </property>
</property> </widget>
<property name="centerButtons"> </item>
<bool>false</bool> <item row="0" column="1">
</property> <widget class="QLineEdit" name="lineEdit_2"/>
</widget> </item>
<widget class="QLabel" name="label"> <item row="2" column="0">
<property name="geometry"> <widget class="QLabel" name="label_4">
<rect> <property name="text">
<x>40</x> <string>旁白语速:</string>
<y>40</y> </property>
<width>72</width> </widget>
<height>15</height> </item>
</rect> <item row="3" column="1" alignment="Qt::AlignHCenter">
</property> <widget class="QDialogButtonBox" name="buttonBox">
<property name="text"> <property name="toolTip">
<string>视频路径:</string> <string/>
</property> </property>
</widget> <property name="toolTipDuration">
<widget class="QLineEdit" name="lineEdit"> <number>-1</number>
<property name="geometry"> </property>
<rect> <property name="orientation">
<x>130</x> <enum>Qt::Horizontal</enum>
<y>40</y> </property>
<width>231</width> <property name="standardButtons">
<height>21</height> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</rect> </property>
</property> <property name="centerButtons">
</widget> <bool>false</bool>
<widget class="QPushButton" name="pushButton"> </property>
<property name="geometry"> </widget>
<rect> </item>
<x>390</x> <item row="0" column="0">
<y>40</y> <widget class="QLabel" name="label_2">
<width>101</width> <property name="text">
<height>31</height> <string>旁白脚本表格:</string>
</rect> </property>
</property> </widget>
<property name="text"> </item>
<string>选择文件</string> <item row="1" column="0">
</property> <widget class="QLabel" name="label_3">
</widget> <property name="text">
<widget class="QLabel" name="label_2"> <string>旁白说话人:</string>
<property name="geometry"> </property>
<rect> </widget>
<x>20</x> </item>
<y>90</y> </layout>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>旁白脚本表格:</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_2">
<property name="geometry">
<rect>
<x>130</x>
<y>90</y>
<width>231</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>390</x>
<y>90</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>表格路径</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>30</x>
<y>140</y>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>旁白说话人:</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>30</x>
<y>200</y>
<width>111</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>旁白语速:</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>130</x>
<y>140</y>
<width>231</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_4">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>130</x>
<y>200</y>
<width>231</width>
<height>21</height>
</rect>
</property>
</widget>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'assemble_dialog.ui' # Form implementation generated from reading ui file 'd:\AddCaption\cur_version\accessibility_movie_2\assemble_dialog.ui'
# #
# Created by: PyQt5 UI code generator 5.12 # Created by: PyQt5 UI code generator 5.15.4
# #
# WARNING! All changes made in this file will be lost! # WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
...@@ -13,46 +15,48 @@ class Ui_Dialog(object): ...@@ -13,46 +15,48 @@ class Ui_Dialog(object):
def setupUi(self, Dialog): def setupUi(self, Dialog):
Dialog.setObjectName("Dialog") Dialog.setObjectName("Dialog")
Dialog.resize(585, 326) Dialog.resize(585, 326)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.buttonBox.setGeometry(QtCore.QRect(220, 250, 341, 32)) self.gridLayout.setObjectName("gridLayout")
self.buttonBox.setToolTip("")
self.buttonBox.setToolTipDuration(-1)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setCenterButtons(False)
self.buttonBox.setObjectName("buttonBox")
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(40, 40, 72, 15))
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(130, 40, 231, 21))
self.lineEdit.setObjectName("lineEdit")
self.pushButton = QtWidgets.QPushButton(Dialog) self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(390, 40, 101, 31))
self.pushButton.setObjectName("pushButton") self.pushButton.setObjectName("pushButton")
self.label_2 = QtWidgets.QLabel(Dialog) self.gridLayout.addWidget(self.pushButton, 0, 2, 1, 1)
self.label_2.setGeometry(QtCore.QRect(20, 90, 111, 16))
self.label_2.setObjectName("label_2")
self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_2.setGeometry(QtCore.QRect(130, 90, 231, 21))
self.lineEdit_2.setObjectName("lineEdit_2")
self.pushButton_2 = QtWidgets.QPushButton(Dialog)
self.pushButton_2.setGeometry(QtCore.QRect(390, 90, 101, 31))
self.pushButton_2.setObjectName("pushButton_2")
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setGeometry(QtCore.QRect(30, 140, 111, 16))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(Dialog) self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setGeometry(QtCore.QRect(30, 200, 111, 16))
self.label_4.setObjectName("label_4") self.label_4.setObjectName("label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.lineEdit_3 = QtWidgets.QLineEdit(Dialog) self.lineEdit_3 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_3.setEnabled(False) self.lineEdit_3.setEnabled(False)
self.lineEdit_3.setGeometry(QtCore.QRect(130, 140, 231, 21))
self.lineEdit_3.setObjectName("lineEdit_3") self.lineEdit_3.setObjectName("lineEdit_3")
self.gridLayout.addWidget(self.lineEdit_3, 2, 1, 1, 1)
self.lineEdit_4 = QtWidgets.QLineEdit(Dialog) self.lineEdit_4 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_4.setEnabled(False) self.lineEdit_4.setEnabled(False)
self.lineEdit_4.setGeometry(QtCore.QRect(130, 200, 231, 21))
self.lineEdit_4.setObjectName("lineEdit_4") self.lineEdit_4.setObjectName("lineEdit_4")
self.gridLayout.addWidget(self.lineEdit_4, 3, 1, 1, 1)
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setObjectName("lineEdit")
self.gridLayout.addWidget(self.lineEdit, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_2.setObjectName("lineEdit_2")
self.gridLayout.addWidget(self.lineEdit_2, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(Dialog)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.pushButton_2 = QtWidgets.QPushButton(Dialog)
self.pushButton_2.setObjectName("pushButton_2")
self.gridLayout.addWidget(self.pushButton_2, 1, 2, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setToolTip("")
self.buttonBox.setToolTipDuration(-1)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setCenterButtons(False)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 4, 1, 1, 1, QtCore.Qt.AlignHCenter)
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) self.buttonBox.accepted.connect(Dialog.accept)
...@@ -62,9 +66,9 @@ class Ui_Dialog(object): ...@@ -62,9 +66,9 @@ class Ui_Dialog(object):
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog")) Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "视频路径:"))
self.pushButton.setText(_translate("Dialog", "选择文件")) self.pushButton.setText(_translate("Dialog", "选择文件"))
self.label_4.setText(_translate("Dialog", "旁白语速:"))
self.label_3.setText(_translate("Dialog", "旁白说话人:"))
self.label_2.setText(_translate("Dialog", "旁白脚本表格:")) self.label_2.setText(_translate("Dialog", "旁白脚本表格:"))
self.label.setText(_translate("Dialog", "视频路径:"))
self.pushButton_2.setText(_translate("Dialog", "表格路径")) self.pushButton_2.setText(_translate("Dialog", "表格路径"))
self.label_3.setText(_translate("Dialog", "旁白说话人:"))
self.label_4.setText(_translate("Dialog", "旁白语速:"))
\ No newline at end of file
"""基于OCR的旁白区间检测算法 """基于OCR的旁白区间检测算法
总体流程如下: 总体流程如下:
- 首先检测得到字幕的上下边界位置,框定大概的字幕检测范围; - 首先检测得到字幕的上下边界位置,框定大概的字幕检测范围;
- 视频每秒取3帧,并使用OCR获取字幕以及时间戳等信息; - 视频每秒取3帧,并使用OCR获取字幕以及时间戳等信息;
- 根据字幕间的时间差判断能否插入旁白以及旁白的推荐字数。 - 根据字幕间的时间差判断能否插入旁白以及旁白的推荐字数。
外部调用方式: 外部调用方式:
.. code-block:: python .. code-block:: python
from detect_with_ocr import detect_with_ocr from detect_with_ocr import detect_with_ocr
detect_with_ocr(video_path, book_path, start_time, end_time, state) detect_with_ocr(video_path, book_path, start_time, end_time, state)
""" """
import os import os
import cv2 import cv2
import numpy as np import numpy as np
from paddleocr import PaddleOCR from paddleocr import PaddleOCR
import sys import sys
print("PaddleOCR load path:", os.path.abspath(sys.modules[PaddleOCR.__module__].__file__)) print("PaddleOCR load path:", os.path.abspath(sys.modules[PaddleOCR.__module__].__file__))
import difflib import difflib
import re import re
from typing import Tuple, Union from typing import Tuple, Union
from detect_with_asr import create_sheet, write_to_sheet from detect_with_asr import create_sheet, write_to_sheet
from main_window import MainWindow, Element from main_window import MainWindow, Element
# 字幕的上下边界 # 字幕的上下边界
up_b, down_b = 0, 0 up_b, down_b = 0, 0
# 初始化ocr工具 # 初始化ocr工具
ocr = PaddleOCR(use_angle_cls=True, lang="ch", show_log=False, use_gpu=False) ocr = PaddleOCR(use_angle_cls=True, lang="ch", show_log=False, use_gpu=False)
# 正常语速为4字/秒 # 正常语速为4字/秒
normal_speed = 4 normal_speed = 4
def get_position(video_path: str, start_time: float) -> Tuple[float, float]: def get_position(video_path: str, start_time: float) -> Tuple[float, float]:
# return (885.0, 989.0) # return (885.0, 989.0)
"""根据对视频中的画面进行分析,确定字幕的位置,以便后续的字幕识别 """根据对视频中的画面进行分析,确定字幕的位置,以便后续的字幕识别
Args: Args:
video_path (str): 视频存储路径 video_path (str): 视频存储路径
start_time (float): 视频开始时间 start_time (float): 视频开始时间
Returns: Returns:
Tuple[float, float]: 字幕在整个画面中的上下边界位置 Tuple[float, float]: 字幕在整个画面中的上下边界位置
""" """
print("video_path:", video_path) print("video_path:", video_path)
video = cv2.VideoCapture(video_path) video = cv2.VideoCapture(video_path)
# print("video:", video) # print("video:", video)
subtitle_position = {} subtitle_position = {}
fps = video.get(cv2.CAP_PROP_FPS) fps = video.get(cv2.CAP_PROP_FPS)
start = int(start_time * fps) start = int(start_time * fps)
cnt = 0 cnt = 0
txt_cnt = 0 txt_cnt = 0
pre_txt = None pre_txt = None
video.set(cv2.CAP_PROP_POS_FRAMES, start) video.set(cv2.CAP_PROP_POS_FRAMES, start)
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT) * 0.6) height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT) * 0.6)
while True: while True:
_, img = video.read() _, img = video.read()
# print("img:", img) # print("img:", img)
# gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cv2.imshow('img', gray) # cv2.imshow('img', gray)
# cv2.imshow(img) # cv2.imshow(img)
cnt += 1 cnt += 1
if img is None or cnt > 10000: if img is None or cnt > 10000:
break break
if cnt % int(fps / 3) != 0: if cnt % int(fps / 3) != 0:
continue continue
img = img[height:] img = img[height:]
res = ocr.ocr(img, cls=True) res = ocr.ocr(img, cls=True)
sorted(res, key=lambda text: text[0][0][1]) sorted(res, key=lambda text: text[0][0][1])
bottom_position = None bottom_position = None
if len(res) == 0: if len(res) == 0:
continue continue
log = [] log = []
print("cnt:", cnt, "rect_num:", len(res)) print("cnt:", cnt, "rect_num:", len(res))
for x in res: for x in res:
# print("x:", x) # print("x:", x)
rect, (txt, confidence) = x rect, (txt, confidence) = x
# font_size = rect[2][1] - rect[0][1] # font_size = rect[2][1] - rect[0][1]
mid = (rect[0][0] + rect[1][0]) / 2 mid = (rect[0][0] + rect[1][0]) / 2
gradient = np.arctan(abs((rect[1][1] - rect[0][1]) / (rect[1][0] - rect[0][0]))) gradient = np.arctan(abs((rect[1][1] - rect[0][1]) / (rect[1][0] - rect[0][0])))
# 可能是字幕的文本 # 可能是字幕的文本
if confidence > 0.9 and 0.4 * img.shape[1] < mid < 0.6 * img.shape[1] and gradient < 0.1: if confidence > 0.9 and 0.4 * img.shape[1] < mid < 0.6 * img.shape[1] and gradient < 0.1:
if bottom_position is None: if bottom_position is None:
bottom_position = rect[0][1] bottom_position = rect[0][1]
# 判断是否与前一文本相同(是不是同一个字幕),非同一字幕的前提下,取对应上下边界, # 判断是否与前一文本相同(是不是同一个字幕),非同一字幕的前提下,取对应上下边界,
keys = subtitle_position.keys() keys = subtitle_position.keys()
if abs(rect[0][1] - bottom_position) < 10: if abs(rect[0][1] - bottom_position) < 10:
if pre_txt is None or pre_txt != txt: if pre_txt is None or pre_txt != txt:
txt_cnt += 1 txt_cnt += 1
pre_txt = txt pre_txt = txt
if (rect[0][0], rect[2][1]) in keys: if (rect[0][0], rect[2][1]) in keys:
subtitle_position[(rect[0][1], rect[2][1])] += 1 subtitle_position[(rect[0][1], rect[2][1])] += 1
else: else:
replace = False replace = False
for k in keys: for k in keys:
# 更新键值为最宽的上下限 # 更新键值为最宽的上下限
if abs(rect[0][1] - k[0]) + abs(rect[2][1] - k[1]) < 10: if abs(rect[0][1] - k[0]) + abs(rect[2][1] - k[1]) < 10:
new_k = min(k[0], rect[0][1]), max(k[1], rect[2][1]) new_k = min(k[0], rect[0][1]), max(k[1], rect[2][1])
if new_k != k: if new_k != k:
subtitle_position[new_k] = subtitle_position[k] subtitle_position[new_k] = subtitle_position[k]
subtitle_position[new_k] += 1 subtitle_position[new_k] += 1
subtitle_position.pop(k) subtitle_position.pop(k)
else: else:
subtitle_position[k] += 1 subtitle_position[k] += 1
replace = True replace = True
break break
if not replace: if not replace:
subtitle_position[(rect[0][1], rect[2][1])] = 1 subtitle_position[(rect[0][1], rect[2][1])] = 1
if txt_cnt == 3: if txt_cnt == 3:
break break
print(subtitle_position) print(subtitle_position)
up_bounding, down_bounding = max(subtitle_position, key=subtitle_position.get) up_bounding, down_bounding = max(subtitle_position, key=subtitle_position.get)
return up_bounding + height, down_bounding + height return up_bounding + height, down_bounding + height
def erasePunc(txt: str) -> str: def erasePunc(txt: str) -> str:
"""去除字符串中的非中文字符 """去除字符串中的非中文字符
Args: Args:
txt (str): 待处理字符串 txt (str): 待处理字符串
Returns: Returns:
str: 处理后的字符串 str: 处理后的字符串
""" """
pattern = re.compile(r'[^\u4e00-\u9fa5]') pattern = re.compile(r'[^\u4e00-\u9fa5]')
txt = re.sub(pattern, '', txt) txt = re.sub(pattern, '', txt)
return txt return txt
def string_similar(s1: str, s2: str) -> float: def string_similar(s1: str, s2: str) -> float:
"""比较字符串s1和s2的相似度,主要用于减少输出文件中相似字幕的重复 """比较字符串s1和s2的相似度,主要用于减少输出文件中相似字幕的重复
Args: Args:
s1 (str): 第一个字符串 s1 (str): 第一个字符串
s2 (str): 第二个字符串 s2 (str): 第二个字符串
Returns: Returns:
float: 字符串间的相似度 float: 字符串间的相似度
""" """
# 去除非中文字符后,再比较相似度 # 去除非中文字符后,再比较相似度
s1 = erasePunc(s1) s1 = erasePunc(s1)
s2 = erasePunc(s2) s2 = erasePunc(s2)
return difflib.SequenceMatcher(None, s1, s2).quick_ratio() return difflib.SequenceMatcher(None, s1, s2).quick_ratio()
def normalize(text: str) -> str: def normalize(text: str) -> str:
"""规范化处理文本中的一些标点符号 """规范化处理文本中的一些标点符号
Args: Args:
text (str): 待处理字符串 text (str): 待处理字符串
Returns: Returns:
str: 处理后的字符串 str: 处理后的字符串
""" """
# 将英文标点转换为中文标点 # 将英文标点转换为中文标点
E_pun = u',.!?()[]:;' E_pun = u',.!?()[]:;'
C_pun = u',。!?()【】:;' C_pun = u',。!?()【】:;'
table = {ord(f): ord(t) for f, t in zip(E_pun, C_pun)} table = {ord(f): ord(t) for f, t in zip(E_pun, C_pun)}
text = text.translate(table) text = text.translate(table)
text = text.strip(' ,。、【】_·:-@‘[;') text = text.strip(' ,。、【】_·:-@‘[;')
# 促成首尾匹配的() # 促成首尾匹配的()
if text[-1] == ')' and text[0] != '(': if text[-1] == ')' and text[0] != '(':
text = '(' + text text = '(' + text
elif text[-1] != ')' and text[0] == '(': elif text[-1] != ')' and text[0] == '(':
text = text + ')' text = text + ')'
return text return text
def detect_subtitle(img: np.ndarray) -> Union[str, None]: def detect_subtitle(img: np.ndarray) -> Union[str, None]:
"""检测当前画面得到字幕信息 """检测当前画面得到字幕信息
Args: Args:
img (np.ndarray): 当前画面 img (np.ndarray): 当前画面
Returns: Returns:
Union[str, None]: 字幕信息(没有字幕时返回None) Union[str, None]: 字幕信息(没有字幕时返回None)
""" """
subTitle = '' subTitle = ''
height = down_b - up_b height = down_b - up_b
img = img[int(up_b - height * 0.7):int(down_b + height * 0.7)] img = img[int(up_b - height * 0.7):int(down_b + height * 0.7)]
# img = cv2.resize(img, (int(img.shape[1] * 0.5), int(img.shape[0] * 0.5))) # 针对低帧率的视频做图像放大处理
res = ocr.ocr(img, cls=True) if img.shape[1] < 1000:
sorted(res, key=lambda text: text[0][0][1]) img = cv2.resize(img, (int(img.shape[1] * 1.5), int(img.shape[0] * 1.5)))
if len(res) == 0: res = ocr.ocr(img, cls=True)
return None sorted(res, key=lambda text: text[0][0][1])
possible_txt = [] if len(res) == 0:
for x in res: return None
# cv2.imshow("cut", img) possible_txt = []
# cv2.waitKey(0) for x in res:
# cv2.destroyAllWindows() # cv2.imshow("cut", img)
rect, (txt, confidence) = x # cv2.waitKey(0)
font_size = rect[2][1] - rect[0][1] # cv2.destroyAllWindows()
mid = (rect[0][0] + rect[1][0]) / 2 rect, (txt, confidence) = x
gradient = np.arctan(abs((rect[1][1] - rect[0][1]) / (rect[1][0] - rect[0][0]))) font_size = rect[2][1] - rect[0][1]
# log.append("文本:{},置信度:{},中心点:{},斜率:{},字体大小:{}".format(txt, confidence, mid / img.shape[1], gradient, mid = (rect[0][0] + rect[1][0]) / 2
# font_size)) 置信度>0.7 & 斜率<0.1 & 字幕偏移量<=25 & 字幕中心在画面宽的0.4-0.6之间 gradient = np.arctan(abs((rect[1][1] - rect[0][1]) / (rect[1][0] - rect[0][0])))
if confidence > 0.7 and gradient < 0.1 and 0.4 < mid / img.shape[1] < 0.6 and \ # log.append("文本:{},置信度:{},中心点:{},斜率:{},字体大小:{}".format(txt, confidence, mid / img.shape[1], gradient,
abs(rect[0][1] - 30) + abs(img.shape[0] - rect[2][1] - 30) <= 25: # font_size)) 置信度>0.7 & 斜率<0.1 & 字幕偏移量<=25 & 字幕中心在画面宽的0.4-0.6之间
subTitle += txt if confidence > 0.7 and gradient < 0.1 and 0.4 < mid / img.shape[1] < 0.6 and \
# 如果字幕在一行中分为两个(或以上)对话文本 abs(rect[0][1] - 30) + abs(img.shape[0] - rect[2][1] - 30) <= 25:
elif confidence > 0.85 and gradient < 0.1: subTitle += txt
if 0.3 < mid / img.shape[1] < 0.4 or 0.6 < mid / img.shape[1] < 0.7: # 如果字幕在一行中分为两个(或以上)对话文本
possible_txt.append(txt) elif confidence > 0.85 and gradient < 0.1:
if len(possible_txt) >= 2: if 0.3 < mid / img.shape[1] < 0.4 or 0.6 < mid / img.shape[1] < 0.7:
subTitle = ''.join(possible_txt) possible_txt.append(txt)
if len(subTitle) > 0: if len(possible_txt) >= 2:
return subTitle subTitle = ''.join(possible_txt)
return None if len(subTitle) > 0:
return subTitle
return None
def process_video(video_path: str, begin: float, end: float, book_path: str, sheet_name: str, state=None, mainWindow: MainWindow=None):
"""处理视频,主要完成对字幕的捕捉以及根据字幕分析得出旁白可能位置的任务
def process_video(video_path: str, begin: float, end: float, book_path: str, sheet_name: str, state=None, mainWindow: MainWindow=None):
Args: """处理视频,主要完成对字幕的捕捉以及根据字幕分析得出旁白可能位置的任务
video_path (str): 待处理视频的路径
begin (float): 电影的实际开始位置(秒) Args:
end (float): 电影除演职表外的实际结束位置(秒) video_path (str): 待处理视频的路径
book_path (str): 输出表格地址 begin (float): 电影的实际开始位置(秒)
sheet_name (str): 输出表格中的表名 end (float): 电影除演职表外的实际结束位置(秒)
state (optional): 用于通信的状态关键字. Defaults to None. book_path (str): 输出表格地址
""" sheet_name (str): 输出表格中的表名
global normal_speed state (optional): 用于通信的状态关键字. Defaults to None.
if mainWindow.projectContext.speaker_speed is not None: """
normal_speed = float(mainWindow.projectContext.speaker_speed.split('(')[1].split('字')[0]) global normal_speed
sz = len(mainWindow.projectContext.all_elements) if mainWindow.projectContext.speaker_speed is not None:
if sz == 0: normal_speed = float(mainWindow.projectContext.speaker_speed.split('(')[1].split('字')[0])
last_time = begin sz = len(mainWindow.projectContext.all_elements)
else: if sz == 0:
last_time = float(mainWindow.projectContext.all_elements[sz - 1].ed_time_sec) + 0.01 last_time = begin
print("当前使用的语速为", normal_speed) else:
if state is None: last_time = float(mainWindow.projectContext.all_elements[sz - 1].ed_time_sec) + 0.01
state = [None] print("当前使用的语速为", normal_speed)
video = cv2.VideoCapture(video_path) if state is None:
fps = video.get(cv2.CAP_PROP_FPS) state = [None]
lastSubTitle = None video = cv2.VideoCapture(video_path)
# res是在视频遍历过程中获取的字幕文件,不掺杂对旁白的分析 fps = video.get(cv2.CAP_PROP_FPS)
res = [] lastSubTitle = None
cnt = 0 # res是在视频遍历过程中获取的字幕文件,不掺杂对旁白的分析
start_time = 0 res = []
end_time = 0 cnt = 0
video.set(cv2.CAP_PROP_POS_MSEC, begin * 1000) start_time = 0
pre_state = state[0] end_time = 0
while True: video.set(cv2.CAP_PROP_POS_MSEC, begin * 1000)
_, frame = video.read() pre_state = state[0]
if frame is None: while True:
break _, frame = video.read()
cnt += 1 if frame is None:
cur_time = video.get(cv2.CAP_PROP_POS_MSEC) / 1000 break
# 判断当前帧是否已超限制 cnt += 1
if cur_time > end: cur_time = video.get(cv2.CAP_PROP_POS_MSEC) / 1000
if cur_time - end_time > 1: # 判断当前帧是否已超限制
print('--------------------------------------------------') if cur_time > end:
recommend_lens = int((cur_time - end_time) * normal_speed) if cur_time - end_time > 1:
# write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens]) print('--------------------------------------------------')
add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens]) recommend_lens = int((cur_time - end_time) * normal_speed)
# 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, '']) # 判断当前是否有字幕需要被保存下来
add_to_list(mainWindow, "字幕", [round(start_time, 3), round(end, 3), lastSubTitle, '']) if end_time < start_time:
break # write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end, 2), lastSubTitle, ''])
# 每秒取4帧画面左右 add_to_list(mainWindow, "字幕", [round(start_time, 3), round(end, 3), lastSubTitle, ''])
if cnt % int(fps / 4) == 0: break
# 更新当前工程的检测进度 # 每秒取4帧画面左右
if pre_state is None: if cnt % int(fps / 4) == 0:
state[0] = float(cur_time/ end) # 更新当前工程的检测进度
else: if pre_state is None:
state[0] = min(0.9999, float(cur_time / end)) state[0] = float(cur_time/ end)
mainWindow.projectContext.nd_process = state[0] else:
mainWindow.projectContext.last_time = cur_time state[0] = min(0.9999, float(cur_time / end))
mainWindow.projectContext.nd_process = state[0]
subTitle = detect_subtitle(frame) mainWindow.projectContext.last_time = cur_time
if subTitle is not None:
subTitle = normalize(subTitle) subTitle = detect_subtitle(frame)
# 第一次找到字幕 if subTitle is not None:
if lastSubTitle is None and subTitle is not None: subTitle = normalize(subTitle)
start_time = cur_time # 第一次找到字幕
# 字幕消失 if lastSubTitle is None and subTitle is not None:
elif lastSubTitle is not None and subTitle is None: start_time = cur_time
end_time = cur_time # 字幕消失
res.append([start_time, end_time, lastSubTitle]) elif lastSubTitle is not None and subTitle is None:
if (len(res) == 1 and res[-1][0] - last_time >= 1) or (len(res) > 1 and res[-1][0] - res[-2][1]) >= 1: end_time = cur_time
print('--------------------------------------------------') res.append([start_time, end_time, lastSubTitle])
recommend_lens = int((res[-1][0] - last_time) * normal_speed) if len(res) == 1 else int( if (len(res) == 1 and res[-1][0] - last_time >= 1) or (len(res) > 1 and res[-1][0] - res[-2][1]) >= 1:
(res[-1][0] - res[-2][1]) * normal_speed) print('--------------------------------------------------')
# write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens]) recommend_lens = int((res[-1][0] - last_time) * normal_speed) if len(res) == 1 else int(
add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens]) (res[-1][0] - res[-2][1]) * normal_speed)
print(start_time, end_time, lastSubTitle) # write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
# write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, '']) print(start_time, end_time, lastSubTitle)
add_to_list(mainWindow, "字幕", [round(start_time, 3), round(end_time, 3), lastSubTitle, ''])
elif lastSubTitle is not None and subTitle is not None: # write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
# 两句话连在一起,但是两句话不一样 add_to_list(mainWindow, "字幕", [round(start_time, 3), round(end_time, 3), lastSubTitle, ''])
if string_similar(lastSubTitle, subTitle) < 0.7: elif lastSubTitle is not None and subTitle is not None:
end_time = cur_time # 两句话连在一起,但是两句话不一样
res.append([start_time, end_time, lastSubTitle]) if string_similar(lastSubTitle, subTitle) < 0.7:
if (len(res) == 1 and res[-1][0] - last_time >= 1) or (len(res) > 1 and res[-1][0] - res[-2][1]) >= 1: end_time = cur_time
print('--------------------------------------------------') res.append([start_time, end_time, lastSubTitle])
recommend_lens = int((res[-1][0] - last_time) * normal_speed) if len(res) == 1 else int( if (len(res) == 1 and res[-1][0] - last_time >= 1) or (len(res) > 1 and res[-1][0] - res[-2][1]) >= 1:
(res[-1][0] - res[-2][1]) * normal_speed) print('--------------------------------------------------')
# write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens]) recommend_lens = int((res[-1][0] - last_time) * normal_speed) if len(res) == 1 else int(
add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens]) (res[-1][0] - res[-2][1]) * normal_speed)
print(start_time, end_time, lastSubTitle) # write_to_sheet(book_path, sheet_name, ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
# write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, '']) add_to_list(mainWindow, "旁白", ['', '', '', '插入旁白,推荐字数为%d' % recommend_lens])
add_to_list(mainWindow, "字幕", [round(start_time, 3), round(end_time, 3), lastSubTitle, '']) print(start_time, end_time, lastSubTitle)
start_time = end_time # write_to_sheet(book_path, sheet_name, [round(start_time, 2), round(end_time, 2), lastSubTitle, ''])
else: add_to_list(mainWindow, "字幕", [round(start_time, 3), round(end_time, 3), lastSubTitle, ''])
lastSubTitle = subTitle if len(subTitle) > len(lastSubTitle) else lastSubTitle start_time = end_time
continue else:
# 当前字幕与上一段字幕不一样 lastSubTitle = subTitle if len(subTitle) > len(lastSubTitle) else lastSubTitle
lastSubTitle = subTitle continue
# 当前字幕与上一段字幕不一样
def add_to_list(mainWindow: MainWindow, element_type: str, li: list): lastSubTitle = subTitle
st_time_sec, ed_time_sec, subtitle, suggest = li def add_to_list(mainWindow: MainWindow, element_type: str, li: list):
st_time_sec, ed_time_sec = str(st_time_sec), str(ed_time_sec)
# 默认使用配置文件中的语速 st_time_sec, ed_time_sec, subtitle, suggest = li
speed = mainWindow.projectContext.speaker_speed st_time_sec, ed_time_sec = str(st_time_sec), str(ed_time_sec)
aside = "" # 默认使用配置文件中的语速
i = len(mainWindow.projectContext.all_elements) speed = mainWindow.projectContext.speaker_speed
if element_type == "字幕": aside = ""
mainWindow.projectContext.subtitle_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside,speed)) i = len(mainWindow.projectContext.all_elements)
mainWindow.projectContext.all_elements.append(mainWindow.projectContext.subtitle_list[-1]) if element_type == "字幕":
else: mainWindow.projectContext.subtitle_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside,speed))
if i == 0: mainWindow.projectContext.all_elements.append(mainWindow.projectContext.subtitle_list[-1])
st_time_sec = "0.01" else:
else: if i == 0:
st_time_sec = "%.2f" % (float(mainWindow.projectContext.all_elements[i - 1].ed_time_sec) + 0.01) st_time_sec = "0.01"
else:
# 因为暂时没有用到ed_time_sec,所以直接赋值空吧 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,speed)) ed_time_sec = ""
mainWindow.projectContext.all_elements.append(mainWindow.projectContext.aside_list[-1])
mainWindow.projectContext.aside_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside,speed))
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, mainWindow: MainWindow=None):
"""使用ocr检测视频获取字幕并输出旁白推荐
def detect_with_ocr(video_path: str, book_path: str, start_time: float, end_time: float, state=None, mainWindow: MainWindow=None):
Args: """使用ocr检测视频获取字幕并输出旁白推荐
video_path (str): 待处理视频地址
book_path (str): 表格存储位置 Args:
start_time (float): 视频实际开始时间 video_path (str): 待处理视频地址
end_time (float): 视频实际结束时间 book_path (str): 表格存储位置
state (optional): 用于通信的状态关键字. Defaults to None. start_time (float): 视频实际开始时间
""" end_time (float): 视频实际结束时间
print("start and end time:", start_time, end_time) state (optional): 用于通信的状态关键字. Defaults to None.
if state is None: """
state = [None] print("start and end time:", start_time, end_time)
# if os.path.exists(book_path): if state is None:
# os.remove(book_path) state = [None]
book_name_xlsx = book_path # if os.path.exists(book_path):
sheet_name_xlsx = "旁白插入位置建议" # os.remove(book_path)
book_name_xlsx = book_path
context = mainWindow.projectContext sheet_name_xlsx = "旁白插入位置建议"
# 获取字幕在画面中的上下边界,方便在后续视频遍历过程中直接对字幕对应区域进行分析
global up_b, down_b context = mainWindow.projectContext
if context.detected: # 获取字幕在画面中的上下边界,方便在后续视频遍历过程中直接对字幕对应区域进行分析
up_b, down_b = context.caption_boundings[0], context.caption_boundings[1] global up_b, down_b
else: if context.detected:
# 此处start_time + 300是为了节省用户调整视频开始时间的功夫(强行跳过前5分钟) up_b, down_b = context.caption_boundings[0], context.caption_boundings[1]
up_b, down_b = get_position(video_path, start_time +300) else:
context.caption_boundings = [up_b, down_b] # 此处start_time + 300是为了节省用户调整视频开始时间的功夫(强行跳过前5分钟)
up_b, down_b = get_position(video_path, start_time +300)
context.detected = True context.caption_boundings = [up_b, down_b]
# 获取并构建输出信息
# table_head = [["起始时间", "终止时间", "字幕", '建议', '解说脚本']] context.detected = True
# print("create sheet at time: ", datetime.datetime.now()) # 获取并构建输出信息
# create_sheet(book_name_xlsx, sheet_name_xlsx, table_head) # table_head = [["起始时间", "终止时间", "字幕", '建议', '解说脚本']]
# print("process the total video at time: ", datetime.datetime.now()) # print("create sheet at time: ", datetime.datetime.now())
process_video(video_path, start_time, end_time, book_name_xlsx, sheet_name_xlsx, state, mainWindow) # 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, mainWindow)
if __name__ == '__main__':
path = "D:/mystudy/Eagle/accessibility_movie_1/test.mp4"
print("get_pos:", get_position(path, 0)) if __name__ == '__main__':
path = "D:/mystudy/Eagle/accessibility_movie_1/test.mp4"
print("get_pos:", get_position(path, 0))
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -21,6 +21,7 @@ class Ui_MainWindow(object): ...@@ -21,6 +21,7 @@ class Ui_MainWindow(object):
" padding: 5px;\n" " padding: 5px;\n"
"}") "}")
self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget = QtWidgets.QWidget(MainWindow)
# self.centralwidget.setStyleSheet("font: 9pt \"黑体\";")
self.centralwidget.setObjectName("centralwidget") self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
...@@ -206,6 +207,7 @@ class Ui_MainWindow(object): ...@@ -206,6 +207,7 @@ class Ui_MainWindow(object):
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.all_tab) self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.all_tab)
self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.all_tableWidget = QtWidgets.QTableWidget(self.all_tab) self.all_tableWidget = QtWidgets.QTableWidget(self.all_tab)
# self.all_tableWidget.setStyleSheet("font: 9pt \"微软雅黑\";")
self.all_tableWidget.setObjectName("all_tableWidget") self.all_tableWidget.setObjectName("all_tableWidget")
self.all_tableWidget.setColumnCount(0) self.all_tableWidget.setColumnCount(0)
self.all_tableWidget.setRowCount(0) self.all_tableWidget.setRowCount(0)
...@@ -240,6 +242,7 @@ class Ui_MainWindow(object): ...@@ -240,6 +242,7 @@ class Ui_MainWindow(object):
self.shuiping.setStretch(1, 5) self.shuiping.setStretch(1, 5)
self.verticalLayout.addLayout(self.shuiping) self.verticalLayout.addLayout(self.shuiping)
self.verticalWidget_2 = QtWidgets.QWidget(self.centralwidget) self.verticalWidget_2 = QtWidgets.QWidget(self.centralwidget)
# self.verticalWidget_2.setStyleSheet("font: 9pt \"微软雅黑\";")
self.verticalWidget_2.setObjectName("verticalWidget_2") self.verticalWidget_2.setObjectName("verticalWidget_2")
self.chuizhi = QtWidgets.QVBoxLayout(self.verticalWidget_2) self.chuizhi = QtWidgets.QVBoxLayout(self.verticalWidget_2)
self.chuizhi.setObjectName("chuizhi") self.chuizhi.setObjectName("chuizhi")
...@@ -330,18 +333,26 @@ class Ui_MainWindow(object): ...@@ -330,18 +333,26 @@ class Ui_MainWindow(object):
self.statusbar.setObjectName("statusbar") self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar) MainWindow.setStatusBar(self.statusbar)
self.setting = QtWidgets.QAction(MainWindow) self.setting = QtWidgets.QAction(MainWindow)
# font = QtGui.QFont()
# font.setFamily("微软雅黑")
# self.setting.setFont(font)
self.setting.setObjectName("setting") self.setting.setObjectName("setting")
self.action_open_project = QtWidgets.QAction(MainWindow) self.action_open_project = QtWidgets.QAction(MainWindow)
# self.action_open_project.setFont(font)
self.action_open_project.setObjectName("action_open_project") self.action_open_project.setObjectName("action_open_project")
self.import_movie = QtWidgets.QAction(MainWindow) self.import_movie = QtWidgets.QAction(MainWindow)
# self.import_movie.setFont(font)
self.import_movie.setObjectName("import_movie") 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.action_save = QtWidgets.QAction(MainWindow) self.action_save = QtWidgets.QAction(MainWindow)
# self.action_save.setFont(font)
self.action_save.setObjectName("action_save") self.action_save.setObjectName("action_save")
self.action_undo = QtWidgets.QAction(MainWindow) self.action_undo = QtWidgets.QAction(MainWindow)
# self.action_undo.setFont(font)
self.action_undo.setObjectName("action_undo") self.action_undo.setObjectName("action_undo")
self.action_redo = QtWidgets.QAction(MainWindow) self.action_redo = QtWidgets.QAction(MainWindow)
# self.action_redo.setFont(font)
self.action_redo.setObjectName("action_redo") self.action_redo.setObjectName("action_redo")
self.action_3 = QtWidgets.QAction(MainWindow) self.action_3 = QtWidgets.QAction(MainWindow)
self.action_3.setObjectName("action_3") self.action_3.setObjectName("action_3")
...@@ -352,10 +363,12 @@ class Ui_MainWindow(object): ...@@ -352,10 +363,12 @@ class Ui_MainWindow(object):
self.action_operate = QtWidgets.QAction(MainWindow) self.action_operate = QtWidgets.QAction(MainWindow)
self.action_operate.setObjectName("action_operate") self.action_operate.setObjectName("action_operate")
self.action_export = QtWidgets.QAction(MainWindow) self.action_export = QtWidgets.QAction(MainWindow)
# self.action_export.setFont(font)
self.action_export.setObjectName("action_export") self.action_export.setObjectName("action_export")
self.action_insert_aside_from_now = QtWidgets.QAction(MainWindow) self.action_insert_aside_from_now = QtWidgets.QAction(MainWindow)
self.action_insert_aside_from_now.setObjectName("action_insert_aside_from_now") self.action_insert_aside_from_now.setObjectName("action_insert_aside_from_now")
self.action_create = QtWidgets.QAction(MainWindow) self.action_create = QtWidgets.QAction(MainWindow)
# self.action_create.setFont(font)
self.action_create.setObjectName("action_create") self.action_create.setObjectName("action_create")
self.menu.addAction(self.action_create) self.menu.addAction(self.action_create)
self.menu.addAction(self.action_open_project) self.menu.addAction(self.action_open_project)
......
...@@ -174,6 +174,7 @@ class ProjectContext: ...@@ -174,6 +174,7 @@ class ProjectContext:
return return
with open(self.conf_path, 'r', encoding='utf8') as f: with open(self.conf_path, 'r', encoding='utf8') as f:
info = json.load(f) info = json.load(f)
# print(json.dumps(info, ensure_ascii=False, indent=4))
self.video_path = info["video_path"] self.video_path = info["video_path"]
self.excel_path = info["excel_path"] self.excel_path = info["excel_path"]
self.speaker_info = info["speaker_info"]["speaker_id"] self.speaker_info = info["speaker_info"]["speaker_id"]
...@@ -207,8 +208,7 @@ class ProjectContext: ...@@ -207,8 +208,7 @@ class ProjectContext:
} }
} }
f.write(json.dumps(info)) f.write(json.dumps(info))
def setVideoPath(self, video_path): def setVideoPath(self, video_path):
self.video_path = video_path self.video_path = video_path
......
...@@ -141,7 +141,7 @@ class Operation_Dialog(QDialog, Ui_Dialog): ...@@ -141,7 +141,7 @@ class Operation_Dialog(QDialog, Ui_Dialog):
assert start_time_f < end_time_f assert start_time_f < end_time_f
if row_number < rowCount: if row_number < rowCount:
# 要求结束时间在下一行的起始时间前面,对增加和修改都适用 # 要求结束时间在下一行的起始时间前面,对增加和修改都适用
assert float(self.mainWindow.projectContext.all_elements[list_idx+1].st_time_sec) > end_time_f assert float(self.mainWindow.projectContext.all_elements[list_idx+1].st_time_sec) >= end_time_f
# 要求起始时间在上一行后面,在下一行前面 # 要求起始时间在上一行后面,在下一行前面
if self.comboBox_2.currentText() == "增加一行": if self.comboBox_2.currentText() == "增加一行":
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'operation_dialog.ui' # Form implementation generated from reading ui file 'd:\AddCaption\cur_version\accessibility_movie_2\operation_dialog.ui'
# #
# Created by: PyQt5 UI code generator 5.12 # Created by: PyQt5 UI code generator 5.15.4
# #
# WARNING! All changes made in this file will be lost! # WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
...@@ -12,52 +14,20 @@ from PyQt5 import QtCore, QtGui, QtWidgets ...@@ -12,52 +14,20 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object): class Ui_Dialog(object):
def setupUi(self, Dialog): def setupUi(self, Dialog):
Dialog.setObjectName("Dialog") Dialog.setObjectName("Dialog")
Dialog.resize(724, 437) Dialog.resize(724, 502)
self.gridLayout = QtWidgets.QGridLayout(Dialog) self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.gridLayout.setObjectName("gridLayout") self.gridLayout.setObjectName("gridLayout")
self.label_14 = QtWidgets.QLabel(Dialog) self.label_11 = QtWidgets.QLabel(Dialog)
self.label_14.setObjectName("label_14") self.label_11.setObjectName("label_11")
self.gridLayout.addWidget(self.label_14, 5, 3, 1, 1) self.gridLayout.addWidget(self.label_11, 6, 2, 1, 1)
self.comboBox_3 = QtWidgets.QComboBox(Dialog) self.comboBox_3 = QtWidgets.QComboBox(Dialog)
self.comboBox_3.setEnabled(True) self.comboBox_3.setEnabled(True)
self.comboBox_3.setEditable(False) self.comboBox_3.setEditable(False)
self.comboBox_3.setObjectName("comboBox_3") self.comboBox_3.setObjectName("comboBox_3")
self.gridLayout.addWidget(self.comboBox_3, 5, 4, 1, 1) self.gridLayout.addWidget(self.comboBox_3, 6, 4, 1, 1)
self.label_11 = QtWidgets.QLabel(Dialog)
self.label_11.setObjectName("label_11")
self.gridLayout.addWidget(self.label_11, 5, 2, 1, 1)
self.label_9 = QtWidgets.QLabel(Dialog) self.label_9 = QtWidgets.QLabel(Dialog)
self.label_9.setObjectName("label_9") self.label_9.setObjectName("label_9")
self.gridLayout.addWidget(self.label_9, 3, 2, 1, 1) self.gridLayout.addWidget(self.label_9, 3, 2, 1, 1)
self.lineEdit_6 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_6.setEnabled(True)
self.lineEdit_6.setObjectName("lineEdit_6")
self.gridLayout.addWidget(self.lineEdit_6, 5, 1, 1, 1)
self.lineEdit_4 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_4.setEnabled(True)
self.lineEdit_4.setObjectName("lineEdit_4")
self.gridLayout.addWidget(self.lineEdit_4, 4, 1, 1, 1)
self.pickEndPos = QtWidgets.QPushButton(Dialog)
self.pickEndPos.setObjectName("pickEndPos")
self.gridLayout.addWidget(self.pickEndPos, 3, 3, 1, 1)
self.pickStartPos = QtWidgets.QPushButton(Dialog)
self.pickStartPos.setObjectName("pickStartPos")
self.gridLayout.addWidget(self.pickStartPos, 2, 3, 1, 1)
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setObjectName("label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
self.label = QtWidgets.QLabel(Dialog)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.pushButton_3 = QtWidgets.QPushButton(Dialog)
self.pushButton_3.setObjectName("pushButton_3")
self.gridLayout.addWidget(self.pushButton_3, 1, 3, 1, 2)
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.label_8 = QtWidgets.QLabel(Dialog)
self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.label_8, 2, 2, 1, 1)
self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.label_2 = QtWidgets.QLabel(Dialog) self.label_2 = QtWidgets.QLabel(Dialog)
...@@ -70,9 +40,41 @@ class Ui_Dialog(object): ...@@ -70,9 +40,41 @@ class Ui_Dialog(object):
self.label_13.setObjectName("label_13") self.label_13.setObjectName("label_13")
self.verticalLayout.addWidget(self.label_13) self.verticalLayout.addWidget(self.label_13)
self.gridLayout.addLayout(self.verticalLayout, 1, 2, 1, 1) self.gridLayout.addLayout(self.verticalLayout, 1, 2, 1, 1)
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setObjectName("label_4")
self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1)
self.pickStartPos = QtWidgets.QPushButton(Dialog)
self.pickStartPos.setObjectName("pickStartPos")
self.gridLayout.addWidget(self.pickStartPos, 2, 3, 1, 1)
self.label_10 = QtWidgets.QLabel(Dialog)
self.label_10.setObjectName("label_10")
self.gridLayout.addWidget(self.label_10, 4, 2, 1, 1)
self.label_14 = QtWidgets.QLabel(Dialog)
self.label_14.setObjectName("label_14")
self.gridLayout.addWidget(self.label_14, 6, 3, 1, 1)
self.label_7 = QtWidgets.QLabel(Dialog) self.label_7 = QtWidgets.QLabel(Dialog)
self.label_7.setObjectName("label_7") self.label_7.setObjectName("label_7")
self.gridLayout.addWidget(self.label_7, 5, 0, 1, 1) self.gridLayout.addWidget(self.label_7, 6, 0, 1, 1)
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.pickEndPos = QtWidgets.QPushButton(Dialog)
self.pickEndPos.setObjectName("pickEndPos")
self.gridLayout.addWidget(self.pickEndPos, 3, 3, 1, 1)
self.lineEdit_6 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_6.setEnabled(True)
self.lineEdit_6.setObjectName("lineEdit_6")
self.gridLayout.addWidget(self.lineEdit_6, 6, 1, 1, 1)
self.lineEdit_4 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_4.setEnabled(True)
self.lineEdit_4.setObjectName("lineEdit_4")
self.gridLayout.addWidget(self.lineEdit_4, 4, 1, 1, 1)
self.label = QtWidgets.QLabel(Dialog)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.pushButton_3 = QtWidgets.QPushButton(Dialog)
self.pushButton_3.setObjectName("pushButton_3")
self.gridLayout.addWidget(self.pushButton_3, 1, 3, 1, 2)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setEnabled(False) self.buttonBox.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
...@@ -87,10 +89,31 @@ class Ui_Dialog(object): ...@@ -87,10 +89,31 @@ class Ui_Dialog(object):
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setCenterButtons(False) self.buttonBox.setCenterButtons(False)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 7, 4, 1, 1) self.gridLayout.addWidget(self.buttonBox, 8, 4, 1, 1)
self.label_10 = QtWidgets.QLabel(Dialog) self.label_8 = QtWidgets.QLabel(Dialog)
self.label_10.setObjectName("label_10") self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.label_10, 4, 2, 1, 1) self.gridLayout.addWidget(self.label_8, 2, 2, 1, 1)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.pushButton_2 = QtWidgets.QPushButton(Dialog)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout_2.addWidget(self.pushButton_2)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem)
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout_2.addWidget(self.pushButton)
self.horizontalLayout_2.setStretch(0, 1)
self.horizontalLayout_2.setStretch(1, 1)
self.horizontalLayout_2.setStretch(2, 1)
self.gridLayout.addLayout(self.horizontalLayout_2, 8, 1, 1, 2)
self.label_6 = QtWidgets.QLabel(Dialog)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.label_5 = QtWidgets.QLabel(Dialog)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
self.comboBox = QtWidgets.QComboBox(Dialog) self.comboBox = QtWidgets.QComboBox(Dialog)
...@@ -100,42 +123,29 @@ class Ui_Dialog(object): ...@@ -100,42 +123,29 @@ class Ui_Dialog(object):
self.comboBox.addItem("") self.comboBox.addItem("")
self.comboBox.addItem("") self.comboBox.addItem("")
self.horizontalLayout.addWidget(self.comboBox) self.horizontalLayout.addWidget(self.comboBox)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem) self.horizontalLayout.addItem(spacerItem1)
self.horizontalLayout.setStretch(0, 1) self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 1) self.horizontalLayout.setStretch(1, 1)
self.gridLayout.addLayout(self.horizontalLayout, 0, 1, 1, 1) self.gridLayout.addLayout(self.horizontalLayout, 0, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(Dialog)
self.label_5.setObjectName("label_5")
self.gridLayout.addWidget(self.label_5, 4, 0, 1, 1)
self.timeEdit = QtWidgets.QTimeEdit(Dialog)
self.timeEdit.setCurrentSection(QtWidgets.QDateTimeEdit.MinuteSection)
self.timeEdit.setCurrentSectionIndex(1)
self.timeEdit.setObjectName("timeEdit")
self.gridLayout.addWidget(self.timeEdit, 2, 1, 1, 1)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.pushButton_2 = QtWidgets.QPushButton(Dialog)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout_2.addWidget(self.pushButton_2)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem1)
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout_2.addWidget(self.pushButton)
self.horizontalLayout_2.setStretch(0, 1)
self.horizontalLayout_2.setStretch(1, 1)
self.gridLayout.addLayout(self.horizontalLayout_2, 7, 1, 1, 2)
self.comboBox_2 = QtWidgets.QComboBox(Dialog) self.comboBox_2 = QtWidgets.QComboBox(Dialog)
self.comboBox_2.setObjectName("comboBox_2") self.comboBox_2.setObjectName("comboBox_2")
self.comboBox_2.addItem("") self.comboBox_2.addItem("")
self.comboBox_2.addItem("") self.comboBox_2.addItem("")
self.comboBox_2.addItem("") self.comboBox_2.addItem("")
self.gridLayout.addWidget(self.comboBox_2, 0, 2, 1, 1) self.gridLayout.addWidget(self.comboBox_2, 0, 2, 1, 1)
self.lineEdit_5 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_5.setEnabled(True)
self.lineEdit_5.setObjectName("lineEdit_5")
self.gridLayout.addWidget(self.lineEdit_5, 5, 1, 1, 1)
self.lineEdit = QtWidgets.QLineEdit(Dialog) self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setObjectName("lineEdit") self.lineEdit.setObjectName("lineEdit")
self.gridLayout.addWidget(self.lineEdit, 1, 1, 1, 1) self.gridLayout.addWidget(self.lineEdit, 1, 1, 1, 1)
self.timeEdit = QtWidgets.QTimeEdit(Dialog)
self.timeEdit.setCurrentSection(QtWidgets.QDateTimeEdit.MinuteSection)
self.timeEdit.setCurrentSectionIndex(1)
self.timeEdit.setObjectName("timeEdit")
self.gridLayout.addWidget(self.timeEdit, 2, 1, 1, 1)
self.timeEdit_2 = QtWidgets.QTimeEdit(Dialog) self.timeEdit_2 = QtWidgets.QTimeEdit(Dialog)
self.timeEdit_2.setCurrentSection(QtWidgets.QDateTimeEdit.SecondSection) self.timeEdit_2.setCurrentSection(QtWidgets.QDateTimeEdit.SecondSection)
self.timeEdit_2.setCurrentSectionIndex(2) self.timeEdit_2.setCurrentSectionIndex(2)
...@@ -148,30 +158,29 @@ class Ui_Dialog(object): ...@@ -148,30 +158,29 @@ class Ui_Dialog(object):
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog")) Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label_14.setText(_translate("Dialog", "语速:"))
self.label_11.setText(_translate("Dialog", "*请填文字")) self.label_11.setText(_translate("Dialog", "*请填文字"))
self.label_9.setText(_translate("Dialog", "*请填数字,最多保留两位小数")) self.label_9.setText(_translate("Dialog", "*请填数字,最多保留两位小数"))
self.pickEndPos.setText(_translate("Dialog", "取当前位置")) self.label_2.setText(_translate("Dialog", "行(如果操作是增加,则在该行后面增加)"))
self.pickStartPos.setText(_translate("Dialog", "取当前位置")) self.label_13.setText(_translate("Dialog", "*需要填在【字幕旁白】页面中的行数"))
self.label_4.setText(_translate("Dialog", "结束时间:")) self.label_4.setText(_translate("Dialog", "结束时间:"))
self.pickStartPos.setText(_translate("Dialog", "取当前位置"))
self.label_10.setText(_translate("Dialog", "*请填文字"))
self.label_14.setText(_translate("Dialog", "语速:"))
self.label_7.setText(_translate("Dialog", "旁白:"))
self.label_3.setText(_translate("Dialog", "起始时间:"))
self.pickEndPos.setText(_translate("Dialog", "取当前位置"))
self.label.setText(_translate("Dialog", "我想操作第")) self.label.setText(_translate("Dialog", "我想操作第"))
self.pushButton_3.setText(_translate("Dialog", "填充\n" self.pushButton_3.setText(_translate("Dialog", "填充\n"
"行信息")) "行信息"))
self.label_3.setText(_translate("Dialog", "起始时间:"))
self.label_8.setText(_translate("Dialog", "*请填数字,最多保留两位小数")) self.label_8.setText(_translate("Dialog", "*请填数字,最多保留两位小数"))
self.label_2.setText(_translate("Dialog", "行(如果操作是增加,则在该行后面增加)"))
self.label_13.setText(_translate("Dialog", "*需要填在【字幕旁白】页面中的行数"))
self.label_7.setText(_translate("Dialog", "旁白:"))
self.label_10.setText(_translate("Dialog", "*请填文字"))
self.comboBox.setItemText(0, _translate("Dialog", "字幕"))
self.comboBox.setItemText(1, _translate("Dialog", "旁白"))
self.label_5.setText(_translate("Dialog", "字幕:"))
self.timeEdit.setDisplayFormat(_translate("Dialog", "hh:mm:ss.zzz"))
self.pushButton_2.setText(_translate("Dialog", "修改")) self.pushButton_2.setText(_translate("Dialog", "修改"))
self.pushButton.setText(_translate("Dialog", "检测")) self.pushButton.setText(_translate("Dialog", "检测"))
self.label_6.setText(_translate("Dialog", "推荐字数:"))
self.label_5.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(0, _translate("Dialog", "增加一行"))
self.comboBox_2.setItemText(1, _translate("Dialog", "修改一行")) self.comboBox_2.setItemText(1, _translate("Dialog", "修改一行"))
self.comboBox_2.setItemText(2, _translate("Dialog", "删除一行")) self.comboBox_2.setItemText(2, _translate("Dialog", "删除一行"))
self.timeEdit.setDisplayFormat(_translate("Dialog", "hh:mm:ss.zzz"))
self.timeEdit_2.setDisplayFormat(_translate("Dialog", "hh:mm:ss.zzz")) self.timeEdit_2.setDisplayFormat(_translate("Dialog", "hh:mm:ss.zzz"))
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