Spaces:
Runtime error
Runtime error
Update 1
Browse files
app.py
CHANGED
@@ -8,8 +8,6 @@ import docx # To create Word documents
|
|
8 |
from moviepy.video.tools.subtitles import SubtitlesClip
|
9 |
from moviepy.editor import TextClip
|
10 |
from pytube import YouTube # For downloading YouTube videos
|
11 |
-
from moviepy.editor import TextClip, CompositeVideoClip
|
12 |
-
from moviepy.video.tools.subtitles import SubtitlesClip
|
13 |
|
14 |
# Load Whisper model for speech-to-text (using smaller 'tiny' model for faster performance)
|
15 |
asr = pipeline("automatic-speech-recognition", model="openai/whisper-tiny")
|
@@ -48,37 +46,36 @@ def transcribe_audio(chunk):
|
|
48 |
|
49 |
def add_subtitle(video):
|
50 |
try:
|
51 |
-
# The video is passed as a file path string, so we use it directly
|
52 |
video_path = video if isinstance(video, str) else None
|
53 |
if not video_path:
|
54 |
return "No video provided!"
|
55 |
|
56 |
video = mp.VideoFileClip(video_path)
|
57 |
audio = video.audio
|
58 |
-
|
59 |
-
#
|
60 |
-
with tempfile.NamedTemporaryFile(delete=
|
61 |
audio.write_audiofile(tmp_audio_file.name, codec='pcm_s16le')
|
62 |
waveform, sr = librosa.load(tmp_audio_file.name, sr=16000)
|
63 |
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
|
|
71 |
|
72 |
-
full_transcription = " ".join(transcriptions)
|
73 |
-
subtitle_storage["original"] = full_transcription # Store the original subtitle
|
74 |
-
subtitle_storage["video_path"] = video_path # Store the video path
|
75 |
-
|
76 |
return f"Subtitle added: {full_transcription[:100]}..." # Display first 100 characters
|
77 |
|
78 |
except Exception as e:
|
79 |
return f"Error in adding subtitle: {e}"
|
80 |
|
81 |
-
def translate_subtitle(
|
82 |
try:
|
83 |
# Translate the stored subtitle
|
84 |
original_subtitle = subtitle_storage.get("original")
|
@@ -138,20 +135,20 @@ def download_video():
|
|
138 |
video_path = subtitle_storage.get("video_path")
|
139 |
video = mp.VideoFileClip(video_path)
|
140 |
|
141 |
-
#
|
142 |
-
generator = lambda txt: TextClip(txt, font="Arial", fontsize=24, color="white", method=
|
143 |
|
144 |
subs = []
|
145 |
-
subtitle_length = 5 # seconds
|
146 |
for i in range(0, len(translated_subtitle), 50):
|
147 |
start_time = (i // 50) * subtitle_length
|
148 |
-
end_time = start_time + subtitle_length
|
149 |
subtitle_text = translated_subtitle[i:i + 50]
|
150 |
subs.append(((start_time, end_time), subtitle_text))
|
151 |
|
152 |
subtitles = SubtitlesClip(subs, generator)
|
153 |
|
154 |
-
subtitled_video = CompositeVideoClip([video, subtitles.set_position(('center', 'bottom'))])
|
155 |
|
156 |
output_video_path = "subtitled_video.mp4"
|
157 |
subtitled_video.write_videofile(output_video_path)
|
@@ -161,7 +158,6 @@ def download_video():
|
|
161 |
except Exception as e:
|
162 |
return f"Error in generating subtitled video: {e}"
|
163 |
|
164 |
-
|
165 |
# Gradio UI Interface
|
166 |
with gr.Blocks() as demo:
|
167 |
# Title
|
@@ -189,21 +185,21 @@ with gr.Blocks() as demo:
|
|
189 |
translate_button = gr.Button("Translate Subtitle")
|
190 |
translate_status = gr.Textbox(label="Translation Status")
|
191 |
|
192 |
-
translate_button.click(translate_subtitle, inputs=
|
193 |
|
194 |
# Download as Word
|
195 |
with gr.Row():
|
196 |
-
|
197 |
-
|
198 |
|
199 |
-
|
200 |
|
201 |
# Download Subtitled Video
|
202 |
with gr.Row():
|
203 |
-
|
204 |
download_video_status = gr.Textbox(label="Download Video Status")
|
205 |
|
206 |
-
|
207 |
|
208 |
# Launch the Gradio app
|
209 |
demo.launch()
|
|
|
8 |
from moviepy.video.tools.subtitles import SubtitlesClip
|
9 |
from moviepy.editor import TextClip
|
10 |
from pytube import YouTube # For downloading YouTube videos
|
|
|
|
|
11 |
|
12 |
# Load Whisper model for speech-to-text (using smaller 'tiny' model for faster performance)
|
13 |
asr = pipeline("automatic-speech-recognition", model="openai/whisper-tiny")
|
|
|
46 |
|
47 |
def add_subtitle(video):
|
48 |
try:
|
|
|
49 |
video_path = video if isinstance(video, str) else None
|
50 |
if not video_path:
|
51 |
return "No video provided!"
|
52 |
|
53 |
video = mp.VideoFileClip(video_path)
|
54 |
audio = video.audio
|
55 |
+
|
56 |
+
# Extract audio to a temporary file
|
57 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix='.wav') as tmp_audio_file:
|
58 |
audio.write_audiofile(tmp_audio_file.name, codec='pcm_s16le')
|
59 |
waveform, sr = librosa.load(tmp_audio_file.name, sr=16000)
|
60 |
|
61 |
+
# Transcribe in chunks (parallel)
|
62 |
+
chunk_duration = 15 # seconds
|
63 |
+
chunk_size = sr * chunk_duration
|
64 |
+
chunks = [waveform[i:i + chunk_size] for i in range(0, len(waveform), chunk_size)]
|
65 |
|
66 |
+
with ThreadPoolExecutor() as executor:
|
67 |
+
transcriptions = list(executor.map(transcribe_audio, chunks))
|
68 |
+
|
69 |
+
full_transcription = " ".join(transcriptions)
|
70 |
+
subtitle_storage["original"] = full_transcription
|
71 |
+
subtitle_storage["video_path"] = video_path
|
72 |
|
|
|
|
|
|
|
|
|
73 |
return f"Subtitle added: {full_transcription[:100]}..." # Display first 100 characters
|
74 |
|
75 |
except Exception as e:
|
76 |
return f"Error in adding subtitle: {e}"
|
77 |
|
78 |
+
def translate_subtitle(language):
|
79 |
try:
|
80 |
# Translate the stored subtitle
|
81 |
original_subtitle = subtitle_storage.get("original")
|
|
|
135 |
video_path = subtitle_storage.get("video_path")
|
136 |
video = mp.VideoFileClip(video_path)
|
137 |
|
138 |
+
# Generate subtitle text without ImageMagick (using TextClip with a basic font)
|
139 |
+
generator = lambda txt: TextClip(txt, font="Arial-Bold", fontsize=24, color="white", method='label') # Use 'label'
|
140 |
|
141 |
subs = []
|
142 |
+
subtitle_length = 5 # seconds each subtitle will be displayed
|
143 |
for i in range(0, len(translated_subtitle), 50):
|
144 |
start_time = (i // 50) * subtitle_length
|
145 |
+
end_time = start_time + subtitle_length # Each subtitle lasts for 'subtitle_length' seconds
|
146 |
subtitle_text = translated_subtitle[i:i + 50]
|
147 |
subs.append(((start_time, end_time), subtitle_text))
|
148 |
|
149 |
subtitles = SubtitlesClip(subs, generator)
|
150 |
|
151 |
+
subtitled_video = mp.CompositeVideoClip([video, subtitles.set_position(('center', 'bottom'))])
|
152 |
|
153 |
output_video_path = "subtitled_video.mp4"
|
154 |
subtitled_video.write_videofile(output_video_path)
|
|
|
158 |
except Exception as e:
|
159 |
return f"Error in generating subtitled video: {e}"
|
160 |
|
|
|
161 |
# Gradio UI Interface
|
162 |
with gr.Blocks() as demo:
|
163 |
# Title
|
|
|
185 |
translate_button = gr.Button("Translate Subtitle")
|
186 |
translate_status = gr.Textbox(label="Translation Status")
|
187 |
|
188 |
+
translate_button.click(translate_subtitle, inputs=language_dropdown, outputs=translate_status) # Update inputs
|
189 |
|
190 |
# Download as Word
|
191 |
with gr.Row():
|
192 |
+
download_word_button = gr.Button("Download as Word") # Renamed the button to avoid conflict
|
193 |
+
download_word_status = gr.File(label="Download Translated Word File") # File output for Word download
|
194 |
|
195 |
+
download_word_button.click(download_word, inputs=None, outputs=download_word_status)
|
196 |
|
197 |
# Download Subtitled Video
|
198 |
with gr.Row():
|
199 |
+
download_video_button2 = gr.Button("Download Subtitled Video") # Renamed the button to avoid conflict
|
200 |
download_video_status = gr.Textbox(label="Download Video Status")
|
201 |
|
202 |
+
download_video_button2.click(download_video, inputs=None, outputs=download_video_status)
|
203 |
|
204 |
# Launch the Gradio app
|
205 |
demo.launch()
|