Merge 07b046ebbf703d6f3a5d419bb9e6db1b565c7dfc into d65f0ff8b40c99e9a3117f4354650da3a97d90c4

This commit is contained in:
箱庭XTer 2024-07-11 23:13:42 +08:00 committed by GitHub
commit 45954e5311
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 711 additions and 21 deletions

View File

@ -25,4 +25,5 @@ jieba_fast
jieba jieba
LangSegment>=0.2.0 LangSegment>=0.2.0
Faster_Whisper Faster_Whisper
wordsegment wordsegment
srt

View File

@ -3,22 +3,22 @@ import locale
import os import os
def load_language_list(language): def load_language_list(language, locale_path="./i18n/locale"):
with open(f"./i18n/locale/{language}.json", "r", encoding="utf-8") as f: with open(os.path.join(locale_path, f"{language}.json"), "r", encoding="utf-8") as f:
language_list = json.load(f) language_list = json.load(f)
return language_list return language_list
class I18nAuto: class I18nAuto:
def __init__(self, language=None): def __init__(self, language=None, locale_path="./i18n/locale"):
if language in ["Auto", None]: if language in ["Auto", None]:
language = locale.getdefaultlocale()[ language = locale.getdefaultlocale()[
0 0
] # getlocale can't identify the system's language ((None, None)) ] # getlocale can't identify the system's language ((None, None))
if not os.path.exists(f"./i18n/locale/{language}.json"): if not os.path.exists(os.path.join(locale_path, f"{language}.json")):
language = "en_US" language = "en_US"
self.language = language self.language = language
self.language_map = load_language_list(language) self.language_map = load_language_list(language, locale_path)
def __call__(self, key): def __call__(self, key):
return self.language_map.get(key, key) return self.language_map.get(key, key)

View File

@ -2,11 +2,12 @@ import json
import os import os
from collections import OrderedDict from collections import OrderedDict
dir_path = "./i18n/locale" # The path to the i18n locale directory, you can change it to your own path
# Define the standard file name # Define the standard file name
standard_file = "locale/zh_CN.json" standard_file = os.path.join(dir_path, "zh_CN.json")
# Find all JSON files in the directory # Find all JSON files in the directory
dir_path = "locale/"
languages = [ languages = [
os.path.join(dir_path, f) os.path.join(dir_path, f)
for f in os.listdir(dir_path) for f in os.listdir(dir_path)
@ -30,7 +31,7 @@ for lang_file in languages:
# Add any missing keys to the language file # Add any missing keys to the language file
for key in diff: for key in diff:
lang_data[key] = key lang_data[key] = standard_data[key]
# Del any extra keys to the language file # Del any extra keys to the language file
for key in miss: for key in miss:

View File

@ -1,7 +1,20 @@
import ast import ast
import glob
import json import json
from collections import OrderedDict from collections import OrderedDict
import os
locale_path = "./i18n/locale" # The path to the i18n locale directory, you can change it to your own path
scan_list = ["./",
"GPT_SoVITS/",
"tools/"
] # The path to the directory you want to scan, you can change it to your own path
scan_subfolders = False # Whether to scan subfolders
# 你想要保留的特殊词汇
special_words_to_keep = {
}
def extract_i18n_strings(node): def extract_i18n_strings(node):
@ -21,20 +34,32 @@ def extract_i18n_strings(node):
return i18n_strings return i18n_strings
strings = []
# scan the directory for all .py files (recursively)
# for each file, parse the code into an AST # for each file, parse the code into an AST
# for each AST, extract the i18n strings # for each AST, extract the i18n strings
def scan_i18n_strings(filename):
strings = [] with open(filename, "r", encoding="utf-8") as f:
for filename in glob.iglob("**/*.py", recursive=True):
with open(filename, "r") as f:
code = f.read() code = f.read()
if "I18nAuto" in code: if "I18nAuto" in code:
tree = ast.parse(code) tree = ast.parse(code)
i18n_strings = extract_i18n_strings(tree) i18n_strings = extract_i18n_strings(tree)
print(filename, len(i18n_strings)) print(filename, len(i18n_strings))
strings.extend(i18n_strings) strings.extend(i18n_strings)
# scan the directory for all .py files (recursively)
if scan_subfolders:
for folder in scan_list:
for dirpath, dirnames, filenames in os.walk(folder):
for filename in [f for f in filenames if f.endswith(".py")]:
scan_i18n_strings(os.path.join(dirpath, filename))
else:
for folder in scan_list:
for filename in os.listdir(folder):
if filename.endswith(".py"):
scan_i18n_strings(os.path.join(folder, filename))
code_keys = set(strings) code_keys = set(strings)
""" """
n_i18n.py n_i18n.py
@ -49,11 +74,13 @@ print()
print("Total unique:", len(code_keys)) print("Total unique:", len(code_keys))
standard_file = "i18n/locale/zh_CN.json" standard_file = os.path.join(locale_path, "zh_CN.json")
with open(standard_file, "r", encoding="utf-8") as f: try:
standard_data = json.load(f, object_pairs_hook=OrderedDict) with open(standard_file, "r", encoding="utf-8") as f:
standard_keys = set(standard_data.keys()) standard_data = json.load(f, object_pairs_hook=OrderedDict)
standard_keys = set(standard_data.keys())
except FileNotFoundError:
standard_keys = set()
# Define the standard file name # Define the standard file name
unused_keys = standard_keys - code_keys unused_keys = standard_keys - code_keys
print("Unused keys:", len(unused_keys)) print("Unused keys:", len(unused_keys))
@ -64,12 +91,18 @@ missing_keys = code_keys - standard_keys
print("Missing keys:", len(missing_keys)) print("Missing keys:", len(missing_keys))
for missing_key in missing_keys: for missing_key in missing_keys:
print("\t", missing_key) print("\t", missing_key)
code_keys_dict = OrderedDict() code_keys_dict = OrderedDict()
for s in strings: for s in strings:
code_keys_dict[s] = s if s in special_words_to_keep:
code_keys_dict[s] = special_words_to_keep[s]
else:
code_keys_dict[s] = s
# write back # write back
os.makedirs(locale_path, exist_ok=True)
with open(standard_file, "w", encoding="utf-8") as f: with open(standard_file, "w", encoding="utf-8") as f:
json.dump(code_keys_dict, f, ensure_ascii=False, indent=4, sort_keys=True) json.dump(code_keys_dict, f, ensure_ascii=False, indent=4, sort_keys=True)
f.write("\n") f.write("\n")

View File

@ -0,0 +1,60 @@
{
"List 合并小工具": "List Merge Tool",
"SRT合并切分插件": "SRT Merge and Split Plugin",
"SRT文件": "SRT File",
"SRT编辑界面": "SRT Edit Interface",
"srt文件内容": "SRT File Content",
"上传SRT文件": "Upload SRT File",
"上传文件": "Upload Files",
"两个文件夹不能相同!!!": "The two folders cannot be the same!!!",
"主文件夹": "Main Folder",
"作者: ": "Author: ",
"使用方法": "How to Use",
"保存合并后字幕": "Save Merged Subtitles",
"保存子文件夹名称": "Save Subfolder Name",
"保存文件夹": "Save Folder",
"允许最短长度": "Minimum Allowed Length",
"内容预览": "Content Preview",
"切分与保存": "Split and Save",
"切分完成": "Split Completed",
"切分并保存音频、list": "Split and Save Audio, List",
"切分预览": "Split Preview",
"判定为短间隔时长": "Judged as Short Interval Duration",
"到": " to ",
"前置保留时间": "Preceding Retention Time",
"前置添加静音时间": "Prepend Silence Time",
"句末加句号": "Add Period at the End of Sentence",
"合并后srt文本": "Merged SRT Text",
"合并后的List": "Merged List",
"合并字幕": "Merge Subtitles",
"合并字幕设置": "Subtitle Merge Settings",
"合并文件夹与List": "Merge Folder and List",
"后置保留时间": "Following Retention Time",
"后置添加静音时间": "Append Silence Time",
"扫描文件夹": "Scan Folder",
"找不到字幕!!!": "Subtitles Not Found!!!",
"找不到音频!!!": "Audio Not Found!!!",
"提供SRT文件可使用剪映或者ASR工具获得与原始音频文件。": "Provide SRT File (can be obtained via Clip or ASR tools) and Original Audio File.",
"提前合并时间间隔很短的字幕": "Merge Subtitles with Short Intervals in Advance",
"提示": "Tips",
"文件夹路径": "Folder Path",
"最大间隔时间": "Maximum Interval Time",
"最长允许单句长度": "Maximum Allowed Sentence Length",
"根据面板合并短句并过滤你不希望出现的句子。": "Merge short sentences according to the panel and filter out sentences you do not want to appear.",
"次文件夹": "Second Folder",
"正在切分音频": "Splitting Audio",
"正在建设,敬请期待": "Under Construction, Stay Tuned",
"注意:该文件夹已存在": "Warning: The folder already exists",
"角色名称,留空使用主文件夹的": "Role Name, Leave Blank to Use Main Folder's",
"语言": "Language",
"读取文件": "Read File",
"读取本地文件": "Read Local File",
"过滤字幕": "Filter Subtitles",
"过滤带有英文的": "Filter Out English",
"过滤设置": "Filter Settings",
"过滤词语,一行一个": "Filter Words, One Per Line",
"这是一个插件用于依靠SRT文件得到切分与打标好的音频。": "This is a plugin for obtaining split and tagged audio based on SRT files.",
"随后保存成切分好的音频与list文件。": "Then save as split audio and list files.",
"音频文件": "Audio File",
"音频格式": "Audio Format"
}

View File

@ -0,0 +1,60 @@
{
"List 合并小工具": "List 合并小工具",
"SRT合并切分插件": "SRT合并切分插件",
"SRT文件": "SRT文件",
"SRT编辑界面": "SRT编辑界面",
"srt文件内容": "srt文件内容",
"上传SRT文件": "上传SRT文件",
"上传文件": "上传文件",
"两个文件夹不能相同!!!": "两个文件夹不能相同!!!",
"主文件夹": "主文件夹",
"作者: ": "作者: ",
"使用方法": "使用方法",
"保存合并后字幕": "保存合并后字幕",
"保存子文件夹名称": "保存子文件夹名称",
"保存文件夹": "保存文件夹",
"允许最短长度": "允许最短长度",
"内容预览": "内容预览",
"切分与保存": "切分与保存",
"切分完成": "切分完成",
"切分并保存音频、list": "切分并保存音频、list",
"切分预览": "切分预览",
"判定为短间隔时长": "判定为短间隔时长",
"到": "到",
"前置保留时间": "前置保留时间",
"前置添加静音时间": "前置添加静音时间",
"句末加句号": "句末加句号",
"合并后srt文本": "合并后srt文本",
"合并后的List": "合并后的List",
"合并字幕": "合并字幕",
"合并字幕设置": "合并字幕设置",
"合并文件夹与List": "合并文件夹与List",
"后置保留时间": "后置保留时间",
"后置添加静音时间": "后置添加静音时间",
"扫描文件夹": "扫描文件夹",
"找不到字幕!!!": "找不到字幕!!!",
"找不到音频!!!": "找不到音频!!!",
"提供SRT文件可使用剪映或者ASR工具获得与原始音频文件。": "提供SRT文件可使用剪映或者ASR工具获得与原始音频文件。",
"提前合并时间间隔很短的字幕": "提前合并时间间隔很短的字幕",
"提示": "提示",
"文件夹路径": "文件夹路径",
"最大间隔时间": "最大间隔时间",
"最长允许单句长度": "最长允许单句长度",
"根据面板合并短句并过滤你不希望出现的句子。": "根据面板合并短句并过滤你不希望出现的句子。",
"次文件夹": "次文件夹",
"正在切分音频": "正在切分音频",
"正在建设,敬请期待": "正在建设,敬请期待",
"注意:该文件夹已存在": "注意:该文件夹已存在",
"角色名称,留空使用主文件夹的": "角色名称,留空使用主文件夹的",
"语言": "语言",
"读取文件": "读取文件",
"读取本地文件": "读取本地文件",
"过滤字幕": "过滤字幕",
"过滤带有英文的": "过滤带有英文的",
"过滤设置": "过滤设置",
"过滤词语,一行一个": "过滤词语,一行一个",
"这是一个插件用于依靠SRT文件得到切分与打标好的音频。": "这是一个插件用于依靠SRT文件得到切分与打标好的音频。",
"随后保存成切分好的音频与list文件。": "随后保存成切分好的音频与list文件。",
"音频文件": "音频文件",
"音频格式": "音频格式"
}

View File

@ -0,0 +1,139 @@
import srt
import shutil
def parse_srt_with_lib(content):
subtitles = list(srt.parse(content))
return subtitles
def generate_srt_with_lib(subtitles):
content = srt.compose(subtitles)
return content
def merge_subtitles_with_lib(subtitles, short_interval, max_interval, max_text_length=30, add_period=True, merge_zero_interval=True):
# 标点符号
punctuations = ["","!", "", "", "?", "", ";", ""]
punctuations_extanded = punctuations
punctuations_extanded.extend([ "", ":", "", ",", "",])
# 直接合并间隔特别短的字幕
if merge_zero_interval:
eps = short_interval
for i in range(len(subtitles) - 1, 0, -1):
if subtitles[i-1].content[-1] in punctuations_extanded:
continue
if abs(subtitles[i].start.total_seconds() - subtitles[i-1].end.total_seconds()) < eps:
subtitles[i - 1].end = subtitles[i].end
subtitles[i - 1].content += subtitles[i].content
subtitles.pop(i)
merged_subtitles = []
current_subtitle = None
for subtitle in subtitles:
if current_subtitle is None:
current_subtitle = subtitle
else:
current_end = current_subtitle.end.total_seconds()
next_start = subtitle.start.total_seconds()
if current_subtitle.content[-1] not in punctuations and (next_start - current_end <= max_interval and count_words_multilang(current_subtitle.content + subtitle.content) < max_text_length):
current_subtitle.end = subtitle.end
comma = '' if current_subtitle.content[-1] not in punctuations_extanded else ''
current_subtitle.content += comma + subtitle.content
else:
if add_period and current_subtitle.content[-1] not in punctuations_extanded:
current_subtitle.content += ''
merged_subtitles.append(current_subtitle)
current_subtitle = subtitle
if current_subtitle is not None:
merged_subtitles.append(current_subtitle)
# 重新分配id因为srt.compose需要id连续
for i, subtitle in enumerate(merged_subtitles, start=1):
subtitle.index = i
return merged_subtitles
def count_words_multilang(text):
# 初始化计数器
word_count = 0
in_word = False
for char in text:
if char.isspace(): # 如果当前字符是空格
in_word = False
elif char.isascii() and not in_word: # 如果是ASCII字符英文并且不在单词内
word_count += 1 # 新的英文单词
in_word = True
elif not char.isascii(): # 如果字符非英文
word_count += 1 # 每个非英文字符单独计为一个字
return word_count
import pydub, os
def slice_audio_with_lib(audio_path, save_folder, format, subtitles, pre_preserve_time, post_preserve_time, pre_silence_time, post_silence_time, language='ZH', character='character'):
list_file = os.path.join(save_folder, 'datamapping.list')
try:
audio = pydub.AudioSegment.from_file(audio_path)
except Exception as e:
raise e
with open(list_file, 'w', encoding="utf-8") as f:
for i in range(len(subtitles)):
subtitle = subtitles[i]
start = subtitle.start.total_seconds() - pre_preserve_time
end = subtitle.end.total_seconds() + post_preserve_time
if i < len(subtitles) - 1:
next_subtitle = subtitles[i + 1]
end = min(end, 1.0/2*(subtitle.end.total_seconds()+next_subtitle.start.total_seconds()))
if i > 0:
prev_subtitle = subtitles[i - 1]
start = max(start, 1.0/2*(prev_subtitle.end.total_seconds()+subtitle.start.total_seconds()))
try:
sliced_audio = audio[int(start * 1000):int(end * 1000)]
file_name = f'{character}_{i + 1:03d}.{format}'
save_path = os.path.join(save_folder, file_name)
sliced_audio.export(save_path, format=format)
f.write(f"{file_name}|{character}|{language}|{subtitle.content}\n")
print(f"Slice {file_name} from {start} to {end}")
except Exception as e:
raise e
def merge_list_folders(first_list_file, second_list_file, character, first_folder, second_folder):
merged_lines = []
character1 = ""
filenames = set()
with open(first_list_file, 'r', encoding="utf-8") as f:
first_list = f.readlines()
for line in first_list:
filename, character1, language, content = line.split('|')
filenames.add(filename)
if character=="" or character is None:
character = character1
new_line = f"{filename}|{character}|{language}|{content}"
merged_lines.append(new_line)
with open(second_list_file, 'r', encoding="utf-8") as f:
second_list = f.readlines()
for line in second_list:
filename, _, language, content = line.split('|')
orig_filename = filename
num = 1
while filename in filenames:
filename = f"{filename.rsplit('.', 1)[0]}_{num}.{filename.rsplit('.', 1)[1]}"
num += 1
try:
os.rename(os.path.join(second_folder, orig_filename), os.path.join(first_folder, filename))
except Exception as e:
raise e
new_line = f"{filename}|{character}|{language}|{content}"
merged_lines.append(new_line)
os.remove(second_list_file)
if not os.listdir(second_folder):
os.rmdir(second_folder)
with open(first_list_file, 'w', encoding="utf-8") as f:
f.writelines(merged_lines)
return "\n".join(merged_lines)

396
tools/srt_slicer/webui.py Normal file
View File

@ -0,0 +1,396 @@
import gradio as gr
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')))
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
sys.path.append('.')
from srt_utils import (
merge_subtitles_with_lib,
parse_srt_with_lib,
generate_srt_with_lib,
slice_audio_with_lib,
count_words_multilang,
merge_list_folders
)
port = 8991
is_share = True
if len(sys.argv) > 2:
port = int(sys.argv[1])
is_share = eval(sys.argv[2])
from i18n.i18n import I18nAuto
import os
i18n = I18nAuto(language=None, locale_path="./tools/srt_slicer/i18n/locale")
def merge_srt(input_text, output_text, short_interval=0.1, max_interval=1, max_text_length=30, add_period=True, merge_zero_interval=True):
original_subtitles = parse_srt_with_lib(input_text)
merged_subtitles = merge_subtitles_with_lib(original_subtitles, short_interval, max_interval, max_text_length, add_period, merge_zero_interval)
output_text = generate_srt_with_lib(merged_subtitles)
return output_text
def slice_audio(
input_audio,
save_folder,
audio_format,
output_text,
pre_preserve_time,
post_preserve_time,
pre_silence_time,
post_silence_time,
language,
character,
):
if isinstance(input_audio, str) and input_audio != "":
pass
else:
gr.Warning(i18n("找不到音频!!!"))
return
if output_text == "":
gr.Warning(i18n("找不到字幕!!!"))
return
character_folder = os.path.join(save_folder, character)
os.makedirs(character_folder, exist_ok=True)
subtitles = parse_srt_with_lib(output_text)
try:
gr.Info(f"{i18n('正在切分音频')} {input_audio} {i18n('')} {character_folder}")
slice_audio_with_lib(
input_audio,
character_folder,
audio_format,
subtitles,
pre_preserve_time,
post_preserve_time,
pre_silence_time,
post_silence_time,
language,
character,
)
gr.Info(f"{i18n('切分完成')} ")
except Exception as e:
gr.Warning(f"Can't Slice, Error: {e}")
def get_relative_path(path, base):
return os.path.relpath(path, base)
def get_srt_and_audio_files(folder):
if not os.path.exists(folder):
os.makedirs(folder, exist_ok=True)
srt_files = []
audio_files = []
audio_file_formats = ["mp3", "wav", "ogg", "flac"]
for root, dirs, files in os.walk(folder):
for file in files:
if file.lower().endswith(".srt"):
srt_files.append(get_relative_path(os.path.join(root, file), folder))
for audio_file_format in audio_file_formats:
if file.lower().endswith(audio_file_format):
audio_files.append(get_relative_path(os.path.join(root, file), folder))
srt_file = ""
audio_file = ""
if len(srt_files) > 0:
srt_file = srt_files[0]
if len(audio_files) > 0:
audio_file = audio_files[0]
return gr.Dropdown(srt_files,value=srt_file), gr.Dropdown(audio_files,value=audio_file)
def change_srt_file(folder,srt_file):
srt_folder = os.path.dirname(os.path.join(folder, srt_file))
basename = os.path.basename(srt_file).rsplit(".", 1)[0]
audio_file_formats = ["mp3", "wav", "ogg", "flac"]
for file in os.listdir(srt_folder):
print(f"basename: {basename}, file: {file}")
if basename.lower() in file.lower():
for audio_file_format in audio_file_formats:
if file.lower().endswith(audio_file_format):
return gr.Dropdown(value=get_relative_path(os.path.join(srt_folder, file), folder))
return gr.Dropdown(interactive=True)
def filter_srt(input_text, min_length, filter_english, filter_words):
subtitles = parse_srt_with_lib(input_text)
filtered_subtitles = []
for subtitle in subtitles:
if count_words_multilang(subtitle.content) >= min_length:
flag = False
if filter_english:
for i in subtitle.content:
if i in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
flag = True
break
if not flag and filter_words:
filter_words.replace("\r", "\n")
for word in filter_words.split("\n"):
if word in subtitle.content:
flag = True
break
if not flag:
filtered_subtitles.append(subtitle)
return generate_srt_with_lib(filtered_subtitles)
def load_srt_from_file(srt_file):
try:
with open(srt_file, "r", encoding="utf-8") as f:
return f.read()
except:
return ""
def load_audio_from_file(audio_file):
try:
return gr.Audio(audio_file)
except:
return gr.Audio(value=None)
def load_from_dropdown(input_folder, srt_files_list, audio_files_list):
if isinstance(srt_files_list, str) and isinstance(audio_files_list, str):
srt_file= os.path.join(input_folder, srt_files_list)
audio_file = os.path.join(input_folder, audio_files_list)
return load_srt_from_file(srt_file), load_audio_from_file(audio_file)
else:
return "", gr.Audio(value=None)
def enable_gr_elements(*args):
return [gr.update(interactive=True) for _ in args]
def disable_gr_elements(*args):
return [gr.update(interactive=False) for _ in args]
def save_srt_to_file(srt_text, save_folder, character):
character_folder = os.path.join(save_folder, character)
os.makedirs(character_folder, exist_ok=True)
srt_file = os.path.join(character_folder, "merged.srt")
with open(srt_file, "w", encoding="utf-8") as f:
f.write(srt_text)
def scan_list_folders(folder):
if not os.path.exists(folder):
os.makedirs(folder, exist_ok=True)
list_folders = []
for list_folder in os.listdir(folder):
if os.path.isdir(os.path.join(folder, list_folder)):
list_folders.append(get_relative_path(os.path.join(folder, list_folder), folder))
first_list_folder = ""
second_list_folder = ""
if len(list_folders) > 0:
first_list_folder = second_list_folder = list_folders[0]
if len(list_folders) > 1:
second_list_folder = list_folders[1]
return gr.Dropdown(list_folders, value=first_list_folder), gr.Dropdown(list_folders, value=second_list_folder)
def preview_merged_list(first_list_folder, second_list_folder, merge_list_character_name, save_folder):
if first_list_folder == "" or second_list_folder == "":
return ""
if first_list_folder == second_list_folder:
gr.Warning(i18n("两个文件夹不能相同!!!"))
return ""
first_list_folder = os.path.join(save_folder, first_list_folder)
second_list_folder = os.path.join(save_folder, second_list_folder)
print(f"first_list_folder: {first_list_folder}, second_list_folder: {second_list_folder}")
first_list = os.path.join(first_list_folder, [file for file in os.listdir(first_list_folder) if file.lower().endswith(".list")][0])
second_list = os.path.join(second_list_folder, [file for file in os.listdir(second_list_folder) if file.lower().endswith(".list")][0])
try:
return merge_list_folders(first_list, second_list, merge_list_character_name, first_list_folder, second_list_folder)
except Exception as e:
gr.Warning(f"Can't Merge, Error: {e}")
return ""
from datetime import datetime
def change_character_name(input_audio):
try:
input_audio_name = os.path.basename(input_audio).rsplit(".", 1)[0]
character = input_audio_name[:20]
except:
character = datetime.now().strftime("%m%d%H%M")
return gr.Textbox(value=character)
def check_character_foldfer(folder, character):
character_folder = os.path.join(folder, character)
if os.path.exists(character_folder):
return gr.Textbox(visible=True)
return gr.Textbox(visible=False)
with gr.Blocks() as app:
with gr.Row():
gr.HTML(f"""<h1>{i18n("SRT合并切分插件")}</h1>
<p>{i18n("这是一个插件用于依靠SRT文件得到切分与打标好的音频。")}</p><p>{i18n("作者: ")}<a href="https://github.com/X-T-E-R">XTer</a></p>
<h2>{i18n("使用方法")}</h2>
<ol>
<li>{i18n("提供SRT文件可使用剪映或者ASR工具获得与原始音频文件。")}</li>
<li>{i18n("根据面板合并短句并过滤你不希望出现的句子。")}</li>
<li>{i18n("随后保存成切分好的音频与list文件。")}</li>
</ol>""")
with gr.Tabs():
with gr.Tab(i18n("SRT编辑界面")):
with gr.Row():
with gr.Column(scale=2) as input_col:
with gr.Tabs():
with gr.Tab(i18n("读取本地文件")):
input_folder = gr.Textbox("input/srt_and_audios", label=i18n("文件夹路径"),interactive=True)
scan_button = gr.Button(i18n("扫描文件夹"), variant="secondary",interactive=True)
srt_files_list = gr.Dropdown([], label=i18n("SRT文件"),interactive=True)
audio_files_list = gr.Dropdown([], label=i18n("音频文件"),interactive=True)
srt_read_button = gr.Button(i18n("读取文件"), variant="secondary",interactive=True)
with gr.Tab(i18n("上传文件")):
input_srt_file = gr.File(label=i18n("上传SRT文件"), type="filepath", file_types=["srt"])
upload_audio = gr.Audio(type="filepath",label=i18n("音频文件"))
# input_audio_file = gr.File(label=i18n("上传音频文件"), type="audio", file_types=["mp3", "wav", "ogg"])
with gr.Tabs():
with gr.Tab(i18n("内容预览")):
input_audio = gr.Textbox("", label=i18n("音频文件"),interactive=False)
input_text = gr.Textbox("", lines=20, max_lines=30, label=i18n("srt文件内容"))
input_srt_file.change(load_srt_from_file, [input_srt_file], [input_text])
with gr.Column(scale=1) as control_col:
with gr.Tabs():
with gr.Tab(i18n("合并字幕设置")):
merge_zero_interval = gr.Checkbox(label=i18n("提前合并时间间隔很短的字幕"),interactive=True, value=True)
short_interval = gr.Slider(value=0.05, minimum=0, maximum=0.5, step=0.005, label=i18n("判定为短间隔时长"),interactive=True,visible=True)
max_interval = gr.Slider(value=0.8, minimum=0.1, maximum=10, step=0.1, label=i18n("最大间隔时间"),interactive=True)
max_text_length = gr.Slider(value=50,minimum=5,maximum=200,step=1, label=i18n("最长允许单句长度"),interactive=True)
add_period = gr.Checkbox(label=i18n("句末加句号"),interactive=True, value=True)
merge_button = gr.Button(i18n("合并字幕"), variant="primary")
with gr.Tab(i18n("过滤设置")):
min_length = gr.Slider(value=5, minimum=0, maximum=20, step=1, label=i18n("允许最短长度"),interactive=True)
filter_english = gr.Checkbox(label=i18n("过滤带有英文的"),interactive=True)
filter_words = gr.Textbox("", label=i18n("过滤词语,一行一个"),lines=5,max_lines=10,interactive=True)
filter_button = gr.Button(i18n("过滤字幕"), variant="primary",interactive=False)
with gr.Tab(i18n("切分与保存")):
with gr.Group():
pre_preserve_time = gr.Slider(value=0.1, minimum=0, maximum=1, step=0.01, label=i18n("前置保留时间"),interactive=True)
post_preserve_time = gr.Slider(value=0.1, minimum=0, maximum=1, step=0.01, label=i18n("后置保留时间"),interactive=True)
pre_silence_time = gr.Slider(value=0.05, minimum=0, maximum=1, step=0.01, label=i18n("前置添加静音时间"),interactive=True,visible=False)
post_silence_time = gr.Slider(value=0.1, minimum=0, maximum=1, step=0.01, label=i18n("后置添加静音时间"),interactive=True,visible=False)
with gr.Group():
language = gr.Dropdown([i18n(i) for i in [ "ZH", "EN", "JA"]], value="ZH", label=i18n("语言"),interactive=True)
audio_format = gr.Dropdown(["mp3", "wav", "ogg"], value="wav", label=i18n("音频格式"),interactive=True)
with gr.Group():
save_folder = gr.Textbox("output/sliced_audio", label=i18n("保存文件夹"),interactive=True)
character = gr.Textbox("character", label=i18n("保存子文件夹名称"),interactive=True)
character_warning = gr.Textbox(i18n("注意:该文件夹已存在"), label=i18n("提示"),interactive=False,visible=False)
save_srt_button = gr.Button(i18n("保存合并后字幕"),variant="secondary",interactive=True)
slice_audio_button = gr.Button(i18n("切分并保存音频、list"), variant="primary",interactive=False)
with gr.Column(scale=2) as output_col:
with gr.Tabs():
with gr.Tab(i18n("合并后srt文本")):
output_text = gr.Textbox("", lines=20, max_lines=30, label="Sliced SRT")
with gr.Tab(i18n("切分预览")):
gr.Textbox(i18n("正在建设,敬请期待"), label=i18n("提示"),interactive=False)
with gr.Tab(i18n("List 合并小工具")):
with gr.Row():
with gr.Column(scale=2):
scan_list_folder = gr.Textbox("output/sliced_audio", label=i18n("文件夹路径"),interactive=True)
scan_list_button = gr.Button(i18n("扫描文件夹"), variant="secondary")
first_list_folder = gr.Dropdown([], label=i18n("主文件夹"),interactive=True)
second_list_folder = gr.Dropdown([], label=i18n("次文件夹"),interactive=True)
merge_list_character_name = gr.Textbox("", label=i18n("角色名称,留空使用主文件夹的"),interactive=True)
merge_list_button = gr.Button(i18n("合并文件夹与List"), variant="primary")
with gr.Column(scale=2):
list_preview = gr.Textbox("", lines=20, max_lines=30, label=i18n("合并后的List"))
scan_list_button.click(scan_list_folders, [scan_list_folder], [first_list_folder, second_list_folder])
merge_list_button.click(preview_merged_list, [first_list_folder, second_list_folder, merge_list_character_name, scan_list_folder], [list_preview])
save_folder.change(lambda x:gr.Textbox(value=x), [save_folder], [scan_list_folder])
scan_list_folder.change(lambda x:gr.Textbox(value=x), [scan_list_folder], [save_folder])
scan_button.click(get_srt_and_audio_files, [input_folder], [srt_files_list, audio_files_list])
merge_zero_interval.change(lambda x: gr.update(visible=x), [merge_zero_interval],[short_interval])
srt_files_list.change(change_srt_file, [input_folder, srt_files_list], [audio_files_list])
srt_read_button.click(
load_from_dropdown,
[input_folder, srt_files_list, audio_files_list],
[input_text, input_audio],
)
input_text.change(
disable_gr_elements,
[slice_audio_button, filter_button],
[slice_audio_button, filter_button],
).then(
change_character_name,
[input_audio],
[character],
)
upload_audio.change(
change_character_name,
[upload_audio],
[character],
).then(
lambda x:gr.Textbox(value=x),
[upload_audio],
[input_audio],
)
merge_button.click(
merge_srt,
[
input_text,
output_text,
short_interval,
max_interval,
max_text_length,
add_period,
merge_zero_interval
],
[output_text],
).then(
enable_gr_elements,
[slice_audio_button, filter_button],
[slice_audio_button, filter_button],
)
slice_audio_button.click(
slice_audio,
[
input_audio,
save_folder,
audio_format,
output_text,
pre_preserve_time,
post_preserve_time,
pre_silence_time,
post_silence_time,
language,
character
],
)
save_srt_button.click(
save_srt_to_file,
[output_text, save_folder, character],
)
filter_button.click(
filter_srt,
[output_text, min_length, filter_english, filter_words],
[output_text],
)
character.change(
check_character_foldfer,
[save_folder, character],
[character_warning],
)
if gr.__version__.split(".")[0] == "4":
app.launch(
server_name="0.0.0.0",
inbrowser=True,
share=is_share,
server_port=port,
quiet=True,
)
else:
app.queue(concurrency_count=511, max_size=1022).launch(
server_name="0.0.0.0",
inbrowser=True,
share=is_share,
server_port=port,
quiet=True,
)