import gradio as gr from subtitle import subtitle_maker,LANGUAGE_CODE source_lang_list = ['Automatic', "English", "Hindi", "Bengali"] available_language = LANGUAGE_CODE.keys() source_lang_list.extend(available_language) target_lang_list = ["English", "Hindi", "Bengali"] target_lang_list.extend(available_language) def update_target_lang(selected_src): """Update target language automatically when source changes.""" if selected_src == "Automatic": return "English" else: return selected_src def ui1(): with gr.Blocks() as demo: gr.HTML("""

🎬 Auto Subtitle Generator

If you have a large video, upload the audio instead, it's much faster to upload.

😇 Run on Google Colab
""") with gr.Row(): with gr.Column(): upload_media = gr.File(label="Upload Audio or Video File") input_lang = gr.Dropdown(label="Source Language", choices=source_lang_list, value="English") generate_btn = gr.Button("🚀 Generate Subtitle", variant="primary") with gr.Accordion("⚙️ Translation using Google Translator", open=False): output_lang = gr.Dropdown(label="Translate Into", choices=target_lang_list, value="English") with gr.Column(): default_srt = gr.File(label="🎯 Original Subtitles (Default Generated by whisper)") customized_srt = gr.File(label="📝 Readable Subtitles (Multi-line)") word_level_srt = gr.File(label="🔠 Word-by-Word Subtitles") with gr.Accordion("🌍 Other Subtitle Formats", open=False): translated_srt = gr.File(label="🌐 Translated Subtitles") shorts_srt = gr.File(label="📱 Shorts/Reels Subtitles") transcript_txt = gr.File(label="📄 Full Transcript (Text File)") subtitle_json= gr.File(label="📄 Full Transcript (JSON File) To make .ass file") word_json= gr.File(label="📄 Shorts Transcript (JSON File) To make .ass file") transcript_box = gr.Textbox(label="🗒️ Transcript Preview", lines=4,show_copy_button=True) generate_btn.click( fn=subtitle_maker, inputs=[upload_media, input_lang, output_lang], outputs=[default_srt, translated_srt, customized_srt, word_level_srt, shorts_srt, transcript_txt, subtitle_json,word_json,transcript_box] ) input_lang.change( fn=update_target_lang, inputs=input_lang, outputs=output_lang ) # Add example runs (optional) # gr.Examples( # examples=[ # ["sample.mp3", "English", "English"], # ["sample.wav", "English", "Hindi"], # ], # inputs=[upload_media, input_lang, output_lang] # ) return demo def prompt_translation(language): """ Generates a dubbing-friendly translation prompt for an .srt subtitle file. Tailored for natural speech and timing accuracy. """ prompt = f""" -------------- You are a professional subtitle translator for **video dubbing**. Translate the following `.srt` subtitle file into **{language}** while preserving timing, meaning, and emotional tone. Output in JSON format exactly like this: ```json {{ "subtitle sequence number": {{ "timestamp": "original timestamp", "actual subtitle text": "original English subtitle line", "dubbing": "natural, dubbing-friendly {language} translation" }} }} ``` **Guidelines for Translation:** 1. **Understand the full context** before translating — read the entire subtitle file first. 2. Translate into **natural, conversational {language}**, not a direct word-for-word translation. 6. Keep translations **roughly similar in length** to the original so lip movements sync naturally. """ return prompt def prompt_fix_grammar(language="English"): """ Generates a dubbing-friendly grammar correction prompt for an .srt subtitle file. Tailored for natural speech and timing accuracy. """ prompt = f""" -------------- You are a professional subtitle editor for **video dubbing**. Fix the grammar, spelling, and awkward phrasing in the following `.srt` subtitle file while preserving timing, meaning, and emotional tone.   Do NOT translate — keep everything in {language}. Output in JSON format exactly like this: ```json {{ "subtitle sequence number": {{ "timestamp": "original timestamp", "actual subtitle text": "original {language} subtitle line", "dubbing": "natural, dubbing-friendly corrected {language} line" }} }} ``` **Guidelines for Grammar Fixing:** 1. **Understand the full context** before editing — read the entire subtitle file first. 2. Correct grammar, spelling, and phrasing errors while keeping the same meaning. 4. Keep corrections **roughly similar in length** to the original so lip movements sync naturally. """ return prompt def prompt_srt_to_romanized(language="Hindi"): """ Generates a prompt for converting a .srt subtitle file from any language to a Romanized (Latin letters) version, preserving timing, meaning, punctuation, and formatting. """ prompt = f""" -------------- You are a professional subtitle editor tasked with converting subtitles to Romanized text. Your task is to convert a `.srt` subtitle file from {language} to **Romanized {language}**, keeping everything exactly the same except using Latin letters for all words. **Instructions:** 1. Preserve the original timestamp of each subtitle. 2. Keep the original meaning, punctuation, and formatting intact. 3. Convert **only the original subtitle text** to Roman letters, word by word. 4. Do not add, remove, or change any words. 5. Output in strict JSON format exactly like this: ```json {{ "subtitle sequence number": {{ "timestamp": "original timestamp", "original subtitle text": "original {language} subtitle line", "dubbing": "Romanized, {language} line of original subtitle text" }} }} ```` Focus entirely on **accurate Romanization**; do not modify anything else. """ return prompt import pysrt def prompt_maker(srt_path, target_language, task="Translation"): txt_path = srt_path.replace(".srt", ".txt") subs = pysrt.open(srt_path, encoding='utf-8') with open(txt_path, 'w', encoding='utf-8') as f: for sub in subs: f.write(f"{sub.index}\n") f.write(f"{sub.start} --> {sub.end}\n") f.write(f"{sub.text}\n\n") if task == "Translation": f.write(prompt_translation(target_language)) if task=="Romanization": f.write(prompt_srt_to_romanized(target_language)) else: f.write(prompt_fix_grammar(target_language)) with open(txt_path, 'r', encoding='utf-8') as f: content = f.read() # return both prompt text and original path return content, srt_path import pysrt import json import os def json_to_srt(json_script, srt_path): """ Convert dubbing-friendly JSON back into .srt Uses original srt_path to name output _dubbing.srt """ os.makedirs("./dubbing_srt", exist_ok=True) base_name = os.path.basename(srt_path) name_no_ext, _ = os.path.splitext(base_name) output_srt_path = os.path.join("./dubbing_srt", f"{name_no_ext}_dubbing.srt") # Load JSON if isinstance(json_script, str): json_object = json.loads(json_script) else: json_object = json_script # Write to file with open(output_srt_path, "w", encoding="utf-8") as f: for i, (key, value) in enumerate(json_object.items(), start=1): f.write(f"{i}\n") f.write(f"{value['timestamp']}\n") f.write(f"{value['dubbing']}\n\n") return output_srt_path def ui2(): with gr.Blocks() as demo: gr.Markdown("

