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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -49
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
- txt_clip = create_subtitle_clip_pil(entry["translated"], entry["start"], entry["end"], video_width, video_height, font_path)
 
 
 
 
 
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
- audio_segment = audio_clip.set_start(entry["start"]).set_duration(desired_duration)
 
385
  except Exception as e:
386
- logger.error(f"\u274c Failed to generate audio segment for entry {i}: {e}")
 
 
387
  audio_segment = None
388
 
389
- return i, txt_clip, audio_segment
390
 
391
- def add_transcript_voiceover(video_path, translated_json, output_path, add_voiceover=False, target_language="en", speaker_sample_paths=None):
392
- """
393
- Add transcript and voiceover to a video, segment by segment.
394
- """
395
- video = VideoFileClip(video_path)
396
- font_path = "./NotoSansSC-Regular.ttf"
397
 
398
- text_clips = []
399
- audio_segments = []
 
 
 
 
400
 
401
- with concurrent.futures.ThreadPoolExecutor() as executor:
402
- futures = [executor.submit(process_entry, entry, i, video.w, video.h, add_voiceover, target_language, font_path, speaker_sample_paths)
403
- for i, entry in enumerate(translated_json)]
404
-
405
- # Collect results with original index i
406
- results = []
407
- for future in concurrent.futures.as_completed(futures):
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
- final_video = CompositeVideoClip([video] + text_clips)
421
 
422
- logger.info("Methods in CompositeVideoClip:")
423
- for method in dir(final_video):
424
- logger.info(method)
425
-
426
- if add_voiceover:
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
- final_video = final_video.set_audio(final_audio)
 
 
 
 
 
432
 
433
- logger.info(f"Saving the final video to: {output_path}")
434
- final_video.write_videofile(output_path, codec="libx264", audio_codec="aac")
 
 
 
435
 
436
- logger.info("Video processing completed successfully.")
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