Commit 464b8e26 authored by smile2019's avatar smile2019

Merge remote-tracking branch 'refs/remotes/origin/feat_1' into feat_1

parents 72383c7f 7db705f9
......@@ -9,4 +9,8 @@ dist
build
log
product_test
res/ffmpeg-4.3.1/bin/output.mp4
res/ffmpeg-4.3.1/bin/qiji_local.mp4
venv/
venv37/
shenming_test
\ No newline at end of file
......@@ -78,7 +78,8 @@ def predict_long_audio_with_paddle(wav_path, pre_time, book_name, sheet_name, st
(time_stamps[i][0] + pre_time) * normal_speed)
print("插入旁白,推荐字数为%d" % recommend_lens)
# narratages.append(["", "", "", "插入旁白,推荐字数为%d" % recommend_lens])
write_to_sheet(book_name, sheet_name, ["", "", "", "插入旁白,推荐字数为%d" % recommend_lens])
# write_to_sheet(book_name, sheet_name, ["", "", "", "插入旁白,推荐字数为%d" % recommend_lens])
write_to_sheet(book_name, sheet_name, ["", "", "", "%d" % recommend_lens])
# narratages.append([round(time_stamps[i][0] + pre_time, 2), round(time_stamps[i][1] + pre_time, 2),
# text, ''])
write_to_sheet(book_name, sheet_name,
......
This diff is collapsed.
......@@ -16,14 +16,23 @@ from prompt_dialog import Prompt_Dialog
class Create_Dialog(QDialog, Ui_Dialog):
init_project_signal = pyqtSignal(str)
def __init__(self):
def __init__(self, mainWindow):
super(Create_Dialog, self).__init__()
self.mainWindow = mainWindow
self.setupUi(self)
self.setWindowTitle("新建工程")
self.get_dir.clicked.connect(self.choose_root)
self.confirm.clicked.connect(self.create_project)
self.get_video_dir.clicked.connect(self.choose_video)
self.prompt_dialog = Prompt_Dialog()
self.cancel.clicked.connect(self.close_dialog)
self.video_path = None
def choose_video(self):
path = QFileDialog.getOpenFileUrl(self, "选择待导入视频", QUrl(
os.getcwd()), "Video Files(*.mp4 *.rmvb *mkv *avi *.);; 所有文件(*.*)")[0]
self.video_input.setText(path.path()[1:])
self.video_path = path
def choose_root(self):
"""选择存放新工程的文件夹
......@@ -54,6 +63,7 @@ class Create_Dialog(QDialog, Ui_Dialog):
self.prompt_dialog.show_with_msg("请输入工程名称")
else:
self.prompt_dialog.show_with_msg("请输入合法文件夹路径")
self.mainWindow.play_video(self.video_path)
def close_dialog(self):
"""关闭窗口
......
......@@ -29,6 +29,13 @@ class Ui_Dialog(object):
self.get_dir.setObjectName("get_dir")
self.gridLayout.addWidget(self.get_dir, 0, 2, 1, 1)
self.video_input = QtWidgets.QLineEdit(Dialog)
self.video_input.setObjectName("video_input")
self.gridLayout.addWidget(self.video_input, 2, 1, 1, 1)
self.get_video_dir = QtWidgets.QPushButton(Dialog)
self.get_video_dir.setObjectName("get_video_dir")
self.gridLayout.addWidget(self.get_video_dir, 2, 2, 1, 1)
self.rootLabel = QtWidgets.QLabel(Dialog)
self.rootLabel.setObjectName("rootLabel")
self.gridLayout.addWidget(self.rootLabel, 0, 0, 1, 1)
......@@ -37,6 +44,10 @@ class Ui_Dialog(object):
self.nameLabel.setObjectName("nameLabel")
self.gridLayout.addWidget(self.nameLabel, 1, 0, 1, 1)
self.videoPath = QtWidgets.QLabel(Dialog)
self.videoPath.setObjectName("videoPath")
self.gridLayout.addWidget(self.videoPath, 2, 0, 1, 1)
self.gridLayout.addWidget(self.name_input, 1, 1, 1, 1)
self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
......@@ -68,6 +79,8 @@ class Ui_Dialog(object):
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.nameLabel.setText(_translate("Dialog", "工程名称"))
self.rootLabel.setText(_translate("Dialog", "目标路径"))
self.videoPath.setText(_translate("Dialog", "视频路径"))
self.get_dir.setText(_translate("Dialog", "打开文件夹"))
self.get_video_dir.setText(_translate("Dialog", "导入视频"))
self.confirm.setText(_translate("Dialog", "确认"))
self.cancel.setText(_translate("Dialog", "取消"))
@echo on
%1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close) && exit
@REM @echo on
@REM %1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close) && exit
cd /d %~dp0
IF EXIST "%PROGRAMFILES(X86)%" (GOTO 64BIT) ELSE (GOTO 32BIT)
......@@ -16,6 +16,7 @@ GOTO END
:END
c:
cd C:\LavFilters\
call install_audio.bat
call install_splitter.bat
......
......@@ -98,7 +98,7 @@ def detect_with_asr(video_path: str, book_path: str, start_time=0, end_time=-1,
os.remove(book_path)
book_name_xlsx = book_path
sheet_name_xlsx = "旁白插入位置建议"
table_head = [["起始时间", "终止时间", "字幕", '建议', '解说脚本']]
table_head = [["起始时间", "终止时间", "字幕", '建议旁白字数', '解说脚本']]
create_sheet(book_name_xlsx, sheet_name_xlsx, table_head)
sys.path.append("PaddlePaddle_DeepSpeech2")
......
This diff is collapsed.
{
"user_name":"盲文出版社",
"dd_url_prefix":"https://oapi.dingtalk.com/robot/send?access_token=a7e6b223bc0a6e4b5e3f64b1570d0c884db0d833592f5e84b020c2896130d659",
"secret":"SEC252452789bc17cfb1e6c973f837426fa0f9fd50c8793239c070e9d3c021d8109"
}
\ No newline at end of file
......@@ -9,35 +9,44 @@ import base64
import hashlib
import urllib.parse
user_name = "盲文出版社"
dd_url_prefix = "https://oapi.dingtalk.com/robot/send?access_token=a7e6b223bc0a6e4b5e3f64b1570d0c884db0d833592f5e84b020c2896130d659"
# dd_url_prefix = "https://oapi.dingtalk.com/robot/send?access_token=12a5e64b24e7345fed2415c5c2f9101180763e327b21727cd35fdaa3fb274e74"
secret = 'SEC252452789bc17cfb1e6c973f837426fa0f9fd50c8793239c070e9d3c021d8109'
# secret = "SECb5d68b27bd2e4694667d36c0f91336f3641b3287b945906a83997353f961d415"
with open("./ding_notify.conf", "r", encoding="utf-8") as f:
json_obj = json.load(f)
# user_name = "盲文出版社"
# dd_url_prefix = "https://oapi.dingtalk.com/robot/send?access_token=a7e6b223bc0a6e4b5e3f64b1570d0c884db0d833592f5e84b020c2896130d659"
# # dd_url_prefix = "https://oapi.dingtalk.com/robot/send?access_token=12a5e64b24e7345fed2415c5c2f9101180763e327b21727cd35fdaa3fb274e74"
# secret = 'SEC252452789bc17cfb1e6c973f837426fa0f9fd50c8793239c070e9d3c021d8109'
# # secret = "SECb5d68b27bd2e4694667d36c0f91336f3641b3287b945906a83997353f961d415"
user_name = json_obj["user_name"]
dd_url_prefix = json_obj["dd_url_prefix"]
secret = json_obj["secret"]
def notify(err):
timestamp = str(round(time.time() * 1000))
secret_enc = secret.encode('utf-8')
string_to_sign = '{}\n{}'.format(timestamp, secret)
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
print(timestamp)
print(sign)
dd_url = dd_url_prefix + "&timestamp=" + timestamp + "&sign=" + sign
h = {"Content-Type": "application/json"}
d = {
"msgtype": "markdown",
"markdown": {
"title": "msg",
"text": "| 用户名称:%s \n" % (user_name) +
"\n" +
"| 异常时间:%s \n" % (time.strftime('%Y:%m:%d %H:%M:%S', time.localtime(int(time.time())))) +
"\n" +
"| 异常信息:%s \n" % (err)
try:
timestamp = str(round(time.time() * 1000))
secret_enc = secret.encode('utf-8')
string_to_sign = '{}\n{}'.format(timestamp, secret)
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
print(timestamp)
print(sign)
dd_url = dd_url_prefix + "&timestamp=" + timestamp + "&sign=" + sign
h = {"Content-Type": "application/json"}
d = {
"msgtype": "markdown",
"markdown": {
"title": "msg",
"text": "| 用户名称:%s \n" % (user_name) +
"\n" +
"| 异常时间:%s \n" % (time.strftime('%Y:%m:%d %H:%M:%S', time.localtime(int(time.time())))) +
"\n" +
"| 异常信息:%s \n" % (err)
}
}
}
r = requests.post(dd_url, json.dumps(d), headers=h)
print(r.status_code)
print(r.text)
\ No newline at end of file
r = requests.post(dd_url, json.dumps(d), headers=h)
print(r.status_code)
print(r.text)
except Exception as e:
print("ding notify err")
print(e)
\ No newline at end of file
......@@ -4,6 +4,8 @@ import openpyxl
from management import Element
from utils import reverse_time_to_seconds, get_seconds
def read_xls(file_path):
print("read_xls")
elements = []
......@@ -26,20 +28,20 @@ def read_xls(file_path):
cell_value = str(cell_value) if cell_value != None else ""
# print(cell_value)
if col_index == 0:
start_time = cell_value if cell_value != None else ""
start_time = get_seconds(cell_value) if cell_value != None else ""
if col_index == 1:
end_time = get_seconds(cell_value) if cell_value != None else ""
if col_index == 2:
end_time = cell_value if cell_value != None else ""
if col_index == 4:
subtitle = cell_value if cell_value != None else ""
if col_index == 5:
if col_index == 3:
if cell_value == None or cell_value == "":
break
suggest = cell_value if cell_value != None else ""
if col_index == 6:
if col_index == 4:
if cell_value == None or cell_value == "":
break
aside = cell_value if cell_value != None else ""
if col_index == 7:
if col_index == 5:
speed = cell_value if cell_value != None else ""
col_index = col_index + 1
if suggest != "" and aside != "":
......@@ -71,33 +73,39 @@ def read_xlsx(file_path):
cell_value = str(cell_value) if cell_value != None else ""
# print(cell_value)
if col_index == 0:
start_time = cell_value if cell_value != None else ""
start_time = get_seconds(cell_value) if cell_value != None else ""
if col_index == 1:
end_time = get_seconds(cell_value) if cell_value != None else ""
if col_index == 2:
end_time = cell_value if cell_value != None else ""
if col_index == 4:
subtitle = cell_value if cell_value != None else ""
if col_index == 5:
if col_index == 3:
if cell_value == None or cell_value == "":
break
suggest = cell_value if cell_value != None else ""
if col_index == 6:
if col_index == 4:
if cell_value == None or cell_value == "":
break
aside = cell_value if cell_value != None else ""
if col_index == 7:
if col_index == 5:
speed = cell_value if cell_value != None else ""
col_index = col_index + 1
if suggest != "" and aside != "":
if suggest != None and suggest != "" and aside != None and aside != "":
new_element = Element(start_time, end_time, subtitle, suggest, aside, speed)
# new_element.print_self()
new_element.print_self()
elements.append(new_element)
checkLength(elements)
print("element size:")
print(len(elements))
return elements
def checkLength(elements):
for element in elements:
if int("".join(filter(str.isdigit, element.suggest))) < len(element.aside):
# if int("".join(filter(str.isdigit, element.suggest))) < len(element.aside):
# raise Exception("旁白字数没有按照推荐要求")
if int(element.suggest.split("/")[1]) < len(element.aside):
raise Exception("旁白字数没有按照推荐要求")
else:
element.suggest = str(len(element.aside)) + "/" + element.suggest.split("/")[1]
# elements = read_xlsx("C:/Users/AIA/Desktop/1/121/1.xlsx")
# print(len(elements))
......
import subprocess
import os
import subprocess
import math
import time
import shutil
def calculate_audio_volume(file_path):
# 使用FFmpeg获取音频分贝值
command = [
'res/ffmpeg-4.3.1/bin/ffmpeg', '-i', file_path,
'-af', 'volumedetect', '-f', 'null', '-'
]
print(command)
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
output = result.stderr
# 从输出中解析分贝值
for line in output.split('\n'):
if 'mean_volume' in line:
print(line)
a = float(line.split(':')[1].strip().split("d")[0].strip())
print(a)
# mean_volume = float((line.split(':')[1].strip()).split(" ")[0])
return a
return None
# def adjust_audio_volume(input_file, output_file, multiplier):
# # 使用FFmpeg将音频音量设置为给定倍数
# command = [
# 'ffmpeg', '-i', input_file,
# '-af', f'volume={multiplier}*', output_file
# ]
# subprocess.run(command)
def adjust_audio_volume(input_file, volume_adjustment):
temp_path = "./temp.wav"
command = [
"res/ffmpeg-4.3.1/bin/ffmpeg",
"-i", input_file,
"-af", f"volume={volume_adjustment}",
"-y", # 覆盖输出文件,加上此选项
temp_path # 输出文件与输入文件相同
]
subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
os.remove(input_file)
# os.rename(temp_path, input_file)
shutil.move(temp_path, input_file)
def cg_wav(first_file_path, second_file_path, rate):
try:
print(first_file_path, second_file_path, str(rate))
# 计算第一个文件的音量
first_file_volume = calculate_audio_volume(first_file_path)
if first_file_volume is not None:
# 计算第二个文件的音量并计算倍数
second_file_volume = calculate_audio_volume(second_file_path)
if second_file_volume is not None:
# volume_multiplier = 10 ** ((first_file_volume - second_file_volume) / 20) # 转换为幅度倍数
# # 调整第二个文件的音量
# adjusted_output_file = 'path/to/output/adjusted_file.wav'
# 计算第二个文件应改为自身的大小的倍数
volume_difference_db = first_file_volume - second_file_volume
volume_difference_linear = 10 ** (volume_difference_db / 20) # 转换为线性倍数
adjusted_multiplier = volume_difference_linear * rate
adjust_audio_volume(second_file_path, adjusted_multiplier)
else:
print("无法计算第二个文件的音量")
else:
print("无法计算第一个文件的音量")
except Exception as e:
print("cg_wav err")
print(e)
# cg_wav("C:/Users/Administrator/Desktop/无障碍电影/fuiii0000/output/0.01.wav","C:/Users/Administrator/Desktop/无障碍电影/fuiii0000\output\0.01.wav",0.26)
# calculate_audio_volume("./0.01.wav")
# adjust_audio_volume("./0.01.wav",1.335)
# calculate_audio_volume("./0.01.wav")
# def test(projectContext):
# from split_wav import extract_audio
# video_path = projectContext.video_path
# output_dir = os.path.join(projectContext.project_base_dir, "output")
# extract_audio(video_path, output_dir, 0, -1)
# self.projectContext.video_path
# output_dir = os.path.join(self.projectContext.project_base_dir, "output")
# files = os.listdir(output_dir):
# for i, f in enumerate(files):
# fname = '.'.join(f.split('.')[:-1])
# try:
# st_time = float(fname)
# cur_audio, _ = soundfile.read(os.path.join(output_dir, f))
# # print(len(cur_audio))
# st_index = int(st_time * freq)
# audio_len = len(cur_audio)
# blank_audio[st_index: st_index + audio_len] = cur_audio
# origin_wav[st_index: st_index + audio_len] *= origin_audio_rate
# state[0] = float((i + 1) / len(files)) * 0.6 + 0.2
# except:
# continue
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
......@@ -9,7 +9,7 @@ import openpyxl
import constant
from openpyxl.styles import PatternFill, Alignment
from utils import replace_path_suffix, transfer_second_to_time
from utils import replace_path_suffix, transfer_second_to_time, reverse_time_to_seconds, get_seconds, transfer_second_to_all_time
from speech_synthesis import Speaker
class RunThread(threading.Thread):
"""复写线程类,用于解决主线程无法捕捉子线程中异常的问题
......@@ -125,8 +125,9 @@ class ProjectContext:
self.speaker_speed = None
self.duration = 0
# 一些常量
self.header = ["起始时间", "终止时间", "字幕", '建议', '解说脚本', "语速"]
self.write_header = ["起始时间", "起始时间(转换后)", "终止时间", "终止时间(转换后)", "字幕", '建议', '解说脚本', "语速"]
self.header = ["起始时间", "终止时间", "字幕", '建议旁白字数', '解说脚本', "语速"]
# self.write_header = ["起始时间", "起始时间(转换后)", "终止时间", "终止时间(转换后)", "字幕", '建议', '解说脚本', "语速"]
self.write_header = ["起始时间", "终止时间", "字幕", '建议旁白字数', '解说脚本', "语速"]
self.aside_header = ['起始时间', '推荐字数', '解说脚本',"语速", "预览音频"]
self.subtitle_header = ["起始时间", "终止时间", "字幕"]
......@@ -185,7 +186,7 @@ class ProjectContext:
self.excel_path = info["excel_path"]
self.speaker_info = info["speaker_info"]["speaker_id"]
self.speaker_speed = info["speaker_info"]["speaker_speed"]
self.speaker_type = info["speaker_info"]["speaker_type"] if "speaker_type" in info["speaker_info"] else "科大讯飞"
self.speaker_type = info["speaker_info"]["speaker_type"] if "speaker_type" in info["speaker_info"] else "浙大内部tts"
self.detected = info["detection_info"]["detected"]
self.nd_process = info["detection_info"]["nd_process"]
self.last_time = info["detection_info"]["last_time"]
......@@ -231,7 +232,6 @@ class ProjectContext:
# 先备份文件,再覆盖主文件,可选是否需要备份,默认需要备份
# 20221030:添加旁白检测的进度
def save_project(self, need_save_new: bool=False) -> str:
print("22222sava")
self.save_conf()
# all_element = sorted(all_element, key=lambda x: float(x.st_time_sec))
print("current excel_path:", self.excel_path)
......@@ -260,7 +260,7 @@ class ProjectContext:
def refresh_element(self, row, aside: str):
self.all_elements[int(row)].aside = aside
if not self.initial_ing:
if not self.initial_ing:
save_excel_to_path(self.all_elements, self.excel_path, self.write_header, self.excel_sheet_name)
def refresh_speed(self, row, speed: str)->None:
......@@ -279,8 +279,16 @@ class ProjectContext:
# todo:现在是只用None判断是否是字幕,后续是否也需要用""来?
for i in range(len(d["字幕"])):
st_time_sec, ed_time_sec, subtitle, suggest, aside, speed = [d[x][i] for x in self.header]
print(">>>>>>>>>>>>>>load ed time")
print(st_time_sec)
print(ed_time_sec)
if ed_time_sec == None or ed_time_sec == "":
print(">>>>into load")
ed_time_sec = st_time_sec
# 当前条目是字幕
if d["字幕"][i] != None:
st_time_sec = reverse_time_to_seconds(str(st_time_sec))
ed_time_sec = reverse_time_to_seconds(str(ed_time_sec))
self.subtitle_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside, speed))
self.all_elements.append(self.subtitle_list[-1])
else:
......@@ -299,12 +307,22 @@ class ProjectContext:
if d["终止时间"][i] is None:
# 如果是最后一条
if i == len(d["字幕"]) - 1:
ed_time_sec = "360000" if self.duration == 0 else self.duration # todo 默认最大时长是100h
print(1)
# ed_time_sec = "360000" if self.duration == 0 else self.duration # todo 默认最大时长是100h
else:
ed_time_sec = "%.2f"%(float(d["起始时间"][i + 1]) - 0.01)
else:
ed_time_sec = d["终止时间"][i]
st_time_sec = reverse_time_to_seconds(str(st_time_sec))
ed_time_sec = reverse_time_to_seconds(str(ed_time_sec))
if aside == None:
aside = ""
if suggest != None and suggest != "":
arrays = suggest.split("/")
if len(arrays) == 2:
suggest = str(len(aside)) + "/" + arrays[1]
else:
suggest = str(len(aside)) + "/" + arrays[0]
self.aside_list.append(Element(st_time_sec, ed_time_sec, subtitle, suggest, aside, speed))
self.all_elements.append(self.aside_list[-1])
# print("[load_excel_from_path] ", end='')
......@@ -370,8 +388,9 @@ class ProjectContext:
for speaker in content["speaker_zju_details"]:
speaker_name.append(
",".join([speaker["name"], speaker["gender"], speaker["age_group"]]))
if self.speaker_info is None:
if self.speaker_info is None or self.speaker_info == "":
self.speaker_info = speaker_name[0]
print(">>>>>>>>>>>>>>>>>get all info :" + self.speaker_info)
return tuple(speaker_name)
def init_speakers(self):
......@@ -450,17 +469,31 @@ def write_to_sheet(path: str, sheet_name: str, valuelist: list):
value = value_element.to_list()
# 把None换成空串
value = ["" if x == None else x for x in value]
value.insert(1, transfer_second_to_time(value[0])) if value[0] != "" else value.insert(1, "")
value.insert(3, transfer_second_to_time(value[2])) if value[2] != "" else value.insert(3, "")
# value.insert(1, transfer_second_to_time(value[0])) if value[0] != "" else value.insert(1, "")
# value.insert(3, transfer_second_to_time(value[2])) if value[2] != "" else value.insert(3, "")
# value[0] = get_seconds(value[0]) if value[0] != "" else ""
# value[1] = get_seconds(value[1]) if value[1] != "" else ""
value[0] = transfer_second_to_all_time(value[0]) if value[0] != "" else ""
value[1] = transfer_second_to_all_time(value[1]) if value[1] != "" else ""
suggest = value[3]
if suggest != None and suggest != "":
arrays = suggest.split("/")
if len(arrays) == 2:
value[3] = str(len(value[4])) + "/" + arrays[1]
else:
value[3] = str(len(value[4])) + "/" + arrays[0]
index = len(value)
cur_row = sheet.max_row
for j in range(0, index):
sheet.cell(row=cur_row + 1, column=j + 1, value=str(value[j]))
cell = 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')
cell = sheet.cell(row=cur_row + 1, column=j + 1).fill = PatternFill(fill_type='solid', fgColor='ffff00')
if j == 4:
sheet.cell(row=cur_row + 1, column=j + 1).alignment = Alignment(wrapText=True)
cell = sheet.cell(row=cur_row + 1, column=j + 1).alignment = Alignment(wrapText=True)
cell.number_format = '@'
workbook.save(path)
......
......@@ -13,3 +13,4 @@ class myVideoSlider(QSlider):
# self.setValue(int(value)/9)
value = round(value/self.width()*self.maximum()) # 根据鼠标点击的位置和slider的长度算出百分比
self.ClickedValue.emit(value)
self.setFocus()
\ No newline at end of file
import re
import csv
import argparse
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from difflib import SequenceMatcher
title = ['起始时间(转换后)', '终止时间(转换后)', '字幕']
def init():
# 获取中文停用词列表
global stop_words
with open('chinese_stopwords.txt', 'r', encoding='utf-8') as file:
stop_words = set(line.strip() for line in file)
# 将保存的时间戳转化为秒
def change_to_second(time_str):
from datetime import datetime
time_obj = datetime.strptime(time_str, "%H:%M:%S,%f")
seconds = time_obj.hour * 3600 + time_obj.minute * 60 + \
time_obj.second + time_obj.microsecond / 1000000
return seconds
# 计算字幕的相似度
def calculate_similarity(str1, str2, method='cosine'):
if method == 'cosine':
tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix = tfidf_vectorizer.fit_transform([str1, str2])
similarity_matrix = cosine_similarity(tfidf_matrix)
return similarity_matrix[0][1]
else :
return SequenceMatcher(None, str1, str2).ratio()
# 计算两个时间戳的时间差(单位:秒)
def calculate_time_difference(time1, time2):
return abs(time2 - time1)
def calculate_weight(x, y):
# weight = e^(-alpha * time_diff)
# 相差1s的系数为0.9
alpha = 0.11
return 1 / (alpha * (x + y) + 1)
# 检查句子中的每个单词是否都是停用词
def is_all_stopwords(sentence):
return all(word in stop_words for word in sentence)
### 如果其中有-符号,可能在用excel打开时自动添加=变成公式,读取的时候没问题
def read_srt_to_csv(path_srt, path_output):
with open(path_srt, 'r', encoding='utf-8-sig') as f:
srt_content = f.read() # str
# 使用正则表达式匹配时间码和字幕内容
pattern = re.compile(r'(\d+)\n([\d:,]+) --> ([\d:,]+)\n(.+?)(?=\n\d+\n|$)', re.DOTALL)
matches = pattern.findall(srt_content)
# 写入 csv 文件
with open(path_output, 'w', newline='', encoding='utf-8') as f:
csv_writer = csv.writer(f)
csv_writer.writerow(title)
for _, start, end, subtitle in matches: # 都是str格式
subtitle = re.sub(r'\{[^}]*\}', '', subtitle) # 将srt文件前的加粗等格式去掉
csv_writer.writerow([start, end, subtitle.strip()])
def read_from_xlsx(path_xlsx='output.xlsx', path_output='deal.csv'):
data = pd.read_excel(path_xlsx)
with open(path_output, 'w', newline='', encoding='utf-8') as f:
csv_writer = csv.writer(f)
csv_writer.writerow(title)
for _, data1 in data.iterrows():
start, end, subtitle = data1[1], data1[3], data1[4]
if isinstance(subtitle, float) and np.isnan(subtitle):
continue
# 与srt文件格式同步
start = start.replace('.', ',')
end = end.replace('.', ',')
# print(start, end, subtitle,)
# print(type(start), type(end), type(subtitle))
csv_writer.writerow([start, end, subtitle.strip()])
### 对于srt中的字幕计算相似性度。从ocr中找到时间戳满足<=time_t的字幕,
### 然后计算字幕间的相似度,取一个最大的。字幕从start和end都匹配一遍
# time_threshold设置阈值,用于判断时间差是否可接受
def measure_score(path_srt, path_ocr, time_threshold=5.0, method='cosine'):
data_srt, data_ocr = [], []
with open(path_srt, 'r', encoding='utf-8') as file:
csv_reader = csv.reader(file)
data_srt = [i for i in csv_reader]
data_srt.pop(0)
for i in range(len(data_srt)):
data_srt[i][0] = change_to_second(data_srt[i][0])
data_srt[i][1] = change_to_second(data_srt[i][1])
with open(path_ocr, 'r', encoding='utf-8') as file:
csv_reader = csv.reader(file)
data_ocr = [i for i in csv_reader]
data_ocr.pop(0)
for i in range(len(data_ocr)):
data_ocr[i][0] = change_to_second(data_ocr[i][0])
data_ocr[i][1] = change_to_second(data_ocr[i][1])
# 计算相似度
total_similarity = 0.0
total_weight = 0.0
for sub in data_srt:
max_similarity = 0.0
# 去除srt中的停用词
if is_all_stopwords(sub[2]):
continue
for sub1 in data_ocr:
x, y = abs(sub[0] - sub1[0]), abs(sub[1] - sub1[1])
if min(x, y) <= time_threshold:
# print(sub[2], sub1[2])
score = calculate_similarity(sub[2], sub1[2], 'cosine')
max_similarity = max(max_similarity, score * calculate_weight(x, y))
total_similarity += max_similarity
total_weight += 1
# print(total_similarity, total_similarity / len(data_srt), total_similarity / total_weight)
return total_similarity / len(data_srt), total_similarity / total_weight
if __name__ == '__main__':
init()
parser = argparse.ArgumentParser(description="benchmark")
# 添加命令行参数
parser.add_argument("--path_srt", required=True, type=str, help="Path of srt file, format is srt")
parser.add_argument("--path_ocr", required=True, type=str, help="Path of ocr file, format is xlsx")
parser.add_argument("--method", type=str, default='cosine', help="Select evaluation method")
parser.add_argument("--time_threshold", type=float,default=5.0, help="Allowable time frame")
args = parser.parse_args()
output_file_srt = 'deal_srt.csv'
output_file_ocr = 'deal_ocr.csv'
read_srt_to_csv(args.path_srt, output_file_srt)
read_from_xlsx(args.path_ocr, output_file_ocr)
score = measure_score(output_file_srt, output_file_ocr, args.time_threshold, args.method)
print(f'该评估算法得分: {score[1]:.5f}')
\ No newline at end of file
......@@ -260,9 +260,12 @@ class Operation_Dialog(QDialog, Ui_Dialog):
else: # 如果是旁白
end_time = ""
subtitle = ""
suggest = "插入旁白,推荐字数为" + suggest
# suggest = "插入旁白,推荐字数为" + suggest
# if self.comboBox_2.currentText() == "增加一行":
# suggest = "插入旁白,推荐字数为0"
suggest = suggest
if self.comboBox_2.currentText() == "增加一行":
suggest = "插入旁白,推荐字数为0"
suggest = "0/100"
# 别忘复原
self.buttonBox.setEnabled(False)
self.zmpb_change_slot()
......
......@@ -14,6 +14,7 @@ from PyQt5.QtWidgets import *;
from management import RunThread
from speech_synthesis import ffmpeg_path
from ffmpeg_util import cg_wav
class ExportProcessor(QWidget):
show_warning_signal = pyqtSignal(str)
......@@ -23,27 +24,30 @@ class ExportProcessor(QWidget):
self.state = [0]
self.threads = []
def export_slot(self, video_path, output_dir):
def export_slot(self, video_path, output_dir, pb_cg_rate):
t = RunThread(funcName=self.start_export,
args=(video_path, output_dir),
args=(video_path, output_dir, pb_cg_rate),
name="export")
t.setDaemon(True)
self.threads.append(t)
for t in self.threads:
t.start()
try:
t.start()
except Exception as e:
print(e)
print("===子线程已经开启 in export===")
self.export_callback_signal.emit(self.threads, self.state)
def start_export(self, video_path, output_dir):
mixed_audio_path = aggrevate_audios(video_path, output_dir, self.state)
def start_export(self, video_path, output_dir, pb_cg_rate):
mixed_audio_path = aggrevate_audios(video_path, output_dir, self.state, pb_cg_rate)
export_video(video_path, mixed_audio_path, output_dir, self.state)
# 生成一条无声的音频,然后把旁白音频逐个按照时间位置放进去,得到仅含旁白的音频和旁白+原声的音频
def aggrevate_audios(video_path: str, output_dir: str, state=None):
def aggrevate_audios(video_path: str, output_dir: str, state=None,pb_cg_rate = 1.00):
# 这个模块最多只有80%的进度
if state is None:
state = [0]
......@@ -56,6 +60,18 @@ def aggrevate_audios(video_path: str, output_dir: str, state=None):
# 将生成的旁白音频放入空白音频中,并将原音频的对应位置音量降低为原来的30%
files = os.listdir(output_dir)
if pb_cg_rate != 1.00:
audio_path = os.path.join(output_dir, os.path.basename(video_path).split('.')[0] + ".wav")
for i, f in enumerate(files):
fname = '.'.join(f.split('.')[:-1])
try:
if fname.find(".") != -1:
cg_wav(audio_path, os.path.join(output_dir, f), pb_cg_rate)
except Exception as e:
print(e)
continue
for i, f in enumerate(files):
fname = '.'.join(f.split('.')[:-1])
try:
......
{"video_path": null, "excel_path": null, "detection_info": {"detected": false, "nd_process": 0.0, "last_time": 0.0, "caption_boundings": [], "has_subtitle": true}, "speaker_info": {"speaker_type": "\u6d59\u5927\u5185\u90e8tts", "speaker_id": "test\uff0c\u5973\uff0c\u5e74\u8f7b\u4eba", "speaker_speed": "1.00(4\u5b57/\u79d2)"}}
\ No newline at end of file
{"video_path": null, "excel_path": null, "detection_info": {"detected": false, "nd_process": 0.0, "last_time": 0.0, "caption_boundings": [], "has_subtitle": true}, "speaker_info": {"speaker_type": "", "speaker_id": "eagle\uff0c\u5973\uff0c\u5e74\u8f7b\u4eba", "speaker_speed": "1.00(4\u5b57/\u79d2)"}}
\ No newline at end of file
{
"speaker_details": [{
"id": 0,
"name": "晓辰",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "女",
"description": "休闲、放松的语音,用于自发性对话和会议听录。",
"audio_path": "./res/speaker_audio/Xiaochen.wav",
"speaker_code": "zh-CN-XiaochenNeural"
},
{
"id": 1,
"name": "晓涵",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "女",
"description": "温暖、甜美、富有感情的声音,可用于许多对话场景。",
"audio_path": "./res/speaker_audio/Xiaohan.wav",
"speaker_code": "zh-CN-XiaohanNeural"
},
{
"id": 2,
"name": "晓墨",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "女",
"description": "清晰、放松的声音,具有丰富的角色扮演和情感,适合音频书籍。",
"audio_path": "./res/speaker_audio/Xiaomo.wav",
"speaker_code": "zh-CN-XiaomoNeural"
},
{
"id": 7,
"name": "晓晓",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "女",
"description": "活泼、温暖的声音,具有多种场景风格和情感。",
"audio_path": "./res/speaker_audio/Xiaoxiao.wav",
"speaker_code": "zh-CN-XiaoxiaoNeural"
},
{
"id": 8,
"name": "晓萱",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "女",
"description": "自信、有能力的声音,具有丰富的角色扮演和情感,适合音频书籍。",
"audio_path": "./res/speaker_audio/Xiaoxuan.wav",
"speaker_code": "zh-CN-XiaoxuanNeural"
},
{
"id": 9,
"name": "晓颜",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "女",
"description": "训练有素、舒适的语音,用于客户服务和对话场景。",
"audio_path": "./res/speaker_audio/Xiaoyan.wav",
"speaker_code": "zh-CN-XiaoyanNeural"
},
{
"id": 3,
"name": "晓秋",
"language": "中文(普通话,简体)",
"age_group": "中年人",
"gender": "女",
"description": "智能、舒适的语音,适合阅读长内容。",
"audio_path": "./res/speaker_audio/Xiaoqiu.wav",
"speaker_code": "zh-CN-XiaoqiuNeural"
},
{
"id": 4,
"name": "晓秋",
"language": "中文(普通话,简体)",
"age_group": "中年人",
"gender": "女",
"description": "智能、舒适的语音,适合阅读长内容。",
"audio_path": "./res/speaker_audio/Xiaoqiu.wav",
"speaker_code": "zh-CN-XiaoqiuNeural"
},
{
"id": 5,
"name": "晓睿",
"language": "中文(普通话,简体)",
"age_group": "老年",
"gender": "女",
"description": "成熟、睿智的声音,具有丰富的情感,适合音频书籍。",
"audio_path": "./res/speaker_audio/Xiaorui.wav",
"speaker_code": "zh-CN-XiaoruiNeural"
},
{
"id": 6,
"name": "晓双",
"language": "中文(普通话,简体)",
"age_group": "儿童",
"gender": "女",
"description": "可爱、愉悦的语音,可应用于许多儿童相关场景。",
"audio_path": "./res/speaker_audio/Xiaoshuang.wav",
"speaker_code": "zh-CN-XiaoshuangNeural"
},
{
"id": 10,
"name": "晓悠",
"language": "中文(普通话,简体)",
"age_group": "儿童",
"gender": "女",
"description": "天使般的清晰声音,可以应用于许多儿童相关场景。",
"audio_path": "./res/speaker_audio/Xiaoyou.wav",
"speaker_code": "zh-CN-XiaoyouNeural"
},
{
"id": 11,
"name": "云希",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "男",
"description": "活泼、阳光的声音,具有丰富的情感,可用于许多对话场景。",
"audio_path": "./res/speaker_audio/Yunxi.wav",
"speaker_code": "zh-CN-YunxiNeural"
},
{
"id": 12,
"name": "云扬",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "男",
"description": "专业、流利的声音,具有多种场景风格。",
"audio_path": "./res/speaker_audio/Yunyang.wav",
"speaker_code": "zh-CN-YunyangNeural"
},
{
"id": 13,
"name": "云野",
"language": "中文(普通话,简体)",
"age_group": "中年人",
"gender": "男",
"description": "成熟、放松的声音,具有多种情感,适合音频书籍。",
"audio_path": "./res/speaker_audio/Yunye.wav",
"speaker_code": "zh-CN-YunyeNeural"
}
"speaker_details": [
],
"speaker_zju_details": [{
"id": 0,
"name": "test",
"name": "eagle",
"language": "中文(普通话,简体)",
"age_group": "年轻人",
"gender": "女",
......
......@@ -39,6 +39,7 @@ class Setting_Dialog(QDialog, Ui_Dialog):
self.comboBox_2.clear()
# todo 把所有说话人都加上来
self.speaker_li = projectContext.get_all_speaker_info()
# self.speaker_li = []
self.speaker_zju_li = projectContext.get_all_speaker_zju_info() #本地tts
self.speed_list_zju = ["1.00(4字/秒)", "1.10(4.5字/秒)", "1.25(5字/秒)", "1.50(6字/秒)", "1.75(7字/秒)", "2.00(8字/秒)", "2.50(10字/秒)"] #本地tts
......@@ -46,7 +47,8 @@ class Setting_Dialog(QDialog, Ui_Dialog):
# self.comboBox.addItem(i)
self.speed_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(self.speed_li_2)
self.speaker_types = ["科大讯飞", "浙大内部tts"]
# self.speaker_types = ["科大讯飞", "浙大内部tts"]
self.speaker_types = ["浙大内部tts"]
self.comboBox_0.addItems(self.speaker_types)
print(projectContext.speaker_type)
if projectContext.speaker_type is None or projectContext.speaker_type == "":
......@@ -54,7 +56,7 @@ class Setting_Dialog(QDialog, Ui_Dialog):
else:
self.comboBox_0.setCurrentIndex(self.speaker_types.index(projectContext.speaker_type))
if self.comboBox_0.currentIndex() ==0: #讯飞
if self.comboBox_0.currentIndex() !=0: #讯飞
self.comboBox.addItems(self.speaker_li)
self.comboBox_2.addItems(self.speed_li_2)
else:
......@@ -67,13 +69,13 @@ class Setting_Dialog(QDialog, Ui_Dialog):
self.comboBox.setCurrentIndex(0)
else:
print(projectContext.speaker_info)
self.comboBox.setCurrentIndex(self.speaker_li.index(projectContext.speaker_info) if self.comboBox_0.currentIndex() ==0 else self.speaker_zju_li.index(projectContext.speaker_info))
self.comboBox.setCurrentIndex(self.speaker_li.index(projectContext.speaker_info) if self.comboBox_0.currentIndex() !=0 else self.speaker_zju_li.index(projectContext.speaker_info))
print(projectContext.speaker_speed)
if projectContext.speaker_speed is None or projectContext.speaker_speed == "":
self.comboBox_2.setCurrentIndex(0)
else:
self.comboBox_2.setCurrentIndex(self.speed_li_2.index(projectContext.speaker_speed) if self.comboBox_0.currentIndex() ==0 else self.speed_list_zju.index(projectContext.speaker_speed))
self.comboBox_2.setCurrentIndex(self.speed_li_2.index(projectContext.speaker_speed) if self.comboBox_0.currentIndex() !=0 else self.speed_list_zju.index(projectContext.speaker_speed))
finally:
self.refresh_flag = False
......@@ -84,7 +86,8 @@ class Setting_Dialog(QDialog, Ui_Dialog):
self.comboBox.clear()
self.comboBox_2.clear()
self.projectContext.speaker_type = self.comboBox_0.currentText()
if self.comboBox_0.currentIndex() ==0:
# if self.comboBox_0.currentIndex() ==0:
if self.comboBox_0.currentIndex() !=0:
print("讯飞")
self.comboBox.addItems(self.speaker_li)
self.comboBox_2.addItems(self.speed_li_2)
......@@ -106,12 +109,12 @@ class Setting_Dialog(QDialog, Ui_Dialog):
if self.projectContext.speaker_info is None or self.projectContext.speaker_info == "" :
self.comboBox.setCurrentIndex(0)
else:
self.comboBox.setCurrentIndex(self.speaker_li.index(self.projectContext.speaker_info) if self.comboBox_0.currentIndex() ==0 else self.speaker_zju_li.index(self.projectContext.speaker_info))
self.comboBox.setCurrentIndex(self.speaker_li.index(self.projectContext.speaker_info) if self.comboBox_0.currentIndex() !=0 else self.speaker_zju_li.index(self.projectContext.speaker_info))
if self.projectContext.speaker_speed is None or self.projectContext.speaker_speed == "":
self.comboBox_2.setCurrentIndex(0)
else:
self.comboBox_2.setCurrentIndex(self.speed_li_2.index(self.projectContext.speaker_speed) if self.comboBox_0.currentIndex() ==0 else self.speed_list_zju.index(self.projectContext.speaker_speed))
self.comboBox_2.setCurrentIndex(self.speed_li_2.index(self.projectContext.speaker_speed) if self.comboBox_0.currentIndex() !=0 else self.speed_list_zju.index(self.projectContext.speaker_speed))
def speaker_change_slot(self):
"""切换说话人
......
......@@ -23,11 +23,12 @@ from typing import Tuple
import datetime
import numpy as np
from azure.cognitiveservices.speech import SpeechConfig, SpeechSynthesizer, ResultReason, AudioDataStream
from azure.cognitiveservices.speech.audio import AudioOutputConfig
# from azure.cognitiveservices.speech import SpeechConfig, SpeechSynthesizer, ResultReason, AudioDataStream
# from azure.cognitiveservices.speech.audio import AudioOutputConfig
import openpyxl
import shutil
from vits_chinese import tts
from utils import reverse_time_to_seconds
tmp_file = 'tmp.wav'
adjusted_wav_path = "adjusted.wav"
......@@ -81,8 +82,11 @@ def choose_speaker(speaker_name: str) -> Speaker:
Returns:
Speaker: 返回对应说话人,如果没有这个说话人则报错
"""
print(">>>>>>>>>>>>>speakerName:" + speaker_name)
for speaker in speakers:
print(">>>>>>>>>>>>>speaker:" + speaker.name)
if speaker.name == speaker_name:
return speaker
raise ValueError
......@@ -105,41 +109,42 @@ def speech_synthesis(text: str, output_file: str, speaker: Speaker, speed: float
if speaker.speaker_type != None and speaker.speaker_type == "1":
tts(text, speed, output_file)
else:
speech_config = SpeechConfig(
subscription="db34d38d2d3447d482e0f977c66bd624",
region="eastus"
)
print("1")
# speech_config = SpeechConfig(
# subscription="db34d38d2d3447d482e0f977c66bd624",
# region="eastus"
# )
speech_config.speech_synthesis_language = "zh-CN"
speech_config.speech_synthesis_voice_name = speaker.speaker_code
# speech_config.speech_synthesis_language = "zh-CN"
# speech_config.speech_synthesis_voice_name = speaker.speaker_code
# 先把合成的语音文件输出得到tmp.wav中,便于可能的调速需求
# # 先把合成的语音文件输出得到tmp.wav中,便于可能的调速需求
synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=None)
ssml_string = f"""
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="{speech_config.speech_synthesis_language}">
<voice name="{speaker.speaker_code}">
<prosody rate="{round((speed - 1.0) * 100, 2)}%">
{text}
</prosody>
</voice>
</speak>"""
result = synthesizer.speak_ssml_async(ssml_string).get()
stream = AudioDataStream(result)
stream.save_to_wav_file(output_file)
print(result.reason)
while result.reason == ResultReason.Canceled:
cancellation_details = result.cancellation_details
print("取消的原因", cancellation_details.reason, cancellation_details.error_details)
time.sleep(1)
synthesizer.stop_speaking()
del synthesizer
synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=None)
result = synthesizer.speak_ssml_async(ssml_string).get()
stream = AudioDataStream(result)
stream.save_to_wav_file(output_file)
print(result.reason)
# synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=None)
# ssml_string = f"""
# <speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="{speech_config.speech_synthesis_language}">
# <voice name="{speaker.speaker_code}">
# <prosody rate="{round((speed - 1.0) * 100, 2)}%">
# {text}
# </prosody>
# </voice>
# </speak>"""
# result = synthesizer.speak_ssml_async(ssml_string).get()
# stream = AudioDataStream(result)
# stream.save_to_wav_file(output_file)
# print(result.reason)
# while result.reason == ResultReason.Canceled:
# cancellation_details = result.cancellation_details
# print("取消的原因", cancellation_details.reason, cancellation_details.error_details)
# time.sleep(1)
# synthesizer.stop_speaking()
# del synthesizer
# synthesizer = SpeechSynthesizer(speech_config=speech_config, audio_config=None)
# result = synthesizer.speak_ssml_async(ssml_string).get()
# stream = AudioDataStream(result)
# stream.save_to_wav_file(output_file)
# print(result.reason)
# detached
def change_speed_and_volume(wav_path: str, speed: float = 1.0):
......@@ -205,7 +210,7 @@ def get_narratage_text(sheet_content: dict) -> Tuple[list, list, list]:
for i, text in enumerate(narratage):
# 这里的speed是x.x倍速
speed = float(speeds[i].split('(')[0])
if text is not None:
if text is not None and text != "":
if text == '翻译':
narratage_text.append(subtitle[i])
else:
......@@ -236,8 +241,10 @@ def get_narratage_text(sheet_content: dict) -> Tuple[list, list, list]:
# narratage_start_time.append(cur_start)
# narratage_end_time.append(cur_end)
# cur_start = cur_start + (len(x) / normal_speed + normal_interval) / speed
narratage_start_time.append(float(start_time[i]))
narratage_end_time.append(float(end_time[i])) if end_time[i] is not None else narratage_end_time.append(-1)
# narratage_start_time.append(float(start_time[i]))
# narratage_end_time.append(float(end_time[i])) if end_time[i] is not None else narratage_end_time.append(-1)
narratage_start_time.append(float(reverse_time_to_seconds(start_time[i])))
narratage_end_time.append(float(reverse_time_to_seconds(end_time[i]))) if end_time[i] is not None and end_time[i] != "" else narratage_end_time.append(-1)
narratage_speed.append(speed)
return narratage_text, narratage_start_time, narratage_end_time, narratage_speed
......@@ -251,13 +258,16 @@ def second_to_str(seconds: float) -> str:
Returns:
str: “时:分:秒”格式的时间字符串
"""
seconds = float(seconds)
hour = int(seconds / 3600)
minute = int((seconds - hour * 3600) / 60)
second = int(seconds - hour * 3600 - minute * 60)
ms = int((seconds - second - minute * 60 - hour * 3600) * 1000)
time_str = "%02d:%02d:%02d,%03d" % (hour, minute, second, ms)
return time_str
try:
seconds = float(seconds)
hour = int(seconds / 3600)
minute = int((seconds - hour * 3600) / 60)
second = int(seconds - hour * 3600 - minute * 60)
ms = int((seconds - second - minute * 60 - hour * 3600) * 1000)
time_str = "%02d:%02d:%02d,%03d" % (hour, minute, second, ms)
return time_str
except:
return str(seconds)
def export_caption(sheet_content: dict, caption_file: str):
......
......@@ -56,19 +56,34 @@ def change_project_path(path):
if __name__ == '__main__':
try:
# subprocess.call(['deploy.bat'])
if not is_lav_filters_installed() or not is_file_copyed():
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./res/images/eagle_2.ico"))
apply_stylesheet(app, theme='dark_amber.xml')
mainWindow = MainWindow(project_path)
QtWidgets.QMessageBox.critical(mainWindow,'警告','视频解码器未正常安装',QtWidgets.QMessageBox.Yes)
else:
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
currentExitCode = MainWindow.EXIT_CODE_REBOOT
# if not is_lav_filters_installed() or not is_file_copyed():
# QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
# QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
# app = QApplication(sys.argv)
# app.setWindowIcon(QIcon("./res/images/eagle_2.ico"))
# apply_stylesheet(app, theme='dark_amber.xml')
# mainWindow = MainWindow(project_path)
# QtWidgets.QMessageBox.critical(mainWindow,'警告','视频解码器未正常安装',QtWidgets.QMessageBox.Yes)
# else:
# QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
# QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
# currentExitCode = MainWindow.EXIT_CODE_REBOOT
# if not os.path.exists("C:\LavFilters") and not os.path.exists("C:\Program Files (x86)\LAV Filters"):
# QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
# QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
# app = QApplication(sys.argv)
# app.setWindowIcon(QIcon("./res/images/eagle_2.ico"))
# apply_stylesheet(app, theme='dark_amber.xml')
# mainWindow = MainWindow(project_path)
# QtWidgets.QMessageBox.critical(mainWindow,'警告','视频解码器未正常安装',QtWidgets.QMessageBox.Yes)
# else:
# QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
# QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
# currentExitCode = MainWindow.EXIT_CODE_REBOOT
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
currentExitCode = MainWindow.EXIT_CODE_REBOOT
while currentExitCode == MainWindow.EXIT_CODE_REBOOT:
app = QApplication(sys.argv)
app.setWindowIcon(QIcon("./res/images/eagle_2.ico"))
......@@ -82,6 +97,8 @@ if __name__ == '__main__':
apply_stylesheet(app, theme='dark_amber.xml')
# mainWindow.show()
mainWindow.showMaximized()
if not os.path.exists("C:\LavFilters") and not os.path.exists("C:\Program Files (x86)\LAV Filters"):
mainWindow.import_excel_dialog.show_with_msg("视频解码器未正常安装")
currentExitCode = app.exec_()
app = None
except Exception as e:
......
......@@ -3,7 +3,7 @@
block_cipher = None
env_dir = 'C:/Users/AIA/.conda/envs/testmovie/Lib/site-packages/'
missingPkgs = ['Microsoft.CognitiveServices.Speech.core.dll', 'decorator.py', 'google', 'paddle', 'paddleocr', 'PIL', 'requests', 'urllib3', 'http', 'idna', 'certifi', 'setuptools', 'astor', 'charset_normalizer']
missingPkgs = ['Microsoft.CognitiveServices.Speech.core.dll', 'decorator.py', 'google', 'paddleocr', 'PIL', 'requests', 'urllib3', 'http', 'idna', 'certifi', 'setuptools', 'astor', 'charset_normalizer']
def add_missing_packages(lst):
pkgs = []
......@@ -20,8 +20,8 @@ a = Analysis(
['start.py'],
pathex=[],
binaries=[],
datas=[('res','res')] + pkgPaths,
hiddenimports=[],
datas=[('vits_chinese','vits_chinese')] + [('res','res'),('./deploy.bat','.'),('./ding_notify.conf','.'),('LAVFilters64','LAVFilters64'),('LAVFilters32','LAVFilters32')] + pkgPaths,
hiddenimports=['filecmp'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
......@@ -38,7 +38,7 @@ exe = EXE(
a.scripts,
[],
exclude_binaries=True,
name='start',
name='无障碍电影制作系统',
debug=False,
bootloader_ignore_signals=False,
strip=False,
......@@ -49,6 +49,7 @@ exe = EXE(
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['res\\images\\eagle_2.ico'],
)
coll = COLLECT(
exe,
......@@ -58,5 +59,5 @@ coll = COLLECT(
strip=False,
upx=True,
upx_exclude=[],
name='start',
name='无障碍电影制作系统',
)
......@@ -38,6 +38,29 @@ def validate_and_get_filepath(file_info) -> Tuple[str, bool]:
return "", False
return file_info[0][0], True
def get_seconds(time_str: str):
try:
# print(">>>>>>>>>>reverse time")
# print(time_str)
if time_str is None or time_str == "":
return time_str
parts = time_str.split(":")
if len(parts) != 3:
return time_str
hour = int(parts[0])
minutes = int(parts[1])
seconds_parts = parts[2].split(".")
if len(seconds_parts) != 2:
return time_str
seconds = int(seconds_parts[0])
milliseconds = int(seconds_parts[1])
total_seconds = hour * 3600 + minutes * 60 + seconds + milliseconds / 1000
return str(total_seconds)
except Exception as e:
print(e)
return time_str
def trans_to_seconds(timePoint: str) -> float:
"""将用户输入的时间字符串转换为秒数
......@@ -47,13 +70,17 @@ def trans_to_seconds(timePoint: str) -> float:
Returns:
float: 时间字符串对应秒数
"""
time_in_seconds = 0
timePoints = timePoint.split(':')
units = 1
for i in range(len(timePoints) - 1, -1, -1):
time_in_seconds += units * float(timePoints[i])
units *= 60
return time_in_seconds
# time_in_seconds = 0
# timePoints = timePoint.split(':')
# units = 1
# for i in range(len(timePoints) - 1, -1, -1):
# time_in_seconds += units * float(timePoints[i])
# units *= 60
# return time_in_seconds
try:
return float(reverse_time_to_seconds(timePoint))
except Exception as e:
return None
def transfer_second_to_time(sec: str) -> str:
"""将秒数转换为"hh:mm:ss.xxx"格式的时间字符串
......@@ -64,13 +91,75 @@ def transfer_second_to_time(sec: str) -> str:
Returns:
str: "hh:mm:ss.xxx"格式的时间字符串
"""
duration = int(float(sec))
hour = int(duration/3600)
minutes = int((duration % 3600)/60)
seconds = int(duration%60)
msec = round((float(sec) - hour * 3600 - minutes * 60 - seconds) * 1000)
time = "%02d:%02d:%02d.%03d" % (hour, minutes, seconds, msec)
return time
try:
duration = int(float(sec))
hour = int(duration/3600)
minutes = int((duration % 3600)/60)
seconds = int(duration%60)
# msec = round((float(sec) - hour * 3600 - minutes * 60 - seconds) * 1000)
# time = "%02d:%02d:%02d.%03d" % (hour, minutes, seconds, msec)
time = "%02d:%02d:%02d" % (hour, minutes, seconds)
return time
except Exception as e:
print(e)
return sec
def transfer_second_to_all_time(sec: str) -> str:
"""将秒数转换为"hh:mm:ss.xxx"格式的时间字符串
Args:
sec (str): 待转换的描述
Returns:
str: "hh:mm:ss.xxx"格式的时间字符串
"""
try:
duration = int(float(sec))
hour = int(duration/3600)
minutes = int((duration % 3600)/60)
seconds = int(duration%60)
msec = round((float(sec) - hour * 3600 - minutes * 60 - seconds) * 1000)
time = "%02d:%02d:%02d.%03d" % (hour, minutes, seconds, msec)
# time = "%02d:%02d:%02d" % (hour, minutes, seconds)
return time
except Exception as e:
print(e)
return sec
def reverse_time_to_seconds(time_str: str) -> str:
"""将"hh:mm:ss.xxx"格式的时间字符串转换为秒数
Args:
time_str (str): 时间字符串,格式为"hh:mm:ss.xxx"
Returns:
float: 对应的秒数
"""
try:
# print(">>>>>>>>>>reverse time")
# print(time_str)
if time_str is None or time_str == "":
return time_str
parts = time_str.split(":")
if len(parts) != 3:
return time_str
hour = int(parts[0])
minutes = int(parts[1])
seconds_parts = parts[2].split(".")
# if len(seconds_parts) != 2:
# return time_str
seconds = int(seconds_parts[0])
# milliseconds = int(seconds_parts[1])
# total_seconds = hour * 3600 + minutes * 60 + seconds + milliseconds / 1000
total_seconds = hour * 3600 + minutes * 60 + seconds
print(str(total_seconds))
return str(total_seconds)
except Exception as e:
print(">>>>>>>>>>reverse time err" + time_str)
print(e)
return time_str
def replace_path_suffix(path: str, new_suffix: str) -> str:
"""替换文件路径后缀
......@@ -93,7 +182,7 @@ def check_sheet_content(book_path: str) -> bool:
bool: True(用户输入的表符合预期) or False(用户输入的表格式不正确,很可能输入错误)
"""
sheet_heads = get_sheetHead(book_path)
need_heads = ['起始时间', '终止时间', '字幕', '建议', '解说脚本']
need_heads = ['起始时间', '终止时间', '字幕', '建议旁白字数', '解说脚本']
if len(sheet_heads) == 0:
return False
......@@ -150,7 +239,8 @@ def get_progress_with_cmd(cmd: str, state=None):
if result is not None:
elapsed_time = result.groupdict()['time']
# 此处可能会出现进度超过100%,未对数值进行纠正
progress = trans_to_seconds(elapsed_time) / trans_to_seconds(duration)
# progress = trans_to_seconds(elapsed_time) / trans_to_seconds(duration)
progress = float(get_seconds(elapsed_time)) / float(get_seconds(duration))
state[0] = pre + progress * 0.2
print(elapsed_time)
print(progress)
......
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