🎬 Subtitle Translation Using LLM

") # hidden state to keep original srt path srt_state = gr.State("") with gr.Row(): with gr.Column(): gr.Markdown("### Step 1: Generate Prompt") srt_file = gr.File(label="Upload .srt file generated by Whisper", file_types=[".srt"]) task = gr.Dropdown( ["Translation","Romanization","Fix Grammar [English to English for dubbing]"], label="Select Task", value="Translation", ) language = gr.Dropdown(target_lang_list, label="Select the language you want to translate into", value="English") generate_btn = gr.Button("Generate Prompt") output_prompt = gr.Textbox( label="Copy & Paste this prompt in https://aistudio.google.com/", lines=20, show_copy_button=True ) with gr.Column(): gr.Markdown("### Step 2: Paste JSON & Convert Back to SRT") json_input = gr.Textbox( label="Paste JSON script from https://aistudio.google.com/ ", lines=20, placeholder="Paste the JSON output here..." ) convert_btn = gr.Button("Convert JSON → SRT") srt_file_out = gr.File(label="Download new .srt") # Button actions generate_btn.click( fn=prompt_maker, inputs=[srt_file, language, task], outputs=[output_prompt, srt_state], ) convert_btn.click( fn=json_to_srt, inputs=[json_input, srt_state], outputs=srt_file_out, ) return demo import click @click.command() @click.option("--debug", is_flag=True, default=False, help="Enable debug mode.") @click.option("--share", is_flag=True, default=False, help="Enable sharing of the interface.") def main(share,debug): # def main(debug=True, share=True): demo1 = ui1() demo2 = ui2() custom_css = """.gradio-container { font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif; }""" demo = gr.TabbedInterface([demo1, demo2], ["Generate SRT File", "SRT Translation"], title="",theme=gr.themes.Soft(),css=custom_css) demo.queue().launch(share=share,debug=debug) if __name__ == "__main__": main()