qqwjq1981 commited on
Commit
d6f8089
·
verified ·
1 Parent(s): 0a03934

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -37
app.py CHANGED
@@ -392,48 +392,59 @@ def process_entry(entry, i, video_width, video_height, add_voiceover, target_lan
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
 
392
  audio_segment = None
393
 
394
  return i, txt_clip, audio_segment, error_message
395
+ def add_transcript_voiceover(video_path, translated_json, output_path, add_voiceover=False, target_language="en", speaker_sample_paths=None):
396
+ video = VideoFileClip(video_path)
397
+ font_path = "./NotoSansSC-Regular.ttf"
398
 
399
+ text_clips = []
400
+ audio_segments = []
401
+ error_messages = []
 
 
 
 
 
 
 
402
 
403
+ with concurrent.futures.ThreadPoolExecutor() as executor:
404
+ futures = [executor.submit(process_entry, entry, i, video.w, video.h, add_voiceover, target_language, font_path, speaker_sample_paths)
405
+ for i, entry in enumerate(translated_json)]
406
+
407
+ results = []
408
+ for future in concurrent.futures.as_completed(futures):
409
+ try:
410
+ i, txt_clip, audio_segment, error = future.result()
411
+ results.append((i, txt_clip, audio_segment))
412
+ if error:
413
+ error_messages.append(f"[Entry {i}] {error}")
414
+ except Exception as e:
415
+ err = f"❌ Unexpected error in future result: {e}"
416
+ logger.error(err)
417
+ error_messages.append(err)
418
+
419
+ # Sort by entry index to ensure order
420
+ results.sort(key=lambda x: x[0])
421
+ text_clips = [clip for _, clip, _ in results if clip]
422
  if add_voiceover:
423
+ audio_segments = [segment for _, _, segment in results if segment]
 
 
 
 
 
 
424
 
425
+ final_video = CompositeVideoClip([video] + text_clips)
 
 
 
 
 
 
 
 
 
426
 
427
+ if add_voiceover:
428
+ if audio_segments:
429
+ final_audio = CompositeAudioClip(audio_segments).set_duration(video.duration)
430
+ final_video = final_video.set_audio(final_audio)
431
+ else:
432
+ logger.warning("⚠️ No audio segments available. Adding silent fallback.")
433
+ silent_audio = AudioClip(lambda t: 0, duration=video.duration)
434
+ final_video = final_video.set_audio(silent_audio)
435
+
436
+ logger.info(f"Saving the final video to: {output_path}")
437
+ final_video.write_videofile(output_path, codec="libx264", audio_codec="aac")
438
+
439
+ logger.info("Video processing completed successfully.")
440
+
441
+ # Optional: return errors
442
+ if error_messages:
443
+ logger.warning("⚠️ Errors encountered during processing:")
444
+ for msg in error_messages:
445
+ logger.warning(msg)
446
+
447
+ return error_messages
448
 
449
  import os
450
  import traceback