Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
jianchang512 committed Feb 2, 2024
1 parent 34f4783 commit 17c905f
Show file tree
Hide file tree
Showing 24 changed files with 146 additions and 78 deletions.
10 changes: 10 additions & 0 deletions about.md
Expand Up @@ -69,6 +69,16 @@
- * 生 / 2024-1-25 捐助 18.88 元
- w*d / 2024-1-26 捐助 6.66 元
- *. / 2024-1-27 捐助 0.15 元
- vedanthkadam555 / 2024-1-28 捐助 10 美元
- *明 / 2024-1-29 捐助 20 元
- *骁(支付宝) / 2024-1-29 捐助 2 元
- 5*) / 2024-1-30 捐助 10 元
- rqi14(U*d) / 2024-1-30 捐助 200 元
- *正 / 2024-1-30 捐助 10 元
- i*8 / 2024-1-31 捐助 18 元
- *. / 2024-2-1 捐助 10 元
- *途 / 2024-2-1 捐助 30 元
- *甜(bingsunny0730) / 2024-2-2 捐助 1.68 元
- k*v / 2024-2-2 捐助 10 元
- *林(xjsszl) / 2024-2-2 捐助 10 元
- **宇(支付宝) / 2024-2-2 捐助 10 元
4 changes: 2 additions & 2 deletions version.json
@@ -1,4 +1,4 @@
{
"version": "0.9993",
"version_num": 10003
"version": "0.9994",
"version_num": 10004
}
4 changes: 2 additions & 2 deletions videotrans/__init__.py
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-

VERSION="0.9993 v.wonyes.org"
VERSION_NUM=10003
VERSION="0.9994 v.wonyes.org"
VERSION_NUM=10004
60 changes: 35 additions & 25 deletions videotrans/box/win.py
Expand Up @@ -6,7 +6,7 @@
import time
from PySide6 import QtWidgets
from PySide6.QtCore import QSettings, QUrl
from PySide6.QtGui import QDesktopServices, QIcon
from PySide6.QtGui import QDesktopServices, QIcon, QTextCursor
from PySide6.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QLabel
from videotrans import VERSION
from videotrans.box.component import Player, DropButton, Textedit, TextGetdir
Expand Down Expand Up @@ -241,22 +241,18 @@ def opendir_fn(self, dirname=None):
def receiver(self, json_data):
data = json.loads(json_data)
# fun_name 方法名,type类型,text具体文本
if "func_name" not in data:
self.statuslabel.setText(data['text'][:60])
if data['type'] == 'error':
self.statuslabel.setStyle("""color:#ff0000""")
elif data['func_name'] == "yspfl_end":

if data['func_name'] == "yspfl_end":
# 音视频分离完成了
self.yspfl_startbtn.setText(config.transobj["zhixingwc"] if data['type'] == "end" else config.transobj["zhixinger"])
self.yspfl_startbtn.setDisabled(False)

self.statuslabel.setText("")
self.statuslabel.setText("Succeed")
elif data['func_name'] == 'ysphb_end':
self.ysphb_startbtn.setText(config.transobj["zhixingwc"] if data['type'] == "end" else config.transobj["zhixinger"])
self.ysphb_startbtn.setDisabled(False)
self.ysphb_opendir.setDisabled(False)
if data['type'] == 'end':
self.statuslabel.setText("")
self.statuslabel.setText("Succeed")
basename = os.path.basename(self.ysphb_videoinput.text())
if os.path.exists(config.rootdir + f"/{basename}.srt"):
os.unlink(config.rootdir + f"/{basename}.srt")
Expand All @@ -268,15 +264,16 @@ def receiver(self, json_data):
self.disabled_shibie(False)
if data['type'] == 'end':
self.shibie_startbtn.setText(config.transobj["zhixingwc"])
self.shibie_text.clear()
self.shibie_text.insertPlainText(data['text'])
self.statuslabel.setText("")
self.statuslabel.setText("Succeed")
else:
self.shibie_startbtn.setText(config.transobj["zhixinger"])
elif data['func_name'] == 'hecheng_end':
if data['type'] == 'end':
self.hecheng_startbtn.setText(config.transobj["zhixingwc"])
self.hecheng_startbtn.setToolTip(config.transobj["zhixingwc"])
self.statuslabel.setText("")
self.statuslabel.setText("Succeed")
else:
self.hecheng_startbtn.setText(data['text'])
self.hecheng_startbtn.setToolTip(data['text'])
Expand All @@ -289,17 +286,30 @@ def receiver(self, json_data):
self.disabled_geshi(False)
self.geshi_result.insertPlainText(config.transobj["zhixingwc"])
self.geshi_input.clear()
self.statuslabel.setText("")
self.statuslabel.setText("Succeed")
elif data['func_name'] == 'hun_end':
self.hun_startbtn.setDisabled(False)
self.hun_out.setDisabled(False)
self.statuslabel.setText("")
self.statuslabel.setText("Succeed")
elif data['func_name'] == 'fanyi_end':
self.fanyi_start.setDisabled(False)
self.fanyi_start.setText(config.transobj['starttrans'])
self.fanyi_targettext.clear()
self.fanyi_targettext.setPlainText(data['text'])
self.daochu.setDisabled(False)
self.statuslabel.setText("")
self.statuslabel.setText("Translate end")
elif data['func_name']=='set_fanyi':
self.fanyi_targettext.moveCursor(QTextCursor.End)
self.fanyi_targettext.insertPlainText(data['text'])
elif data['func_name']=='set_subtitle':
self.shibie_text.moveCursor(QTextCursor.End)
self.shibie_text.insertPlainText(data['text'])
elif "func_name" not in data or not data['func_name']:
self.statuslabel.setText(data['text'][:60])
if data['type'] == 'error':
self.statuslabel.setStyle("""color:#ff0000""")
else:
self.statuslabel.setText(data['text'])

