malleswar commited on
Commit
88b1fb2
·
verified ·
1 Parent(s): 400a693

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -251
app.py CHANGED
@@ -60,7 +60,8 @@ def process_video(video_file, language="hindi", progress=gr.Progress()):
60
  print(f"Extracting audio from: {video_file}")
61
  video = VideoFileClip(video_file)
62
  if not video.audio:
63
- shutil.rmtree(output_dir)
 
64
  return None, None, "Video has no audio track"
65
 
66
  video.audio.write_audiofile(
@@ -78,7 +79,7 @@ def process_video(video_file, language="hindi", progress=gr.Progress()):
78
  progress(0.4, desc="Transcribing with Whisper Turbo...")
79
  print(f"Starting transcription (language: {language})...")
80
 
81
- result = pipe(
82
  audio_path,
83
  return_timestamps=True,
84
  generate_kwargs={
@@ -87,67 +88,48 @@ def process_video(video_file, language="hindi", progress=gr.Progress()):
87
  }
88
  )
89
 
90
- print(f"Transcription result keys: {result.keys()}")
91
 
92
  # Verify we have chunks
93
- if not result.get('chunks') or len(result['chunks']) == 0:
94
- error_msg = f"Transcription returned no segments. Full result: {result}"
95
  print(error_msg)
96
- shutil.rmtree(output_dir)
 
97
  return None, None, error_msg
98
 
99
- print(f"Transcription complete: {len(result['chunks'])} segments")
100
 
101
  # Create SRT in output directory (persistent)
102
  progress(0.6, desc="Creating SRT...")
103
  srt_path = os.path.join(output_dir, "subtitles.srt")
104
 
105
  print(f"Creating SRT at: {srt_path}")
106
- print(f"Output directory exists: {os.path.exists(output_dir)}")
107
- print(f"Output directory contents before SRT: {os.listdir(output_dir)}")
108
-
109
- try:
110
- with open(srt_path, 'w', encoding='utf-8-sig') as f:
111
- for i, chunk in enumerate(result['chunks'], 1):
112
- start, end = chunk['timestamp']
113
- text = chunk['text'].strip()
114
-
115
- if text:
116
- f.write(f"{i}\n")
117
- f.write(f"{format_srt_time(start)} --> {format_srt_time(end)}\n")
118
- f.write(f"{text}\n\n")
119
-
120
- print(f"SRT file write completed")
121
- except Exception as e:
122
- print(f"Error writing SRT file: {e}")
123
- import traceback
124
- print(traceback.format_exc())
125
- shutil.rmtree(output_dir)
126
- raise
127
 
128
- # Verify SRT was created
129
- print(f"Checking if SRT exists: {os.path.exists(srt_path)}")
130
- print(f"Output directory contents after SRT: {os.listdir(output_dir)}")
 
 
 
 
 
 
131
 
 
132
  if not os.path.exists(srt_path):
133
- shutil.rmtree(output_dir)
134
- return None, None, f"SRT file was not created at: {srt_path}\nDirectory contents: {os.listdir(output_dir)}"
 
135
 
136
  srt_size = os.path.getsize(srt_path)
137
  if srt_size == 0:
138
- shutil.rmtree(output_dir)
 
139
  return None, None, f"SRT file is empty at: {srt_path}"
140
 
141
  print(f"SRT created successfully: {srt_path} ({srt_size} bytes)")
142
 
143
- # Read SRT content for debugging
144
- try:
145
- with open(srt_path, 'r', encoding='utf-8-sig') as f:
146
- srt_preview = f.read()[:500]
147
- print(f"SRT preview:\n{srt_preview}")
148
- except Exception as e:
149
- print(f"Error reading SRT file: {e}")
150
-
151
  # Burn subtitles
152
  progress(0.85, desc="Burning subtitles...")
153
  output_path = os.path.join(output_dir, "final.mp4")
@@ -158,193 +140,20 @@ def process_video(video_file, language="hindi", progress=gr.Progress()):
158
  ass_path = os.path.join(output_dir, "subtitles.ass")
159
 
160
  print(f"Converting SRT to ASS for better compatibility...")
161
- try:
162
- subprocess.run([
163
- 'ffmpeg', '-y',
164
- '-i', srt_path,
165
- ass_path
166
- ], check=True, capture_output=True, text=True)
167
-
168
- if not os.path.exists(ass_path):
169
- raise Exception(f"Failed to create ASS file at {ass_path}")
170
-
171
- print(f"ASS file created: {ass_path} ({os.path.getsize(ass_path)} bytes)")
172
- except subprocess.CalledProcessError as e:
173
- print(f"SRT to ASS conversion failed: {e.stderr}")
174
- shutil.rmtree(output_dir)
175
- raise
176
-
177
- # Use ASS filter which is more reliable than subtitles filter
178
- # For ass filter, we need to escape special characters differently
179
- ass_path_escaped = ass_path.replace('\\', '\\\\').replace(':', '\\:')
180
-
181
- ffmpeg_cmd = [
182
  'ffmpeg', '-y',
183
- '-i', video_file,
184
- '-vf', f"ass={ass_path_escaped}",
185
- '-c:a', 'copy',
186
- '-c:v', 'libx264',
187
- '-preset', 'medium',
188
- '-crf', '23',
189
- output_path
190
- ]
191
 
192
- print(f"FFmpeg command: {' '.join(ffmpeg_cmd)}")
193
-
194
- try:
195
- ffmpeg_result = subprocess.run(
196
- ffmpeg_cmd,
197
- check=True,
198
- capture_output=True,
199
- text=True,
200
- timeout=600
201
- )
202
- print(f"FFmpeg stdout: {ffmpeg_result.stdout}")
203
- print(f"FFmpeg stderr: {ffmpeg_result.stderr}")
204
- except subprocess.CalledProcessError as e:
205
- print(f"FFmpeg failed!")
206
- print(f"Return code: {e.returncode}")
207
- print(f"Stdout: {e.stdout}")
208
- print(f"Stderr: {e.stderr}")
209
- shutil.rmtree(output_dir)
210
- raise
211
-
212
- if not os.path.exists(output_path):
213
- shutil.rmtree(output_dir)
214
- return None, None, f"Output video was not created at: {output_path}"
215
-
216
- print(f"Video created: {output_path} ({os.path.getsize(output_path)} bytes)")
217
-
218
- progress(1.0, desc="Complete!")
219
-
220
- # Create status with preview
221
- preview_lines = []
222
- for i, chunk in enumerate(result['chunks'][:10], 1):
223
- text = chunk['text'].strip()
224
- start_time = chunk['timestamp'][0]
225
- preview_lines.append(f"{i}. [{start_time:.1f}s] {text}")
226
-
227
- preview_text = "\n".join(preview_lines)
228
- full_text = " ".join([c['text'].strip() for c in result['chunks']])
229
-
230
- status = f"""Processing Complete!
231
- Statistics:
232
- - Model: Whisper Large V3 Turbo
233
- - Device: {device}
234
- - Segments: {len(result['chunks'])}
235
- - Duration: {result['chunks'][-1]['timestamp'][1]:.1f}s
236
- - Language: {language}
237
-
238
- Preview (first 10 segments):
239
- {preview_text}
240
-
241
- Full Transcription:
242
- {full_text[:500]}{"..." if len(full_text) > 500 else ""}
243
-
244
- Files created successfully!
245
- """
246
-
247
- # Don't cleanup output_dir - Gradio needs these files
248
- return srt_path, output_path, status
249
-
250
- except subprocess.TimeoutExpired:
251
- try:
252
  shutil.rmtree(temp_dir, ignore_errors=True)
253
  shutil.rmtree(output_dir, ignore_errors=True)
254
- except:
255
- pass
256
- return None, None, "Processing timeout. Try a shorter video."
257
- except subprocess.CalledProcessError as e:
258
- try:
259
- shutil.rmtree(temp_dir, ignore_errors=True)
260
- shutil.rmtree(output_dir, ignore_errors=True)
261
- except:
262
- pass
263
- error_detail = e.stderr.decode() if hasattr(e.stderr, 'decode') else str(e.stderr) if e.stderr else str(e)
264
- return None, None, f"FFmpeg error: {error_detail}"
265
- except Exception as e:
266
- try:
267
- shutil.rmtree(temp_dir, ignore_errors=True)
268
- shutil.rmtree(output_dir, ignore_errors=True)
269
- except:
270
- pass
271
- import traceback
272
- error_trace = traceback.format_exc()
273
- print(f"Error: {error_trace}")
274
- return None, None, f"Error: {str(e)}\n\nDetails:\n{error_trace}"
275
- finally:
276
- # Only cleanup temp_dir (audio processing), keep output_dir for Gradio
277
- try:
278
- shutil.rmtree(temp_dir)
279
- print(f"Cleaned up temp directory: {temp_dir}")
280
- except Exception as e:
281
- print(f"Cleanup warning: {e}")
282
- # Note: output_dir is NOT cleaned up here - Gradio needs access to the files
283
- # The files will be cleaned up by the OS eventually from /tmp/, 'w', encoding='utf-8-sig') as f:
284
- for i, chunk in enumerate(result['chunks'], 1):
285
- start, end = chunk['timestamp']
286
- text = chunk['text'].strip()
287
-
288
- if text:
289
- f.write(f"{i}\n")
290
- f.write(f"{format_srt_time(start)} --> {format_srt_time(end)}\n")
291
- f.write(f"{text}\n\n")
292
-
293
- print(f"SRT file write completed")
294
- except Exception as e:
295
- print(f"Error writing SRT file: {e}")
296
- import traceback
297
- print(traceback.format_exc())
298
- raise
299
-
300
- # Verify SRT was created
301
- print(f"Checking if SRT exists: {os.path.exists(srt_path)}")
302
- print(f"Temp directory contents after SRT: {os.listdir(temp_dir)}")
303
 
304
- if not os.path.exists(srt_path):
305
- return None, None, f"SRT file was not created at: {srt_path}\nDirectory contents: {os.listdir(temp_dir)}"
306
 
307
- srt_size = os.path.getsize(srt_path)
308
- if srt_size == 0:
309
- return None, None, f"SRT file is empty at: {srt_path}"
310
-
311
- print(f"SRT created successfully: {srt_path} ({srt_size} bytes)")
312
-
313
- # Read SRT content for debugging
314
- try:
315
- with open(srt_path, 'r', encoding='utf-8-sig') as f:
316
- srt_preview = f.read()[:500]
317
- print(f"SRT preview:\n{srt_preview}")
318
- except Exception as e:
319
- print(f"Error reading SRT file: {e}")
320
-
321
- # Burn subtitles
322
- progress(0.85, desc="Burning subtitles...")
323
- output_path = os.path.join(temp_dir, "final.mp4")
324
-
325
- print("Burning subtitles with FFmpeg...")
326
-
327
- # Convert SRT to ASS first (more reliable with FFmpeg)
328
- ass_path = os.path.join(temp_dir, "subtitles.ass")
329
-
330
- print(f"Converting SRT to ASS for better compatibility...")
331
- try:
332
- subprocess.run([
333
- 'ffmpeg', '-y',
334
- '-i', srt_path,
335
- ass_path
336
- ], check=True, capture_output=True, text=True)
337
-
338
- if not os.path.exists(ass_path):
339
- raise Exception(f"Failed to create ASS file at {ass_path}")
340
-
341
- print(f"ASS file created: {ass_path} ({os.path.getsize(ass_path)} bytes)")
342
- except subprocess.CalledProcessError as e:
343
- print(f"SRT to ASS conversion failed: {e.stderr}")
344
- raise
345
-
346
- # Use ASS filter which is more reliable than subtitles filter
347
- # For ass filter, we need to escape special characters differently
348
  ass_path_escaped = ass_path.replace('\\', '\\\\').replace(':', '\\:')
349
 
350
  ffmpeg_cmd = [
@@ -360,24 +169,17 @@ Files created successfully!
360
 
361
  print(f"FFmpeg command: {' '.join(ffmpeg_cmd)}")
362
 
363
- try:
364
- ffmpeg_result = subprocess.run(
365
- ffmpeg_cmd,
366
- check=True,
367
- capture_output=True,
368
- text=True,
369
- timeout=600
370
- )
371
- print(f"FFmpeg stdout: {ffmpeg_result.stdout}")
372
- print(f"FFmpeg stderr: {ffmpeg_result.stderr}")
373
- except subprocess.CalledProcessError as e:
374
- print(f"FFmpeg failed!")
375
- print(f"Return code: {e.returncode}")
376
- print(f"Stdout: {e.stdout}")
377
- print(f"Stderr: {e.stderr}")
378
- raise
379
 
380
  if not os.path.exists(output_path):
 
 
381
  return None, None, f"Output video was not created at: {output_path}"
382
 
383
  print(f"Video created: {output_path} ({os.path.getsize(output_path)} bytes)")
@@ -386,20 +188,20 @@ Files created successfully!
386
 
387
  # Create status with preview
388
  preview_lines = []
389
- for i, chunk in enumerate(result['chunks'][:10], 1):
390
  text = chunk['text'].strip()
391
  start_time = chunk['timestamp'][0]
392
  preview_lines.append(f"{i}. [{start_time:.1f}s] {text}")
393
 
394
  preview_text = "\n".join(preview_lines)
395
- full_text = " ".join([c['text'].strip() for c in result['chunks']])
396
 
397
  status = f"""Processing Complete!
398
  Statistics:
399
  - Model: Whisper Large V3 Turbo
400
  - Device: {device}
401
- - Segments: {len(result['chunks'])}
402
- - Duration: {result['chunks'][-1]['timestamp'][1]:.1f}s
403
  - Language: {language}
404
 
405
  Preview (first 10 segments):
@@ -411,25 +213,29 @@ Full Transcription:
411
  Files created successfully!
412
  """
413
 
 
 
 
 
 
414
  return srt_path, output_path, status
415
 
416
  except subprocess.TimeoutExpired:
 
 
417
  return None, None, "Processing timeout. Try a shorter video."
418
  except subprocess.CalledProcessError as e:
419
- error_detail = e.stderr.decode() if hasattr(e.stderr, 'decode') else str(e.stderr) if e.stderr else str(e)
 
 
420
  return None, None, f"FFmpeg error: {error_detail}"
421
  except Exception as e:
 
 
422
  import traceback
423
  error_trace = traceback.format_exc()
424
  print(f"Error: {error_trace}")
425
  return None, None, f"Error: {str(e)}\n\nDetails:\n{error_trace}"
426
- finally:
427
- # Cleanup
428
- try:
429
- shutil.rmtree(temp_dir)
430
- print(f"Cleaned up temp directory: {temp_dir}")
431
- except Exception as e:
432
- print(f"Cleanup warning: {e}")
433
 
434
  # Gradio UI
435
  with gr.Blocks(theme=gr.themes.Soft(), title="Hindi Subtitle Generator") as demo:
 
60
  print(f"Extracting audio from: {video_file}")
61
  video = VideoFileClip(video_file)
62
  if not video.audio:
63
+ shutil.rmtree(temp_dir, ignore_errors=True)
64
+ shutil.rmtree(output_dir, ignore_errors=True)
65
  return None, None, "Video has no audio track"
66
 
67
  video.audio.write_audiofile(
 
79
  progress(0.4, desc="Transcribing with Whisper Turbo...")
80
  print(f"Starting transcription (language: {language})...")
81
 
82
+ transcription_result = pipe(
83
  audio_path,
84
  return_timestamps=True,
85
  generate_kwargs={
 
88
  }
89
  )
90
 
91
+ print(f"Transcription result keys: {transcription_result.keys()}")
92
 
93
  # Verify we have chunks
94
+ if not transcription_result.get('chunks') or len(transcription_result['chunks']) == 0:
95
+ error_msg = f"Transcription returned no segments. Full result: {transcription_result}"
96
  print(error_msg)
97
+ shutil.rmtree(temp_dir, ignore_errors=True)
98
+ shutil.rmtree(output_dir, ignore_errors=True)
99
  return None, None, error_msg
100
 
101
+ print(f"Transcription complete: {len(transcription_result['chunks'])} segments")
102
 
103
  # Create SRT in output directory (persistent)
104
  progress(0.6, desc="Creating SRT...")
105
  srt_path = os.path.join(output_dir, "subtitles.srt")
106
 
107
  print(f"Creating SRT at: {srt_path}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ with open(srt_path, 'w', encoding='utf-8-sig') as f:
110
+ for i, chunk in enumerate(transcription_result['chunks'], 1):
111
+ start, end = chunk['timestamp']
112
+ text = chunk['text'].strip()
113
+
114
+ if text:
115
+ f.write(f"{i}\n")
116
+ f.write(f"{format_srt_time(start)} --> {format_srt_time(end)}\n")
117
+ f.write(f"{text}\n\n")
118
 
119
+ # Verify SRT was created
120
  if not os.path.exists(srt_path):
121
+ shutil.rmtree(temp_dir, ignore_errors=True)
122
+ shutil.rmtree(output_dir, ignore_errors=True)
123
+ return None, None, f"SRT file was not created at: {srt_path}"
124
 
125
  srt_size = os.path.getsize(srt_path)
126
  if srt_size == 0:
127
+ shutil.rmtree(temp_dir, ignore_errors=True)
128
+ shutil.rmtree(output_dir, ignore_errors=True)
129
  return None, None, f"SRT file is empty at: {srt_path}"
130
 
131
  print(f"SRT created successfully: {srt_path} ({srt_size} bytes)")
132
 
 
 
 
 
 
 
 
 
133
  # Burn subtitles
134
  progress(0.85, desc="Burning subtitles...")
135
  output_path = os.path.join(output_dir, "final.mp4")
 
140
  ass_path = os.path.join(output_dir, "subtitles.ass")
141
 
142
  print(f"Converting SRT to ASS for better compatibility...")
143
+ subprocess.run([
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  'ffmpeg', '-y',
145
+ '-i', srt_path,
146
+ ass_path
147
+ ], check=True, capture_output=True, text=True)
 
 
 
 
 
148
 
149
+ if not os.path.exists(ass_path):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  shutil.rmtree(temp_dir, ignore_errors=True)
151
  shutil.rmtree(output_dir, ignore_errors=True)
152
+ raise Exception(f"Failed to create ASS file at {ass_path}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
+ print(f"ASS file created: {ass_path} ({os.path.getsize(ass_path)} bytes)")
 
155
 
156
+ # Use ASS filter - escape path for FFmpeg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  ass_path_escaped = ass_path.replace('\\', '\\\\').replace(':', '\\:')
158
 
159
  ffmpeg_cmd = [
 
169
 
170
  print(f"FFmpeg command: {' '.join(ffmpeg_cmd)}")
171
 
172
+ subprocess.run(
173
+ ffmpeg_cmd,
174
+ check=True,
175
+ capture_output=True,
176
+ text=True,
177
+ timeout=600
178
+ )
 
 
 
 
 
 
 
 
 
179
 
180
  if not os.path.exists(output_path):
181
+ shutil.rmtree(temp_dir, ignore_errors=True)
182
+ shutil.rmtree(output_dir, ignore_errors=True)
183
  return None, None, f"Output video was not created at: {output_path}"
184
 
185
  print(f"Video created: {output_path} ({os.path.getsize(output_path)} bytes)")
 
188
 
189
  # Create status with preview
190
  preview_lines = []
191
+ for i, chunk in enumerate(transcription_result['chunks'][:10], 1):
192
  text = chunk['text'].strip()
193
  start_time = chunk['timestamp'][0]
194
  preview_lines.append(f"{i}. [{start_time:.1f}s] {text}")
195
 
196
  preview_text = "\n".join(preview_lines)
197
+ full_text = " ".join([c['text'].strip() for c in transcription_result['chunks']])
198
 
199
  status = f"""Processing Complete!
200
  Statistics:
201
  - Model: Whisper Large V3 Turbo
202
  - Device: {device}
203
+ - Segments: {len(transcription_result['chunks'])}
204
+ - Duration: {transcription_result['chunks'][-1]['timestamp'][1]:.1f}s
205
  - Language: {language}
206
 
207
  Preview (first 10 segments):
 
213
  Files created successfully!
214
  """
215
 
216
+ # Cleanup only temp_dir, keep output_dir for Gradio
217
+ shutil.rmtree(temp_dir, ignore_errors=True)
218
+ print(f"Cleaned up temp directory: {temp_dir}")
219
+
220
+ # Return paths - Gradio needs these files to exist
221
  return srt_path, output_path, status
222
 
223
  except subprocess.TimeoutExpired:
224
+ shutil.rmtree(temp_dir, ignore_errors=True)
225
+ shutil.rmtree(output_dir, ignore_errors=True)
226
  return None, None, "Processing timeout. Try a shorter video."
227
  except subprocess.CalledProcessError as e:
228
+ shutil.rmtree(temp_dir, ignore_errors=True)
229
+ shutil.rmtree(output_dir, ignore_errors=True)
230
+ error_detail = e.stderr if hasattr(e, 'stderr') else str(e)
231
  return None, None, f"FFmpeg error: {error_detail}"
232
  except Exception as e:
233
+ shutil.rmtree(temp_dir, ignore_errors=True)
234
+ shutil.rmtree(output_dir, ignore_errors=True)
235
  import traceback
236
  error_trace = traceback.format_exc()
237
  print(f"Error: {error_trace}")
238
  return None, None, f"Error: {str(e)}\n\nDetails:\n{error_trace}"
 
 
 
 
 
 
 
239
 
240
  # Gradio UI
241
  with gr.Blocks(theme=gr.themes.Soft(), title="Hindi Subtitle Generator") as demo: