ismdrobiul489 commited on
Commit
c060ff8
·
1 Parent(s): c8b5875

Add TheBoldFont to static/fonts and use for all captions + add captions to story_reels

Browse files
modules/story_reels/services/story_creator.py CHANGED
@@ -428,7 +428,8 @@ class StoryCreator:
428
  await self._compose_video(
429
  scenes=generated_scenes,
430
  audio_path=mp3_path,
431
- output_path=output_path
 
432
  )
433
 
434
  job["video_url"] = f"/videos/{job_id}.mp4"
@@ -457,7 +458,8 @@ class StoryCreator:
457
  self,
458
  scenes: List[Dict],
459
  audio_path: Path,
460
- output_path: Path
 
461
  ):
462
  """
463
  Compose video from images and audio using MoviePy.
@@ -466,12 +468,14 @@ class StoryCreator:
466
  - Crossfade transitions (0.3s) between scenes
467
  - Subtle Ken Burns zoom (1.05x) for dynamic feel
468
  - Fade in at start, fade out at end
 
469
  """
470
  from moviepy.editor import (
471
  ImageClip,
472
  AudioFileClip,
473
  concatenate_videoclips,
474
  CompositeVideoClip,
 
475
  vfx
476
  )
477
 
@@ -557,6 +561,62 @@ class StoryCreator:
557
 
558
  video = video.set_audio(audio)
559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  # Write final video
561
  logger.info(f"Writing video with effects: crossfade={CROSSFADE_DURATION}s, zoom={ZOOM_FACTOR}x")
562
  video.write_videofile(
 
428
  await self._compose_video(
429
  scenes=generated_scenes,
430
  audio_path=mp3_path,
431
+ output_path=output_path,
432
+ captions=captions_dict
433
  )
434
 
435
  job["video_url"] = f"/videos/{job_id}.mp4"
 
458
  self,
459
  scenes: List[Dict],
460
  audio_path: Path,
461
+ output_path: Path,
462
+ captions: List[Dict] = None
463
  ):
464
  """
465
  Compose video from images and audio using MoviePy.
 
468
  - Crossfade transitions (0.3s) between scenes
469
  - Subtle Ken Burns zoom (1.05x) for dynamic feel
470
  - Fade in at start, fade out at end
471
+ - Word-by-word captions
472
  """
473
  from moviepy.editor import (
474
  ImageClip,
475
  AudioFileClip,
476
  concatenate_videoclips,
477
  CompositeVideoClip,
478
+ TextClip,
479
  vfx
480
  )
481
 
 
561
 
562
  video = video.set_audio(audio)
563
 
564
+ # ====================
565
+ # Add Captions Overlay
566
+ # ====================
567
+ if captions:
568
+ logger.info(f"Adding {len(captions)} captions to video...")
569
+
570
+ # Find font - Priority: TheBoldFont (static/fonts) > DejaVu > Liberation
571
+ thebold_path = Path(__file__).parent.parent.parent.parent / "static" / "fonts" / "THEBOLDFONT-FREEVERSION.ttf"
572
+ dejavu_path = Path("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf")
573
+ liberation_path = Path("/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf")
574
+
575
+ if thebold_path.exists():
576
+ font_name = str(thebold_path)
577
+ elif dejavu_path.exists():
578
+ font_name = str(dejavu_path)
579
+ elif liberation_path.exists():
580
+ font_name = str(liberation_path)
581
+ else:
582
+ font_name = "DejaVu-Sans-Bold"
583
+
584
+ caption_clips = []
585
+ y_pos = TARGET_HEIGHT * 0.75 # 75% down (bottom area)
586
+
587
+ for cap in captions:
588
+ start_time = cap.get("startMs", 0) / 1000
589
+ end_time = cap.get("endMs", 0) / 1000
590
+ duration = end_time - start_time
591
+ text = cap.get("text", "")
592
+
593
+ if duration <= 0 or not text:
594
+ continue
595
+
596
+ try:
597
+ txt_clip = TextClip(
598
+ text,
599
+ fontsize=60,
600
+ color="white",
601
+ font=font_name,
602
+ stroke_color="black",
603
+ stroke_width=2,
604
+ method="caption",
605
+ size=(int(TARGET_WIDTH * 0.9), None),
606
+ align="center"
607
+ )
608
+ txt_clip = txt_clip.set_duration(duration)
609
+ txt_clip = txt_clip.set_start(start_time)
610
+ txt_clip = txt_clip.set_position(("center", y_pos))
611
+ caption_clips.append(txt_clip)
612
+ except Exception as e:
613
+ logger.warning(f"Caption failed: {e}")
614
+ continue
615
+
616
+ if caption_clips:
617
+ video = CompositeVideoClip([video] + caption_clips)
618
+ logger.info(f"Added {len(caption_clips)} caption clips")
619
+
620
  # Write final video
621
  logger.info(f"Writing video with effects: crossfade={CROSSFADE_DURATION}s, zoom={ZOOM_FACTOR}x")
622
  video.write_videofile(
modules/video_creator/services/libraries/video_composer.py CHANGED
@@ -285,19 +285,19 @@ class VideoComposer:
285
  # Allocating 20% of height for caption box
286
 
287
  # Try local font first, then system fonts
288
- font_path = Path(__file__).parent.parent.parent / "static" / "fonts" / "TheBoldFont.ttf"
289
- if font_path.exists():
290
- font_name = str(font_path)
 
 
 
 
 
 
 
 
291
  else:
292
- # Use DejaVu (installed in Dockerfile) - full path for Linux
293
- dejavu_path = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
294
- liberation_path = "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf"
295
- if Path(dejavu_path).exists():
296
- font_name = dejavu_path
297
- elif Path(liberation_path).exists():
298
- font_name = liberation_path
299
- else:
300
- font_name = "DejaVu-Sans-Bold" # Fallback name
301
 
302
  txt_clip = TextClip(
303
  caption["text"],
 
285
  # Allocating 20% of height for caption box
286
 
287
  # Try local font first, then system fonts
288
+ # Priority: TheBoldFont (static/fonts) > DejaVu > Liberation
289
+ thebold_path = Path(__file__).parent.parent.parent.parent.parent / "static" / "fonts" / "THEBOLDFONT-FREEVERSION.ttf"
290
+ dejavu_path = Path("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf")
291
+ liberation_path = Path("/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf")
292
+
293
+ if thebold_path.exists():
294
+ font_name = str(thebold_path)
295
+ elif dejavu_path.exists():
296
+ font_name = str(dejavu_path)
297
+ elif liberation_path.exists():
298
+ font_name = str(liberation_path)
299
  else:
300
+ font_name = "DejaVu-Sans-Bold" # Fallback name
 
 
 
 
 
 
 
 
301
 
302
  txt_clip = TextClip(
303
  caption["text"],
static/fonts/THEBOLDFONT-FREEVERSION.ttf ADDED
Binary file (15.4 kB). View file