# tab-1 音视频分离启动
def yspfl_start_fn(self):
Expand All @@ -313,7 +323,7 @@ def yspfl_start_fn(self):
self.yspfl_task = Worker(
[['-y', '-i', file, '-an', f"{video_out}/{basename}.mp4", f"{video_out}/{basename}.wav"]], "yspfl_end",
self)
self.yspfl_task.update_ui.connect(self.receiver)
# self.yspfl_task.update_ui.connect(self.receiver)
self.yspfl_task.start()
self.yspfl_startbtn.setText(config.transobj['running'])
self.yspfl_startbtn.setDisabled(True)
Expand Down Expand Up @@ -359,7 +369,8 @@ def ysphb_start_fun(self):
basename = os.path.basename(videofile)
srtfile = self.ysphb_srtinput.text()
wavfile = self.ysphb_wavinput.text()

# 是否保留原声
save_raw=self.ysphb_replace.isChecked()
if not videofile or not os.path.exists(videofile):
QMessageBox.critical(self, config.transobj['anerror'], config.transobj['selectvideodir'])
return
Expand Down Expand Up @@ -392,8 +403,8 @@ def ysphb_start_fun(self):
videofile = tmpname_conver

if wavfile:
# 视频里是否有音轨
if video_info['streams_audio'] > 0:
# 视频里是否有音轨 并且保留原声音
if video_info['streams_audio'] > 0 and save_raw:
cmds = [
['-y', '-i', videofile, '-i', wavfile, '-filter_complex', "[0:a][1:a]amerge=inputs=2[aout]", '-map',
'0:v', '-map', "[aout]", '-c:v', 'copy', '-c:a', 'aac', tmpname],
Expand All @@ -409,7 +420,6 @@ def ysphb_start_fun(self):
['-y', '-i', tmpname if wavfile else videofile, "-vf", f"subtitles={srtfile}", '-c:v', 'libx264',
'-c:a', 'copy', f'{savedir}/{basename}.mp4'])
self.ysphb_task = Worker(cmds, "ysphb_end", self)
self.ysphb_task.update_ui.connect(self.receiver)
self.ysphb_task.start()

self.ysphb_startbtn.setText(config.transobj["running"])
Expand Down Expand Up @@ -440,7 +450,7 @@ def shibie_start_fun(self):
self.shibie_ffmpeg_task = Worker([
['-y', '-i', file, out_file]
], "shibie_next", self)
self.shibie_ffmpeg_task.update_ui.connect(self.receiver)
# self.shibie_ffmpeg_task.update_ui.connect(self.receiver)
self.shibie_ffmpeg_task.start()
except Exception as e:
config.logger.error("执行语音识别前,先从视频中分离出音频失败:" + str(e))
Expand All @@ -459,7 +469,7 @@ def shibie_start_next_fun(self):
model = self.shibie_model.currentText()
print(f'{file=}')
self.shibie_task = WorkerWhisper(file, model, translator.get_audio_code(show_source=self.shibie_language.currentText()),"shibie_end", self)
self.shibie_task.update_ui.connect(self.receiver)
# self.shibie_task.update_ui.connect(self.receiver)
self.shibie_task.start()

def shibie_save_fun(self):
Expand Down Expand Up @@ -527,7 +537,7 @@ def hecheng_start_fun(self):
func_name="hecheng_end",
voice_autorate=issrt and self.voice_autorate.isChecked(),
tts_issrt=issrt)
self.hecheng_task.update_ui.connect(self.receiver)
# self.hecheng_task.update_ui.connect(self.receiver)
self.hecheng_task.start()
self.hecheng_startbtn.setText(config.transobj["running"])
self.hecheng_startbtn.setDisabled(True)
Expand Down Expand Up @@ -614,7 +624,7 @@ def geshi_start_fun(self, ext):
self.disabled_geshi(False)
return
self.geshi_task = Worker(cmdlist, "geshi_end", self, True)
self.geshi_task.update_ui.connect(self.receiver)
# self.geshi_task.update_ui.connect(self.receiver)
self.geshi_task.start()

