File size: 6,846 Bytes
c9612c1
 
a5ff31f
c9612c1
e70c3e8
73c9093
be55105
 
 
 
c9612c1
be55105
 
c9612c1
 
 
 
be55105
 
 
38fcd18
 
3cf90f7
 
 
 
 
 
 
 
38fcd18
 
e70c3e8
 
 
 
be55105
0e83a05
6b5a751
 
be55105
 
0e83a05
 
 
 
be55105
58f4eed
be55105
 
73c9093
be55105
73c9093
be55105
73c9093
 
 
 
5ebcbb6
be55105
 
6b5a751
be55105
 
c9612c1
be55105
 
c9612c1
3cf90f7
be55105
 
 
 
 
 
3cf90f7
be55105
 
 
3cf90f7
0e83a05
c9612c1
be55105
 
3cf90f7
0e83a05
 
be55105
c9612c1
be55105
0e83a05
be55105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3cf90f7
 
be55105
 
 
 
 
 
 
 
 
 
 
 
0e83a05
be55105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3cf90f7
be55105
 
 
3cf90f7
be55105
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import moviepy.editor as mp
import librosa
from transformers import pipeline
from concurrent.futures import ThreadPoolExecutor
import tempfile
import docx  # To create Word documents
from moviepy.video.tools.subtitles import SubtitlesClip
from moviepy.editor import TextClip
import os

# Load Whisper model for speech-to-text (using smaller 'tiny' model for faster performance)
asr = pipeline("automatic-speech-recognition", model="openai/whisper-tiny")  # Use 'whisper-tiny' for faster transcription

# MarianMT or M2M100 for translation (multi-language)
translator = pipeline("translation", model="facebook/m2m100_418M")

# Store generated subtitles and translations
subtitle_storage = {}

# Supported languages with their codes
languages = {
    "Persian": "fa",
    "French": "fr",
    "Spanish": "es",
    "German": "de",
    "Chinese": "zh",
    "Arabic": "ar",
    "Hindi": "hi",
    "Russian": "ru"
}

def transcribe_audio(chunk):
    """Transcribe a single audio chunk."""
    return asr(chunk)["text"]

def add_subtitle(video):
    try:
        # The video is passed as a file path string, so we use it directly
        video_path = video if isinstance(video, str) else None
        if not video_path:
            return "No video provided!"
        
        video = mp.VideoFileClip(video_path)
        audio = video.audio

        # Use a temporary file for audio extraction
        with tempfile.NamedTemporaryFile(delete=True, suffix='.wav') as tmp_audio_file:
            audio.write_audiofile(tmp_audio_file.name, codec='pcm_s16le')
            waveform, sr = librosa.load(tmp_audio_file.name, sr=16000)

            # Transcribe in chunks (parallel)
            chunk_duration = 15  # seconds
            chunk_size = sr * chunk_duration
            chunks = [waveform[i:i + chunk_size] for i in range(0, len(waveform), chunk_size) if len(waveform[i:i + chunk_size]) > 0]

            with ThreadPoolExecutor() as executor:
                transcriptions = list(executor.map(transcribe_audio, chunks))

            full_transcription = " ".join(transcriptions)
            subtitle_storage["original"] = full_transcription  # Store the original subtitle
            subtitle_storage["video_path"] = video_path  # Store the video path
            
        return f"Subtitle added: {full_transcription[:100]}..."  # Display first 100 characters

    except Exception as e:
        return f"Error in adding subtitle: {e}"

def translate_subtitle(video, language):
    try:
        # Translate the stored subtitle
        original_subtitle = subtitle_storage.get("original")
        if not original_subtitle:
            return "No subtitle to translate!"
        
        # Translate using the selected language
        translated_subtitle = translator(
            original_subtitle, 
            src_lang="en",  # Source language (assuming the subtitle is in English)
            tgt_lang=languages[language]  # Get the language code from the dropdown selection
        )[0]["translation_text"]

        subtitle_storage["translated"] = translated_subtitle  # Store the translated subtitle
        
        return f"Subtitle translated to {language} successfully!"
    
    except Exception as e:
        return f"Error in translating subtitle: {e}"

def download_word():
    try:
        # Save translated subtitles to a Word document
        translated_subtitle = subtitle_storage.get("translated")
        if not translated_subtitle:
            return "No translated subtitle to save!"
        
        doc = docx.Document()
        doc.add_heading('Translated Subtitles', 0)
        doc.add_paragraph(translated_subtitle)
        
        file_path = "translated_subtitles.docx"
        doc.save(file_path)

        return f"Translated subtitles saved as Word document: {file_path}"
    
    except Exception as e:
        return f"Error in saving subtitles as Word: {e}"

def download_video():
    try:
        # Add subtitles to the video
        original_subtitle = subtitle_storage.get("original")
        translated_subtitle = subtitle_storage.get("translated")

        if not original_subtitle or not translated_subtitle:
            return "No subtitles to overlay on video!"

        video_path = subtitle_storage.get("video_path")
        video = mp.VideoFileClip(video_path)

        # Function to generate subtitle text
        generator = lambda txt: TextClip(txt, font='Arial', fontsize=24, color='white')

        # Simulated subtitle time intervals for simplicity (assumes 5 seconds per subtitle)
        subs = [(i * 5, translated_subtitle[i:i+50]) for i in range(0, len(translated_subtitle), 50)]

        # Create subtitle clips
        subtitles = SubtitlesClip(subs, generator)

        # Overlay subtitles on video
        subtitled_video = mp.CompositeVideoClip([video, subtitles.set_position(('center', 'bottom'))])

        output_video_path = "subtitled_video.mp4"
        subtitled_video.write_videofile(output_video_path)

        return f"Subtitled video is ready for download: {output_video_path}"
    
    except Exception as e:
        return f"Error in generating subtitled video: {e}"

# Gradio UI Interface
with gr.Blocks() as demo:
    # Title
    gr.Markdown("<h1 style='text-align: center;'>Video Subtitle Translator</h1>")
    
    # Video Upload
    with gr.Row():
        video_input = gr.Video(label="Upload Video")
        upload_button = gr.Button("Upload Video")
        upload_status = gr.Textbox(label="Upload Status")
    
    upload_button.click(add_subtitle, inputs=video_input, outputs=upload_status)
    
    # Add Subtitle
    with gr.Row():
        add_subtitle_button = gr.Button("Add Subtitle")
        subtitle_status = gr.Textbox(label="Subtitle Status")
    
    add_subtitle_button.click(add_subtitle, inputs=video_input, outputs=subtitle_status)
    
    # Translate Subtitle
    with gr.Row():
        language_dropdown = gr.Dropdown(choices=list(languages.keys()), label="Choose Target Language", value="Persian")
        translate_button = gr.Button("Translate Subtitle")
        translate_status = gr.Textbox(label="Translation Status")
    
    translate_button.click(translate_subtitle, inputs=[video_input, language_dropdown], outputs=translate_status)
    
    # Download as Word
    with gr.Row():
        download_button = gr.Button("Download as Word")
        download_status = gr.Textbox(label="Download Status")
    
    download_button.click(download_word, inputs=None, outputs=download_status)
    
    # Download Subtitled Video
    with gr.Row():
        download_video_button = gr.Button("Download Subtitled Video")
        download_video_status = gr.Textbox(label="Download Video Status")
    
    download_video_button.click(download_video, inputs=None, outputs=download_video_status)

# Launch the Gradio app
demo.launch()