diff --git a/test.py b/test.py index c08e5b5f..42765721 100644 --- a/test.py +++ b/test.py @@ -33,49 +33,38 @@ # msg=f"separate vocal and background music:{str(e)}" # #set_process(msg) # print(msg) -import sys -from PySide6.QtGui import QGuiApplication -from PySide6.QtWidgets import QWidget, QApplication -def ceshi(): - from you_get.extractors import youtube +## 获取识别文字 +# import os +# from faster_whisper import WhisperModel +# model = WhisperModel("base", device="cpu", +# download_root="./models", +# local_files_only=True) +# data=[] +# +# for i in range(0,24): +# name=f'output0{str(i).zfill(2)}.wav' +# if not os.path.exists(f'c:/users/c1/videos/_video_out/{name}'): +# continue +# segments, info = model.transcribe(f'c:/users/c1/videos/_video_out/{name}', +# beam_size=1, +# best_of=1, +# condition_on_previous_text=False,language="zh") +# res=[] +# for segment in segments: +# res.append(segment.text.strip()) +# data.append(f"wavs/{name}|{'.'.join(res)}|coqui") +# +# with open("./metadata_train.csv","w",encoding='utf-8') as f: +# f.write("\n".join(data)) - try: - youtube.download('https://www.youtube.com/watch?v=n4mF5xo5khM', - output_dir='.', - merge=True, - extractor_proxy='http://127.0.0.1:10809' - ) - except Exception as e: - print(e) - -class StartWindow(QWidget): - def __init__(self): - super(StartWindow, self).__init__() - # 设置窗口无边框和标题 - # 设置窗口的背景图片 - # 窗口大小 - self.resize(560, 350) - self.center() - self.show() - # 使用QTimer延时显示窗口B - ceshi() - - - def center(self): - screen=QGuiApplication.primaryScreen() - qtRect = self.frameGeometry() - qtRect.moveCenter(screen.availableGeometry().center()) - reso=screen.geometry() - self.width, self.height=reso.width(), reso.height() - self.move(qtRect.topLeft()) +import requests +lang=["zh-hans","zh-hant","en","fr","de","ja","ko","ru","es","th","it","pt","vi","ar","tr","hi","hu"] -if __name__ == "__main__": - app = QApplication(sys.argv) - try: - startwin = StartWindow() - except Exception as e: - print(f"error:{str(e)}") - sys.exit(app.exec()) +auth=requests.get('https://edge.microsoft.com/translate/auth') +for it in lang: + url=f'https://api-edge.cognitive.microsofttranslator.com/translate?from=&to={it}&api-version=3.0&includeSentenceLength=true' + res=requests.post(url,json=[{"Text":"hello,my friend\nI am from China"}],headers={"Authorization":f"Bearer {auth.text}"}) + print(res.json()) \ No newline at end of file diff --git a/version.json b/version.json index 36123a55..4c9fa2db 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "version": "0.9997", - "version_num": 10007 + "version": "0.9998", + "version_num": 10008 } diff --git a/videotrans/__init__.py b/videotrans/__init__.py index bfc5334f..5aafad2a 100644 --- a/videotrans/__init__.py +++ b/videotrans/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -VERSION="0.9997 v.wonyes.org" -VERSION_NUM=10007 +VERSION="0.9998 v.wonyes.org" +VERSION_NUM=10008 diff --git a/videotrans/language/en.json b/videotrans/language/en.json index f0d4ea87..55caff80 100644 --- a/videotrans/language/en.json +++ b/videotrans/language/en.json @@ -1,5 +1,6 @@ { "translate_language": { + "test google": "Test connection Google..", "Select Out Dir": "Select Out Dir", "downing...": "Downloading...", "start download": "Start Download", diff --git a/videotrans/language/es.json b/videotrans/language/es.json index fe7498c6..9065e5d8 100644 --- a/videotrans/language/es.json +++ b/videotrans/language/es.json @@ -1,5 +1,6 @@ { "translate_language" : { + "test google": "Test connection Google..", "Select Out Dir": "Select Out Dir", "downing...": "Downloading...", "start download": "Start Download", diff --git a/videotrans/language/zh.json b/videotrans/language/zh.json index 1ec5e968..2df4dde0 100644 --- a/videotrans/language/zh.json +++ b/videotrans/language/zh.json @@ -1,5 +1,6 @@ { "translate_language": { + "test google": "正在测试能否连接到Google..", "Select Out Dir": "下载到..", "downing...": "下载中...", "start download": "立即下载", @@ -179,7 +180,7 @@ "Open": "打开", "Translate channel": "翻译渠道", "Proxy": "代理地址", - "proxy address": "Google或chatGPT官方接口,国内必填代理或设置系统代理,格式http://127.0.0.1:端口号", + "proxy address": "Google或chatGPT官方接口需填代理,代理格式 http://127.0.0.1:端口号 ", "shuoming01": "点击试听当前配音角色的发音\n生成配音可能需要数秒,请耐心等待", "Trial dubbing": "试听配音", "Source lang": "原始语言", @@ -224,17 +225,17 @@ "Donating developers": "捐助开发者", "Standard Function Mode": "标准功能模式", "Display all options for video translation and dubbing": "显示全部选项,进行视频翻译和配音", - "Export Srt From Videos": "视频提取字幕", + "Export Srt From Videos": "视频识别字幕", "Extracting SRT subtitles in the original language from local videos": "从本地视频中提取出原始语言的srt字幕", "Merging Subtitle Video": "字幕视频合并", "Embed locally existing SRT subtitles into the video": "将本地已有的srt字幕嵌入视频中", "Subtitle Create Dubbing": "字幕创建配音", "Local existing SRT subtitle generation dubbing WAV files": "本地已有的srt字幕生成配音wav文件", - "Speech Recognition Text": "语音识别文字", + "Speech Recognition Text": "音视频转文字", "Recognize the sound in audio or video and output SRT text": "将音频或视频中的声音识别后输出srt文字", "From Text Into Speech": "文字合成语音", "Generate audio WAV from text or SRT subtitle files": "将文字或srt字幕文件生成音频wav", - "Extract Srt And Translate": "提取字幕翻译", + "Extract Srt And Translate": "识别字幕翻译", "Extract SRT subtitles from local videos in the original language and translate them into SRT subtitle files in the target language": "从本地视频中提取出原始语言的srt字幕,并翻译为目标语言的srt字幕文件", "Separate Video to audio": "视频音频分离", "Separate audio and silent videos from videos": "从视频中分离出音频和无声视频", diff --git a/videotrans/task/trans_create.py b/videotrans/task/trans_create.py index 1669c24b..69aa63e5 100644 --- a/videotrans/task/trans_create.py +++ b/videotrans/task/trans_create.py @@ -160,6 +160,7 @@ def __init__(self, obj): if os.path.exists(self.targetdir_source_regcon) and os.path.getsize(self.targetdir_source_regcon)==0: os.unlink(self.targetdir_source_regcon) else: + self.targetdir_source_vocal=self.targetdir_source_wav self.source_separate = self.source_back = self.source_vocal = None # 如果存在字幕,则视为目标字幕,直接生成,不再识别和翻译 @@ -315,11 +316,14 @@ def trans(self): if not os.path.exists(self.targetdir_source_sub) or os.path.exists(self.targetdir_target_sub): return True # 测试翻译 + switch_trans="" if config.params['translate_type'].lower()==GOOGLE_NAME.lower(): - set_process("Test Google connecting...") + set_process(config.transobj['test google']) if not self.testgoogle(): - raise Exception(f'无法连接Google,请正确设置代理,例如v2ray默认是http://127.0.0.1:10809,clash默认http://127.0.0.1:7890或开启全局代理') - set_process(transobj['starttrans']) + switch_trans='无法连接Google,已自动切换为Microsoft翻译' + config.params['translate_type']='Microsoft' + + set_process(transobj['starttrans']+switch_trans) # 开始翻译,从目标文件夹读取原始字幕 rawsrt = get_subtitle_from_srt(self.targetdir_source_sub, is_file=True) if not rawsrt or len(rawsrt)<1: @@ -496,11 +500,11 @@ def before_tts(self): filename = self.cache_folder + "/" + md5_hash.hexdigest() + ".mp3" # 如果是clone-voice类型, 需要截取对应片段 if config.params['tts_type']=='clone-voice': - if not os.path.exists(self.targetdir_source_vocal): + if config.params['is_separate'] and not os.path.exists(self.targetdir_source_vocal): raise Exception(f'not exits {self.targetdir_source_vocal}') - # clone 方式文件为wav格式 + # clone 方式文件为wav格式 filename+=".wav" - cut_from_audio(audio_file=self.targetdir_source_vocal,ss=it['startraw'],to=it['endraw'],out_file=filename) + cut_from_audio(audio_file=self.targetdir_source_vocal if config.params['is_separate'] else self.targetdir_source_wav,ss=it['startraw'],to=it['endraw'],out_file=filename) queue_tts.append({ "text": it['text'], diff --git a/videotrans/translator/__init__.py b/videotrans/translator/__init__.py index 5c752627..906459e8 100644 --- a/videotrans/translator/__init__.py +++ b/videotrans/translator/__init__.py @@ -3,6 +3,7 @@ from videotrans.configure import config GOOGLE_NAME = "Google" +MICROSOFT_NAME = "Microsoft" BAIDU_NAME = "Baidu" DEEPL_NAME = "DeepL" DEEPLX_NAME = "DeepLx" @@ -14,6 +15,7 @@ SRT_NAME = "srt" # 翻译通道 TRANSNAMES = [ + MICROSOFT_NAME, GOOGLE_NAME, BAIDU_NAME, DEEPL_NAME, @@ -32,7 +34,8 @@ "zh", # 百度通道 "ZH", # deepl deeplx通道 "zh", # 腾讯通道 - "zh" # OTT通道 + "zh", # OTT通道 + "zh-Hans" ], "zh-tw": [ "zh-tw", @@ -40,7 +43,8 @@ "cht", "ZH", "zh-TW", - "zt" + "zt", + "zh-Hant" ], "en": [ "en", @@ -48,6 +52,7 @@ "en", "EN", "en", + "en", "en" ], "fr": [ @@ -56,6 +61,7 @@ "fra", "FR", "fr", + "fr", "fr" ], "de": [ @@ -64,6 +70,7 @@ "de", "DE", "de", + "de", "de" ], "ja": [ @@ -72,6 +79,7 @@ "jp", "JA", "ja", + "ja", "ja" ], "ko": [ @@ -80,6 +88,7 @@ "kor", "KO", "ko", + "ko", "ko" ], "ru": [ @@ -88,6 +97,7 @@ "ru", "RU", "ru", + "ru", "ru" ], "es": [ @@ -96,6 +106,7 @@ "spa", "ES", "es", + "es", "es" ], "th": [ @@ -104,6 +115,7 @@ "th", "No", "th", + "th", "th" ], "it": [ @@ -112,6 +124,7 @@ "it", "IT", "it", + "it", "it" ], "pt": [ @@ -120,6 +133,7 @@ "pt", "PT", "pt", + "pt", "pt" ], "vi": [ @@ -128,7 +142,8 @@ "vie", "No", "vi", - "No" + "No", + "vi" ], "ar": [ "ar", @@ -136,6 +151,7 @@ "ara", "No", "ar", + "ar", "ar" ], "tr": [ @@ -144,6 +160,7 @@ "tr", "tr", "tr", + "tr", "tr" ], "hi": [ @@ -152,6 +169,7 @@ "hi", "No", "hi", + "hi", "hi" ], "hu": [ @@ -160,7 +178,8 @@ "hu", "HU", "No", - "No" + "No", + "hu" ] } @@ -183,7 +202,6 @@ def get_source_target_code(*, show_source=None, show_target=None, translate_type if not translate_type: return None, None lower_translate_type = translate_type.lower() - print(f'{lower_translate_type == GOOGLE_NAME.lower()}') if show_source: source_list = LANG_CODE[show_source] if show_source in LANG_CODE else LANG_CODE[ config.rev_langlist[show_source]] @@ -202,6 +220,8 @@ def get_source_target_code(*, show_source=None, show_target=None, translate_type return (show_source, show_target) elif lower_translate_type == OTT_NAME.lower(): return (source_list[5] if source_list else "-", target_list[5] if target_list else "-") + elif lower_translate_type==MICROSOFT_NAME.lower(): + return (source_list[6] if source_list else "-", target_list[6] if target_list else "-") else: raise Exception(f"[error]get_source_target_code:{translate_type=},{show_source=},{show_target=}") @@ -237,7 +257,7 @@ def is_allow_translate(*, translate_type=None, show_target=None, only_key=False) if only_key: return True - + #再判断是否为No,即不支持 index = 0 if lower_translate_type == BAIDU_NAME.lower(): index = 2 @@ -245,6 +265,8 @@ def is_allow_translate(*, translate_type=None, show_target=None, only_key=False) index = 3 elif lower_translate_type == TENCENT_NAME.lower(): index = 4 + elif lower_translate_type==MICROSOFT_NAME.lower(): + index=6 if show_target: target_list = LANG_CODE[show_target] if show_target in LANG_CODE else LANG_CODE[ @@ -290,6 +312,8 @@ def run(*, translate_type=None, text_list=None, target_language_name=None, set_p from videotrans.translator.gemini import trans elif lower_translate_type == AZUREGPT_NAME.lower(): from videotrans.translator.azure import trans + elif lower_translate_type==MICROSOFT_NAME.lower(): + from videotrans.translator.microsoft import trans else: print(lower_translate_type == OTT_NAME.lower()) raise Exception(f"[error]run {translate_type=},{target_language_name=}") diff --git a/videotrans/translator/baidu.py b/videotrans/translator/baidu.py index 658be4cb..74f75979 100644 --- a/videotrans/translator/baidu.py +++ b/videotrans/translator/baidu.py @@ -30,7 +30,6 @@ def trans(text_list, target_language="en", *, set_p=True): for it in split_source_text: try: source_length = len(it) - print(f'{source_length=}') text="\n".join(it) salt = int(time.time()) strtext = f"{config.params['baidu_appid']}{text}{salt}{config.params['baidu_miyue']}" @@ -58,7 +57,7 @@ def trans(text_list, target_language="en", *, set_p=True): else: tools.set_process("\n\n".join(result), func_name="set_fanyi") result_length = len(result) - print(f'{result_length=}') + while result_length < source_length: result.append("") result_length += 1 diff --git a/videotrans/translator/deeplx.py b/videotrans/translator/deeplx.py index ed92ae0c..dd2903e0 100644 --- a/videotrans/translator/deeplx.py +++ b/videotrans/translator/deeplx.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import re +import time import requests import json @@ -31,7 +32,6 @@ def trans(text_list, target_language="en", *, set_p=True): for it in split_source_text: try: source_length = len(it) - print(f'{source_length=}') data = { "text": "\n".join(it), "source_lang": "auto", @@ -41,11 +41,12 @@ def trans(text_list, target_language="en", *, set_p=True): url=config.params['deeplx_address'].strip().rstrip('/').replace('/translate','')+'/translate' if not url.startswith('http'): url=f"http://{url}" - print(f'{url=}') - print(data) response = requests.post(url=url, json=data, proxies=None) if response.status_code!=200: - raise Exception(f'错误码={response.status_code}') + if set_p: + tools.set_process(f'错误码={response.status_code},5s后重试') + time.sleep(5) + return trans(text_list,target_language,set_p=set_p) result = response.json() config.logger.info(f'{result=},{response.text}') result=result['data'].strip().replace(''','"').split("\n") @@ -64,7 +65,11 @@ def trans(text_list, target_language="en", *, set_p=True): if response: error+=f'错误码={response.status_code}' config.logger.info(f'DeepLx {error}') - raise Exception(f'DeepLx出错了,请更换翻译渠道:{error}') + if set_p: + tools.set_process(f'DeepLx出错了,请更换翻译渠道:{error},5s后重试') + time.sleep(5) + return trans(text_list,target_language,set_p=set_p) + raise Exception(error) if isinstance(text_list, str): return "\n".join(target_text) diff --git a/videotrans/translator/google.py b/videotrans/translator/google.py index 4f483d5c..819a95c7 100644 --- a/videotrans/translator/google.py +++ b/videotrans/translator/google.py @@ -32,7 +32,7 @@ def trans(text_list, target_language="en", *, set_p=True): # 切割为每次翻译多少行,值在 set.ini中设定,默认10 split_size = int(config.settings['trans_thread']) - print(f'{split_size=}') + split_source_text = [source_text[i:i + split_size] for i in range(0, len(source_text), split_size)] for it in split_source_text: @@ -46,9 +46,8 @@ def trans(text_list, target_language="en", *, set_p=True): } response = requests.get(url, proxies=proxies, headers=headers, timeout=300) if response.status_code != 200: - config.logger.info(f'Google 返回响应:{response.text}\nurl={url}') - time.sleep(10) - return trans(text_list, target_language, set_p=set_p) + config.logger.error(f'Google 返回响应:{response.status_code=},{response.text=}\nurl={url}') + raise Exception(f'Google error_code={response.status_code}') re_result = re.findall( r'(?s)class="(?:t0|result-container)">(.*?)<', response.text) @@ -65,7 +64,6 @@ def trans(text_list, target_language="en", *, set_p=True): else: tools.set_process("\n\n".join(result), func_name="set_fanyi") result_length=len(result) - print(f'{result_length=}') config.logger.info(f'{result_length=},{source_length=}') while result_length-1: - if set_p: - tools.set_process(f'Google HTTPSConnectionPool error,after 5s retry') - config.logger.error(f'Google HTTPSConnectionPool error,after 5s retry:\n{url=}') - time.sleep(5) - return trans(text_list, target_language, set_p=set_p) config.logger.error(f'Google error:{str(error)}') raise Exception(f'Google error:{str(error)}') if isinstance(text_list, str): diff --git a/videotrans/translator/microsoft.py b/videotrans/translator/microsoft.py new file mode 100644 index 00000000..31335583 --- /dev/null +++ b/videotrans/translator/microsoft.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +import time +import requests +from videotrans.configure import config +from videotrans.util import tools + +def trans(text_list, target_language="en", *, set_p=True): + """ + text_list: + 可能是多行字符串,也可能是格式化后的字幕对象数组 + target_language: + 目标语言 + set_p: + 是否实时输出日志,主界面中需要 + """ + + # 翻译后的文本 + target_text = [] + # 整理待翻译的文字为 List[str] + if isinstance(text_list, str): + source_text = text_list.strip().split("\n") + else: + source_text = [f"{t['text']}" for t in text_list] + + # 切割为每次翻译多少行,值在 set.ini中设定,默认10 + split_size = int(config.settings['trans_thread']) + split_source_text = [source_text[i:i + split_size] for i in range(0, len(source_text), split_size)] + auth=requests.get('https://edge.microsoft.com/translate/auth',proxies={"http":"","https":""}) + for it in split_source_text: + try: + source_length=len(it) + text = "\n".join(it) + url = f"https://api-edge.cognitive.microsofttranslator.com/translate?from=&to={target_language}&api-version=3.0&includeSentenceLength=true" + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + "Authorization":f"Bearer {auth.text}" + } + response = requests.post(url, json=[{"Text":text}],headers=headers, timeout=300,proxies={"http":"","https":""}) + if response.status_code != 200: + config.logger.info(f'Microsoft 返回响应:{response.text}\nurl={url}') + if set_p: + tools.set_process(f'error_code={response.status_code},暂停10s后重试') + time.sleep(10) + return trans(text_list, target_language, set_p=set_p) + + re_result=response.json() + if len(re_result)>0 and len(re_result[0]['translations'])>0: + result=re_result[0]['translations'][0]['text'].strip().replace(''','"').split("\n") + if set_p: + tools.set_process("\n\n".join(result), 'subtitle') + else: + tools.set_process("\n\n".join(result), func_name="set_fanyi") + result_length=len(result) + config.logger.info(f'{result_length=},{source_length=}') + while result_length