# 禁用按钮
Expand Down Expand Up @@ -651,7 +661,7 @@ def hun_fun(self):
cmd = ['-y', '-i', file1, '-i', file2, '-filter_complex',
"[0:a][1:a]amix=inputs=2:duration=first:dropout_transition=2", '-ac', '2', savename]
self.geshi_task = Worker([cmd], "hun_end", self, True)
self.geshi_task.update_ui.connect(self.receiver)
# self.geshi_task.update_ui.connect(self.receiver)
self.geshi_task.start()
self.hun_startbtn.setDisabled(True)
self.hun_out.setDisabled(True)
Expand Down Expand Up @@ -694,7 +704,7 @@ def fanyi_start_fun(self):
QMessageBox.critical(self, config.transobj['anerror'], rs)
return
self.fanyi_task = FanyiWorker(translate_type, target_language, source_text, issrt, self)
self.fanyi_task.ui.connect(self.receiver)
# self.fanyi_task.ui.connect(self.receiver)
self.fanyi_task.start()
self.fanyi_start.setDisabled(True)
self.fanyi_start.setText(config.transobj["running"])
Expand Down
66 changes: 35 additions & 31 deletions videotrans/box/worker.py
Expand Up @@ -17,7 +17,7 @@

# 执行 ffmpeg 线程
class Worker(QThread):
update_ui = pyqtSignal(str)
# update_ui = pyqtSignal(str)

def __init__(self, cmd_list, func_name="", parent=None, no_decode=False):
super(Worker, self).__init__(parent)
Expand All @@ -26,7 +26,7 @@ def __init__(self, cmd_list, func_name="", parent=None, no_decode=False):
self.no_decode=no_decode

def run(self):
set_process_box(f'starting...')
set_process_box(f'starting ffmpeg...')
for cmd in self.cmd_list:
logger.info(f"[box]Will execute: ffmpeg {cmd=}")
try:
Expand All @@ -36,18 +36,19 @@ def run(self):
except Exception as e:
logger.error("[bxo]FFmepg exec error:" + str(e))
set_process_box("[bxo]FFmepg exec error:" + str(e))
self.post_message("error", "ffmpeg error")
# self.post_message("error", "ffmpeg error")
return f'[error]{str(e)}'
self.post_message("end", "End\n")
set_process_box(f'Ended','end')
set_process_box('ffmpeg succeed',"end",func_name=self.func_name)
# self.post_message("end", "End\n")
# set_process_box(f'Ended ffmpeg','end')

def post_message(self, type, text):
self.update_ui.emit(json.dumps({"func_name": self.func_name, "type": type, "text": text}))
# def post_message(self, type, text):
# self.update_ui.emit(json.dumps({"func_name": self.func_name, "type": type, "text": text}))


# 执行语音识别
class WorkerWhisper(QThread):
update_ui = pyqtSignal(str)
# update_ui = pyqtSignal(str)

def __init__(self, audio_path, model, language, func_name, parent=None):
super(WorkerWhisper, self).__init__(parent)
Expand All @@ -57,7 +58,7 @@ def __init__(self, audio_path, model, language, func_name, parent=None):
self.language = language

def run(self):
set_process_box(f'start {self.model}')
set_process_box(f'start {self.model} ')
try:
config.box_status='ing'
srts=run_recogn(type="all",audio_file=self.audio_path,model_name=self.model,detect_language=self.language,set_p=False,cache_folder=config.TEMP_DIR)
Expand All @@ -71,13 +72,13 @@ def run(self):
# config.box_status='stop'

def post_message(self, type, text):
self.update_ui.emit(json.dumps({"func_name": self.func_name, "type": type, "text": text}))
set_process_box(text,type,func_name=self.func_name)
# self.update_ui.emit(json.dumps({"func_name": self.func_name, "type": type, "text": text}))


# 合成
class WorkerTTS(QThread):
update_ui = pyqtSignal(str)

# update_ui = pyqtSignal(str)
def __init__(self, parent=None, *,
text=None,
role=None,
Expand All @@ -102,12 +103,13 @@ def __init__(self, parent=None, *,

def run(self):
config.box_status='ing'
set_process_box(f"start {self.tts_type=},{self.role=},{self.rate=}")
set_process_box(f"start {self.tts_type=}")

if self.tts_issrt:
try:
q = self.before_tts()
self.exec_tts(q)
self.post_message("end","Succeed")
except Exception as e:
self.post_message('error', f'srt create dubbing error:{str(e)}')
return
Expand Down Expand Up @@ -136,7 +138,7 @@ def run(self):
], no_decode=True,is_box=True)
if os.path.exists(mp3):
os.unlink(mp3)
self.post_message("end", "Ended")
self.post_message("end", "Succeed")
# config.box_status='stop'

