Update app.py
Browse files
app.py
CHANGED
@@ -353,8 +353,14 @@ def create_subtitle_clip_pil(text, start_time, end_time, video_width, video_heig
|
|
353 |
|
354 |
def process_entry(entry, i, video_width, video_height, add_voiceover, target_language, font_path, speaker_sample_paths=None):
|
355 |
logger.debug(f"Processing entry {i}: {entry}")
|
|
|
356 |
|
357 |
-
|
|
|
|
|
|
|
|
|
|
|
358 |
|
359 |
audio_segment = None
|
360 |
if add_voiceover:
|
@@ -362,8 +368,7 @@ def process_entry(entry, i, video_width, video_height, add_voiceover, target_lan
|
|
362 |
segment_audio_path = f"segment_{i}_voiceover.wav"
|
363 |
desired_duration = entry["end"] - entry["start"]
|
364 |
speaker = entry.get("speaker", "default")
|
365 |
-
speaker_wav_path = f"speaker_{speaker}_sample.wav"
|
366 |
-
#speaker_sample_paths.get(speaker_id, "speaker_default.wav") if speaker_sample_paths else "speaker_default.wav"
|
367 |
|
368 |
generate_voiceover_clone([entry], desired_duration, target_language, speaker_wav_path, segment_audio_path)
|
369 |
|
@@ -374,66 +379,61 @@ def process_entry(entry, i, video_width, video_height, add_voiceover, target_lan
|
|
374 |
logger.debug(f"Audio clip duration: {audio_clip.duration}, Desired duration: {desired_duration}")
|
375 |
|
376 |
if audio_clip.duration < desired_duration:
|
377 |
-
# Pad with silence if audio is too short
|
378 |
silence_duration = desired_duration - audio_clip.duration
|
379 |
-
|
380 |
-
# Concatenate the original audio and silence
|
381 |
audio_clip = concatenate_audioclips([audio_clip, silence(duration=silence_duration)])
|
382 |
logger.info(f"Padded audio with {silence_duration} seconds of silence.")
|
383 |
-
|
384 |
-
|
|
|
385 |
except Exception as e:
|
386 |
-
|
|
|
|
|
387 |
audio_segment = None
|
388 |
|
389 |
-
return i, txt_clip, audio_segment
|
390 |
|
391 |
-
def
|
392 |
-
""
|
393 |
-
|
394 |
-
"""
|
395 |
-
video = VideoFileClip(video_path)
|
396 |
-
font_path = "./NotoSansSC-Regular.ttf"
|
397 |
|
398 |
-
|
399 |
-
|
|
|
|
|
|
|
|
|
400 |
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
try:
|
409 |
-
i, txt_clip, audio_segment = future.result()
|
410 |
-
results.append((i, txt_clip, audio_segment))
|
411 |
-
except Exception as e:
|
412 |
-
logger.error(f"Error processing entry: {e}")
|
413 |
-
|
414 |
-
# Sort by original index i
|
415 |
-
results.sort(key=lambda x: x[0])
|
416 |
-
|
417 |
-
# Extract sorted clips
|
418 |
-
text_clips = [clip for i, clip, segment in results]
|
419 |
|
420 |
-
|
421 |
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
audio_segments = [segment for i, clip, segment in results if segment is not None]
|
428 |
-
final_audio = CompositeAudioClip(audio_segments) # Critical fix
|
429 |
-
final_audio = final_audio.set_duration(video.duration)
|
430 |
|
431 |
-
|
|
|
|
|
|
|
|
|
|
|
432 |
|
433 |
-
|
434 |
-
|
|
|
|
|
|
|
435 |
|
436 |
-
|
437 |
|
438 |
import os
|
439 |
import traceback
|
|
|
353 |
|
354 |
def process_entry(entry, i, video_width, video_height, add_voiceover, target_language, font_path, speaker_sample_paths=None):
|
355 |
logger.debug(f"Processing entry {i}: {entry}")
|
356 |
+
error_message = None
|
357 |
|
358 |
+
try:
|
359 |
+
txt_clip = create_subtitle_clip_pil(entry["translated"], entry["start"], entry["end"], video_width, video_height, font_path)
|
360 |
+
except Exception as e:
|
361 |
+
error_message = f"❌ Failed to create subtitle clip for entry {i}: {e}"
|
362 |
+
logger.error(error_message)
|
363 |
+
txt_clip = None
|
364 |
|
365 |
audio_segment = None
|
366 |
if add_voiceover:
|
|
|
368 |
segment_audio_path = f"segment_{i}_voiceover.wav"
|
369 |
desired_duration = entry["end"] - entry["start"]
|
370 |
speaker = entry.get("speaker", "default")
|
371 |
+
speaker_wav_path = f"speaker_{speaker}_sample.wav"
|
|
|
372 |
|
373 |
generate_voiceover_clone([entry], desired_duration, target_language, speaker_wav_path, segment_audio_path)
|
374 |
|
|
|
379 |
logger.debug(f"Audio clip duration: {audio_clip.duration}, Desired duration: {desired_duration}")
|
380 |
|
381 |
if audio_clip.duration < desired_duration:
|
|
|
382 |
silence_duration = desired_duration - audio_clip.duration
|
|
|
|
|
383 |
audio_clip = concatenate_audioclips([audio_clip, silence(duration=silence_duration)])
|
384 |
logger.info(f"Padded audio with {silence_duration} seconds of silence.")
|
385 |
+
|
386 |
+
audio_segment = audio_clip.set_start(entry["start"]).set_duration(desired_duration)
|
387 |
+
|
388 |
except Exception as e:
|
389 |
+
err = f"❌ Failed to generate audio segment for entry {i}: {e}"
|
390 |
+
logger.error(err)
|
391 |
+
error_message = error_message + " | " + err if error_message else err
|
392 |
audio_segment = None
|
393 |
|
394 |
+
return i, txt_clip, audio_segment, error_message
|
395 |
|
396 |
+
def process_entry(entry, i, video_width, video_height, add_voiceover, target_language, font_path, speaker_sample_paths=None):
|
397 |
+
logger.debug(f"Processing entry {i}: {entry}")
|
398 |
+
error_message = None
|
|
|
|
|
|
|
399 |
|
400 |
+
try:
|
401 |
+
txt_clip = create_subtitle_clip_pil(entry["translated"], entry["start"], entry["end"], video_width, video_height, font_path)
|
402 |
+
except Exception as e:
|
403 |
+
error_message = f"❌ Failed to create subtitle clip for entry {i}: {e}"
|
404 |
+
logger.error(error_message)
|
405 |
+
txt_clip = None
|
406 |
|
407 |
+
audio_segment = None
|
408 |
+
if add_voiceover:
|
409 |
+
try:
|
410 |
+
segment_audio_path = f"segment_{i}_voiceover.wav"
|
411 |
+
desired_duration = entry["end"] - entry["start"]
|
412 |
+
speaker = entry.get("speaker", "default")
|
413 |
+
speaker_wav_path = f"speaker_{speaker}_sample.wav"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
414 |
|
415 |
+
generate_voiceover_clone([entry], desired_duration, target_language, speaker_wav_path, segment_audio_path)
|
416 |
|
417 |
+
if not os.path.exists(segment_audio_path):
|
418 |
+
raise FileNotFoundError(f"Voiceover file not generated at: {segment_audio_path}")
|
419 |
+
|
420 |
+
audio_clip = AudioFileClip(segment_audio_path)
|
421 |
+
logger.debug(f"Audio clip duration: {audio_clip.duration}, Desired duration: {desired_duration}")
|
|
|
|
|
|
|
422 |
|
423 |
+
if audio_clip.duration < desired_duration:
|
424 |
+
silence_duration = desired_duration - audio_clip.duration
|
425 |
+
audio_clip = concatenate_audioclips([audio_clip, silence(duration=silence_duration)])
|
426 |
+
logger.info(f"Padded audio with {silence_duration} seconds of silence.")
|
427 |
+
|
428 |
+
audio_segment = audio_clip.set_start(entry["start"]).set_duration(desired_duration)
|
429 |
|
430 |
+
except Exception as e:
|
431 |
+
err = f"❌ Failed to generate audio segment for entry {i}: {e}"
|
432 |
+
logger.error(err)
|
433 |
+
error_message = error_message + " | " + err if error_message else err
|
434 |
+
audio_segment = None
|
435 |
|
436 |
+
return i, txt_clip, audio_segment, error_message
|
437 |
|
438 |
import os
|
439 |
import traceback
|