diff --git a/README.md b/README.md index 9b91448a..5ae420a1 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,23 @@ apt-get install ffmpeg +# 源码部署问题说明 + +1. 默认使用 ctranslate2的4.x版本,仅支持CUDA12.x版本,如果你的cuda低于12,并且无法升级cuda到12.x,请执行命令卸载ctranslate2然后重新安装 + +``` + +pip uninstall -y ctranslate2 + +pip install ctranslate2==3.24.0 + +``` + +2. 可能会遇到 `xx module not found ` 之类错误,请打开 requirements.txt,搜索该 xx 模块,然后将xx后的 ==及等会后的版本号去掉 + + + + # 使用教程和文档 请查看 https://pyvideotrans.com/guide.html diff --git a/ffmpeg.zip b/ffmpeg.zip deleted file mode 100644 index 121880f7..00000000 Binary files a/ffmpeg.zip and /dev/null differ diff --git "a/ffmpeg\344\270\213\350\275\275.txt" "b/ffmpeg\344\270\213\350\275\275.txt" new file mode 100644 index 00000000..846c2462 --- /dev/null +++ "b/ffmpeg\344\270\213\350\275\275.txt" @@ -0,0 +1,5 @@ +windowsffmpeg󣬽binĿ¼µ ffmpeg.exeffprobe.exe ļƵǰĿ¼µ ffmpeg ļ + +صַ + +https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2023-11-30-12-55/ffmpeg-n6.0.1-win64-gpl-6.0.zip \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 82b2ab34..bf025410 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ click==7.1.2 colorama==0.4.6 coloredlogs==15.0.1 contourpy==1.1.1 -ctranslate2==3.24.0 +ctranslate2 cycler==0.12.1 decorator==4.4.2 deepl==1.16.1 diff --git a/videotrans/__init__.py b/videotrans/__init__.py index b1549f78..abfc32a2 100644 --- a/videotrans/__init__.py +++ b/videotrans/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -VERSION="v1.78" -VERSION_NUM=110708 \ No newline at end of file +VERSION="v1.79" +VERSION_NUM=110709 \ No newline at end of file diff --git a/videotrans/box/win.py b/videotrans/box/win.py index a3b75ff5..e91b5a14 100644 --- a/videotrans/box/win.py +++ b/videotrans/box/win.py @@ -21,6 +21,7 @@ import shutil from videotrans.ui.toolboxen import Ui_MainWindow from videotrans.util.tools import get_azure_rolelist, get_edge_rolelist +from pathlib import Path class MainWindow(QMainWindow, Ui_MainWindow): @@ -120,6 +121,7 @@ def initUI(self): self.hecheng_role.addItems(['No']) self.hecheng_language.currentTextChanged.connect(self.hecheng_language_fun) self.hecheng_startbtn.clicked.connect(self.hecheng_start_fun) + self.listen_btn.clicked.connect(self.listen_voice_fun) self.hecheng_opendir.clicked.connect(lambda: self.opendir_fn(self.hecheng_out.text().strip())) # 设置 tts_type self.tts_type.addItems([i for i in config.params['tts_type_list']]) @@ -238,11 +240,24 @@ def fanyi_import_fun(self, obj=None): def hecheng_import_fun(self): fnames, _ = QFileDialog.getOpenFileNames(self, "Select srt", config.last_opendir, - "Text files(*.srt)") + "Text files(*.srt *.txt)") if len(fnames) < 1: return for (i, it) in enumerate(fnames): - fnames[i] = it.replace('\\', '/').replace('file:///', '') + it=it.replace('\\', '/').replace('file:///', '') + if it.endswith('.txt'): + shutil.copy2(it,f'{it}.srt') + # 使用 "r+" 模式打开文件:读取和写入 + with open(f'{it}.srt', 'r+', encoding='utf-8') as file: + # 读取原始文件内容 + original_content = file.readlines() + # 将文件指针移动到文件开始位置 + file.seek(0) + # 将新行内容与原始内容合并,并写入文件 + file.writelines(["1\n","00:00:00,000 --> 05:00:00,000\n"] + original_content) + + it+='.srt' + fnames[i] = it if len(fnames) > 0: config.last_opendir = os.path.dirname(fnames[0]) @@ -649,6 +664,73 @@ def disabled_shibie(self, type): self.shibie_language.setDisabled(type) self.shibie_model.setDisabled(type) + + # 试听配音 + def listen_voice_fun(self): + lang = translator.get_code(show_text=self.hecheng_language.currentText()) + if not lang or lang=='-': + return QMessageBox.critical(self, config.transobj['anerror'], "选择字幕语言" if config.defaulelang=='zh' else 'Please target language') + text = config.params[f'listen_text_{lang}'] + role = self.hecheng_role.currentText() + if not role or role == 'No': + return QMessageBox.critical(self, config.transobj['anerror'], config.transobj['mustberole']) + voice_dir = os.environ.get('APPDATA') or os.environ.get('appdata') + if not voice_dir or not Path(voice_dir).exists(): + voice_dir = config.rootdir + "/tmp/voice_tmp" + else: + voice_dir = voice_dir.replace('\\', '/') + "/pyvideotrans" + if not Path(voice_dir).exists(): + Path(voice_dir).mkdir(parents=True,exist_ok=True) + lujing_role = role.replace('/', '-') + + rate = int(self.hecheng_rate.value()) + tts_type = self.tts_type.currentText() + + if rate >= 0: + rate = f"+{rate}%" + else: + rate = f"{rate}%" + volume=int(self.volume_rate.value()) + pitch=int(self.pitch_rate.value()) + volume=f'+{volume}%' if volume>=0 else f'{volume}%' + pitch=f'+{pitch}Hz' if pitch>=0 else f'{volume}Hz' + + + + voice_file = f"{voice_dir}/{config.params['tts_type']}-{lang}-{lujing_role}-{volume}-{pitch}.mp3" + if config.params['tts_type'] == 'GPT-SoVITS': + voice_file += '.wav' + + obj = { + "text": text, + "rate": '+0%', + "role": role, + "voice_file": voice_file, + "tts_type": config.params['tts_type'], + "language": lang, + "volume":volume, + "pitch":pitch, + } + + if config.params['tts_type'] == 'clone-voice' and role == 'clone': + return + # 测试能否连接clone + if config.params['tts_type'] == 'clone-voice': + try: + tools.get_clone_role(set_p=True) + except: + QMessageBox.critical(self, config.transobj['anerror'], + config.transobj['You must deploy and start the clone-voice service']) + return + + def feed(d): + QMessageBox.critical(self, config.transobj['anerror'], d) + + from videotrans.task.play_audio import PlayMp3 + t = PlayMp3(obj, self) + t.mp3_ui.connect(feed) + t.start() + # tab-4 语音合成 def hecheng_start_fun(self): txt = self.hecheng_plaintext.toPlainText().strip() @@ -700,6 +782,10 @@ def hecheng_start_fun(self): issrt = self.tts_issrt.isChecked() + if len(self.hecheng_files)>0: + self.tts_issrt.setChecked(True) + issrt=True + self.hecheng_task = WorkerTTS(self, files=self.hecheng_files if len(self.hecheng_files) > 0 else txt, role=role, diff --git a/videotrans/box/worker.py b/videotrans/box/worker.py index 5f7c9bfa..6bc10c42 100644 --- a/videotrans/box/worker.py +++ b/videotrans/box/worker.py @@ -480,9 +480,9 @@ def merge_audio_segments(self, *, segments=None, queue_tts=None, video_time=0, o if diff >= 0: it['end_time'] += diff offset += diff - else: + #else: # 配音小于原时长,添加静音 - merged_audio += AudioSegment.silent(duration=abs(diff)) + # merged_audio += AudioSegment.silent(duration=abs(diff)) if i > 0: silence_duration = it['start_time'] - queue_tts[i - 1]['end_time'] @@ -495,10 +495,10 @@ def merge_audio_segments(self, *, segments=None, queue_tts=None, video_time=0, o queue_tts[i] = it merged_audio += segment - if video_time > 0 and (len(merged_audio) < video_time): + #if video_time > 0 and (len(merged_audio) < video_time): # 末尾补静音 - silence = AudioSegment.silent(duration=video_time - len(merged_audio)) - merged_audio += silence + # silence = AudioSegment.silent(duration=video_time - len(merged_audio)) + # merged_audio += silence # 创建配音后的文件 try: merged_audio.export(out, format="wav") diff --git a/videotrans/recognition/all.py b/videotrans/recognition/all.py index de53f530..aaecb605 100644 --- a/videotrans/recognition/all.py +++ b/videotrans/recognition/all.py @@ -72,6 +72,8 @@ def recogn(*, if config.exit_soft or (config.current_status != 'ing' and config.box_recogn != 'ing'): del model return None + if not segment.words or len(segment.words)<1: + continue sidx += 1 start = int(segment.words[0].start * 1000) end = int(segment.words[-1].end * 1000) diff --git a/videotrans/ui/toolboxen.py b/videotrans/ui/toolboxen.py index fcf37b93..9844da79 100644 --- a/videotrans/ui/toolboxen.py +++ b/videotrans/ui/toolboxen.py @@ -247,6 +247,13 @@ def setupUi(self, MainWindow): self.hecheng_role.setObjectName("hecheng_role") self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.hecheng_role) self.horizontalLayout_10.addLayout(self.formLayout_4) + + self.listen_btn = QtWidgets.QPushButton(self.tab_2) + self.listen_btn.setFixedWidth(80) + self.listen_btn.setToolTip(config.uilanglist.get("shuoming01")) + self.listen_btn.setText(config.uilanglist.get("Trial dubbing")) + self.horizontalLayout_10.addWidget(self.listen_btn) + self.formLayout_5 = QtWidgets.QFormLayout() diff --git a/videotrans/util/tools.py b/videotrans/util/tools.py index adb2daa6..8c5d838d 100644 --- a/videotrans/util/tools.py +++ b/videotrans/util/tools.py @@ -714,12 +714,22 @@ def get_subtitle_from_srt(srtfile, *, is_file=True): raise Exception(f'get srtfile error:{str(e)}') else: content = srtfile.strip().splitlines() + # remove whitespace + content=[c for c in content if c.strip()] + if len(content) < 1: - raise Exception("srt content is 0") - + raise Exception("srt content is empty") + result = format_srt(content) + + # txt 文件转为一条字幕 if len(result) < 1: - return [] + if is_file and srtfile.endswith('.txt'): + result= [ + {"line":1,"time":"00:00:00,000 --> 05:00:00,000","text":"\n".join(content)} + ] + else: + return [] new_result = [] line = 1