# 配音预处理,去掉无效字符,整理开始时间
Expand Down Expand Up @@ -206,16 +208,17 @@ def exec_tts(self, queue_tts):
diff = mp3len - wavlen
if diff > 0 and self.voice_autorate:
speed = mp3len / wavlen
# 新的长度
mp3len = mp3len / speed
diff = mp3len - wavlen
if diff < 0:
diff = 0
tmp_mp3 = os.path.join(config.TEMP_DIR, f'{it["filename"]}.mp3')
speed_up_mp3(filename=it['filename'], speed=speed, out=tmp_mp3)
audio_data = AudioSegment.from_file(tmp_mp3, format="mp3")
# 增加新的偏移
offset += diff
if speed<50:
# 新的长度
mp3len = mp3len / speed
diff = mp3len - wavlen
if diff < 0:
diff = 0
tmp_mp3 = os.path.join(config.TEMP_DIR, f'{it["filename"]}.mp3')
speed_up_mp3(filename=it['filename'], speed=speed, out=tmp_mp3)
audio_data = AudioSegment.from_file(tmp_mp3, format="mp3")
# 增加新的偏移
offset += diff
elif diff > 0:
offset += diff
it['end_time'] = it['start_time'] + mp3len
Expand All @@ -227,7 +230,7 @@ def exec_tts(self, queue_tts):
# 原 total_length==0,说明没有上传视频,仅对已有字幕进行处理,不需要裁切音频
self.merge_audio_segments(segments, start_times)
except Exception as e:
raise Exception(f"[error] exec_tts :" + str(e))
raise Exception(f"[error] exec_tts:" + str(e))
return True

# join all short audio to one ,eg name.mp4 name.mp4.wav
Expand Down Expand Up @@ -259,11 +262,11 @@ def merge_audio_segments(self, segments, start_times):
return merged_audio

def post_message(self, type, text):
self.update_ui.emit(json.dumps({"func_name": self.func_name, "type": type, "text": text}))
set_process_box(text,type,func_name=self.func_name)
# self.update_ui.emit(json.dumps({"func_name": self.func_name, "type": type, "text": text}))

class FanyiWorker(QThread):
ui = pyqtSignal(str)

# ui = pyqtSignal(str)
def __init__(self, type, target_language, text, issrt, parent=None):
super(FanyiWorker, self).__init__(parent)
self.type = type
Expand All @@ -290,8 +293,9 @@ def run(self):
srts_tmp += f"{it['line']}\n{it['time']}\n{it['text']}\n\n"
self.srts = srts_tmp
except Exception as e:
self.ui.emit(json.dumps({"func_name": "fanyi_end", "type": "error", "text": str(e)}))
# self.ui.emit(json.dumps({"func_name": "fanyi_end", "type": "error", "text": str(e)}))
set_process_box(str(e),"error",func_name="fanyi_end")
return

self.ui.emit(json.dumps({"func_name": "fanyi_end", "type": "end", "text": self.srts}))
set_process_box(self.srts,"end",func_name="fanyi_end")
# self.ui.emit(json.dumps({"func_name": "fanyi_end", "type": "end", "text": self.srts}))

3 changes: 2 additions & 1 deletion videotrans/language/en.json
@@ -1,5 +1,6 @@
{
"translate_language": {
"Preserve the original sound in the video": "Preserve the original sound in the video",
"Clone voice cannot be used in subtitle dubbing mode as there are no replicable voices": "Clone voice cannot be used in subtitle dubbing mode as there are no replicable voices",
"lanjie": "Active restriction",
"The ott project at":"The OTT text translate at: github.com/jianchang512/ott",
Expand Down Expand Up @@ -289,7 +290,7 @@
"Translation channels":"Translation channels",
"Target lang":"Target lang",
"Proxy":"Proxy",
"Failed to access Google services. Please set up the proxy correctly":"Failed to access Google services. Please set up the proxy correctly",
"Failed to access Google services. Please set up the proxy correctly":"set up the proxy",
"Import text to be translated from a file..":"Import text to be translated from a file..",
"shuoming1":"If it is only pure text, there is no need to select it.\nIf it is in SRT subtitle format, it needs to be selected to not translate the line numbers and time values in the subtitles, and return them in the original subtitle format.\nIf not selected, all content will be sent to the translation engine for processing at once, and punctuation, symbols, and formatting may change.\n",
"export..":"export..",
Expand Down

0 comments on commit 17c905f

Please sign in to comment.