Spaces:
Sleeping
Sleeping
File size: 10,312 Bytes
06f92fc 8de7fa2 9de0758 8de7fa2 9de0758 2a190c5 8de7fa2 9de0758 8de7fa2 9de0758 8de7fa2 5ef7568 7a8f40a 3765580 7a8f40a 19673f9 6dc088c 2648649 b54375c 7a8f40a 9de0758 5ef7568 9de0758 2a190c5 5ef7568 9de0758 5ef7568 9de0758 6dc088c 2648649 6dc088c 2648649 6dc088c 7a8f40a 2648649 7a8f40a 9de0758 3765580 7a8f40a 06f92fc 9de0758 06f92fc 9de0758 06f92fc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
import gradio as gr
from transformers import MarianMTModel, MarianTokenizer, pipeline
import pysrt
import tempfile
from tqdm import tqdm
from langdetect import detect
import os
from datetime import timedelta
# Danh sách các ngôn ngữ và model tương ứng
LANGUAGE_MODELS = {
"Tiếng Anh": "en",
"Tiếng Việt": "vi",
"Tiếng Pháp": "fr",
"Tiếng Đức": "de",
"Tiếng Tây Ban Nha": "es",
"Tiếng Bồ Đào Nha": "pt",
"Tiếng Ý": "it",
"Tiếng Nga": "ru",
"Tiếng Hà Lan": "nl",
"Tiếng Thụy Điển": "sv",
"Tiếng Phần Lan": "fi",
"Tiếng Đan Mạch": "da",
"Tiếng Na Uy": "no",
"Tiếng Ba Lan": "pl",
"Tiếng Séc": "cs",
"Tiếng Hungary": "hu",
"Tiếng Romania": "ro",
"Tiếng Hy Lạp": "el",
"Tiếng Thổ Nhĩ Kỳ": "tr",
"Tiếng Hindi": "hi",
"Tiếng Ả Rập": "ar",
"Tiếng Trung (Giản thể)": "zh",
"Tiếng Nhật": "ja",
"Tiếng Hàn": "ko"
}
# Đảo ngược dictionary để lấy code từ tên ngôn ngữ
LANGUAGE_CODES = {v: k for k, v in LANGUAGE_MODELS.items()}
# Cache models để tăng tốc độ
model_cache = {}
detector = pipeline("text-classification", model="papluca/xlm-roberta-base-language-detection")
def detect_subtitle_language(file_path):
try:
subs = pysrt.open(file_path)
sample_text = " ".join([sub.text for sub in subs[:10] if sub.text.strip()])
if not sample_text:
return "en" # Mặc định là tiếng Anh nếu không phát hiện được
try:
# Sử dụng langdetect cho đơn giản
lang_code = detect(sample_text)
return lang_code
except:
# Fallback sử dụng model xlm-roberta
result = detector(sample_text[:512])[0] # Giới hạn độ dài đầu vào
return result['label'].split('__')[-1]
except Exception as e:
print(f"Error detecting language: {e}")
return "en"
def get_model(source_lang, target_lang):
model_key = f"{source_lang}-{target_lang}"
if model_key not in model_cache:
model_name = f"Helsinki-NLP/opus-mt-{model_key}"
try:
tokenizer = MarianTokenizer.from_pretrained(model_name)
model = MarianMTModel.from_pretrained(model_name)
model_cache[model_key] = (model, tokenizer)
except:
# Fallback: Dịch qua tiếng Anh nếu không có model trực tiếp
if source_lang != "en":
# Dịch từ ngôn ngữ nguồn -> tiếng Anh -> ngôn ngữ đích
model1_name = f"Helsinki-NLP/opus-mt-{source_lang}-en"
model2_name = f"Helsinki-NLP/opus-mt-en-{target_lang}"
tokenizer1 = MarianTokenizer.from_pretrained(model1_name)
model1 = MarianMTModel.from_pretrained(model1_name)
tokenizer2 = MarianTokenizer.from_pretrained(model2_name)
model2 = MarianMTModel.from_pretrained(model2_name)
model_cache[model_key] = ((model1, tokenizer1), (model2, tokenizer2))
else:
raise gr.Error(f"Không tìm thấy model dịch từ {source_lang} sang {target_lang}")
return model_cache[model_key]
def translate_text(text, model, tokenizer):
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
translated = model.generate(**inputs)
return tokenizer.batch_decode(translated, skip_special_tokens=True)[0]
def add_time_to_subtitle(input_file, hours, minutes, seconds):
if input_file is None:
raise gr.Error("Vui lòng upload file phụ đề!")
try:
if not os.path.exists(input_file):
raise gr.Error("File không tồn tại hoặc không thể đọc!")
subs = pysrt.open(input_file)
# Chuyển đổi thời gian nhập vào thành mili giây (hỗ trợ số thập phân)
try:
seconds_float = float(seconds)
except ValueError:
seconds_float = 0
total_milliseconds = int((int(hours) * 3600 + int(minutes) * 60 + seconds_float) * 1000)
# Thêm thời gian vào tất cả các phụ đề
if total_milliseconds > 0:
for sub in subs:
sub.start.ordinal += total_milliseconds
sub.end.ordinal += total_milliseconds
# Lưu file tạm
output_path = tempfile.NamedTemporaryFile(suffix=".srt", delete=False).name
subs.save(output_path, encoding='utf-8')
return output_path, f"Đã thêm {hours}h {minutes}m {seconds_float}s vào file gốc"
except Exception as e:
raise gr.Error(f"Có lỗi xảy ra khi thêm thời gian: {str(e)}")
def translate_subtitle(input_file, source_language, target_language, hours, minutes, seconds):
if input_file is None:
raise gr.Error("Vui lòng upload file phụ đề!")
try:
if not os.path.exists(input_file):
raise gr.Error("File không tồn tại hoặc không thể đọc!")
source_code = LANGUAGE_MODELS.get(source_language, "en")
target_code = LANGUAGE_MODELS[target_language]
model_info = get_model(source_code, target_code)
subs = pysrt.open(input_file)
# Chuyển đổi thời gian nhập vào thành mili giây (hỗ trợ số thập phân)
try:
seconds_float = float(seconds)
except ValueError:
seconds_float = 0
total_milliseconds = int((int(hours) * 3600 + int(minutes) * 60 + seconds_float) * 1000)
# Thêm thời gian vào tất cả các phụ đề
if total_milliseconds > 0:
for sub in subs:
sub.start.ordinal += total_milliseconds
sub.end.ordinal += total_milliseconds
# Xử lý dịch thuật
if isinstance(model_info[0], tuple):
# Dịch qua tiếng Anh
model1, tokenizer1 = model_info[0]
model2, tokenizer2 = model_info[1]
for sub in tqdm(subs, desc="Đang dịch"):
if sub.text.strip():
en_text = translate_text(sub.text, model1, tokenizer1)
sub.text = translate_text(en_text, model2, tokenizer2)
else:
# Dịch trực tiếp
model, tokenizer = model_info
for sub in tqdm(subs, desc="Đang dịch"):
if sub.text.strip():
sub.text = translate_text(sub.text, model, tokenizer)
# Lưu file tạm
output_path = tempfile.NamedTemporaryFile(suffix=".srt", delete=False).name
subs.save(output_path, encoding='utf-8')
return output_path, f"Dịch từ {source_language} sang {target_language} thành công! Đã thêm {hours}h {minutes}m {seconds_float}s"
except Exception as e:
raise gr.Error(f"Có lỗi xảy ra: {str(e)}")
# Giao diện Gradio
with gr.Blocks(title="Subtitle Translator Pro", theme="soft") as demo:
gr.Markdown("# 🎬 Subtitle Translator Pro")
gr.Markdown("Dịch phụ đề (.srt) giữa nhiều ngôn ngữ khác nhau")
with gr.Row():
with gr.Column():
file_input = gr.File(label="Upload file phụ đề (.srt)", file_types=[".srt"])
with gr.Row():
source_lang = gr.Dropdown(
choices=list(LANGUAGE_MODELS.keys()),
value="Tiếng Anh",
label="Ngôn ngữ nguồn",
interactive=True
)
auto_detect = gr.Checkbox(label="Tự động phát hiện ngôn ngữ", value=True)
target_lang = gr.Dropdown(
choices=list(LANGUAGE_MODELS.keys()),
value="Tiếng Việt",
label="Ngôn ngữ đích"
)
with gr.Row():
hours = gr.Number(label="Giờ", value=0, precision=0, minimum=0)
minutes = gr.Number(label="Phút", value=0, precision=0, minimum=0, maximum=59)
seconds = gr.Number(label="Giây", value=0, minimum=0, step=0.1)
with gr.Row():
add_time_btn = gr.Button("Chỉ thêm thời gian", variant="secondary")
translate_btn = gr.Button("Dịch phụ đề", variant="primary")
with gr.Column():
file_output = gr.File(label="File phụ đề đã xử lý", interactive=False)
status = gr.Textbox(label="Trạng thái")
# Xử lý khi upload file
def on_file_upload(file, auto_detect_flag):
if file and auto_detect_flag:
try:
lang_code = detect_subtitle_language(file.name)
detected_lang = LANGUAGE_CODES.get(lang_code, "Tiếng Anh")
return gr.Dropdown(value=detected_lang)
except:
return gr.Dropdown(value="Tiếng Anh")
return gr.Dropdown()
file_input.upload(
fn=on_file_upload,
inputs=[file_input, auto_detect],
outputs=source_lang
)
# Xử lý khi nhấn nút thêm thời gian
add_time_btn.click(
fn=add_time_to_subtitle,
inputs=[file_input, hours, minutes, seconds],
outputs=[file_output, status]
)
# Xử lý khi nhấn nút dịch phụ đề
translate_btn.click(
fn=translate_subtitle,
inputs=[file_input, source_lang, target_lang, hours, minutes, seconds],
outputs=[file_output, status]
)
gr.Markdown("### Thông tin")
gr.Markdown("""
- Hỗ trợ định dạng .srt
- Tự động phát hiện ngôn ngữ nguồn
- Dịch giữa 24 ngôn ngữ khác nhau
- Hỗ trợ dịch qua tiếng Anh nếu không có model trực tiếp
- Thêm thời gian vào tất cả phụ đề (hỗ trợ giây thập phân)
- Có nút riêng để chỉ thêm thời gian trước khi dịch
""")
if __name__ == "__main__":
demo.launch() |