Anchal23 commited on
Commit
f30736d
·
verified ·
1 Parent(s): ec5062c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -14
app.py CHANGED
@@ -88,6 +88,23 @@ st.markdown("""
88
  </style>
89
  """, unsafe_allow_html=True)
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  def extract_dominant_colors(image, n_colors=3):
92
  """Extract dominant neon-suitable colors from the image"""
93
  # Resize for faster processing
@@ -247,7 +264,7 @@ def create_enhanced_neon_glow(edge_image, colors, glow_size=20):
247
  result = np.clip(result, 0, 255).astype(np.uint8)
248
  return result
249
 
250
- def create_human_like_drawing(image, edges, strokes, num_frames, colors, glow_size=20, bg_color=(0, 0, 0), hold_drawn_frames=0):
251
  """Create drawing animation that progressively reveals the original image with accurate colors"""
252
  height, width = edges.shape
253
  frames = []
@@ -349,7 +366,7 @@ def create_human_like_drawing(image, edges, strokes, num_frames, colors, glow_si
349
 
350
  # Add final complete frame - show 100% original image
351
  final_frame = image.copy()
352
- frames.extend([final_frame] * 25) # Hold for 25 frames
353
 
354
  gc.collect()
355
  return frames
@@ -467,23 +484,50 @@ def create_outro_frame(text, width, height, bg_color=(10, 10, 15),
467
 
468
  return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
469
 
470
- def add_audio_to_video(video_path, audio_path, output_path):
471
- """Add audio to video using ffmpeg"""
472
  import subprocess
473
 
474
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  cmd = [
476
  'ffmpeg', '-y', '-hide_banner', '-loglevel', 'error',
477
  '-i', video_path,
 
478
  '-i', audio_path,
479
- '-c:v', 'libx264',
480
- '-preset', 'fast',
481
  '-c:a', 'aac',
482
  '-b:a', '192k',
483
- '-shortest',
484
- output_path
485
  ]
486
- result = subprocess.run(cmd, capture_output=True, text=True)
 
 
 
 
 
 
487
  if result.returncode != 0:
488
  st.warning(f"Audio mixing warning: {result.stderr}")
489
  return False
@@ -491,9 +535,13 @@ def add_audio_to_video(video_path, audio_path, output_path):
491
  except FileNotFoundError:
492
  st.error("FFmpeg not found. Please install FFmpeg to add audio.")
493
  return False
 
 
 
494
  except Exception as e:
495
  st.error(f"Audio error: {str(e)}")
496
  return False
 
497
 
498
  def create_video(frames, fps, output_path, aspect_ratio):
499
  """Create video from frames"""
@@ -547,7 +595,15 @@ with col1:
547
 
548
  if uploaded_file:
549
  image = Image.open(uploaded_file)
550
- st.image(image, caption="Original Image")
 
 
 
 
 
 
 
 
551
 
552
  st.markdown("</div>", unsafe_allow_html=True)
553
 
@@ -557,7 +613,12 @@ with col2:
557
 
558
  # Simple settings
559
  duration = st.slider("Animation Duration (seconds)", 5, 60, 10)
560
- hold_drawn = st.slider("Hold Drawn Image (seconds)", 0, 10, 3)
 
 
 
 
 
561
 
562
  st.info("✨ Colors and effects are automatically detected from your image!")
563
 
@@ -578,7 +639,35 @@ col6, col7 = st.columns(2)
578
 
579
  with col6:
580
  aspect_ratio = st.selectbox("Aspect Ratio", ["16:9", "9:16", "4:5", "1:1"])
581
- audio_file = st.file_uploader("Background Music (Optional)", type=['mp3', 'wav', 'ogg'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
 
583
  with col7:
584
  fps = st.slider("Frame Rate (FPS)", 24, 60, 30)
@@ -661,11 +750,13 @@ if st.button("🎬 Generate Neon Drawing Video", type="primary"):
661
  progress_bar.progress(55)
662
 
663
  hold_drawn_frames = int(hold_drawn * fps)
 
664
 
665
  frames = create_human_like_drawing(
666
  image_cv, edges, strokes, num_frames,
667
  colors=neon_colors, glow_size=glow_intensity,
668
- bg_color=bg_color, hold_drawn_frames=hold_drawn_frames
 
669
  )
670
 
671
  if not frames:
@@ -725,7 +816,9 @@ if st.button("🎬 Generate Neon Drawing Video", type="primary"):
725
  final_video = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
726
  final_video.close()
727
 
728
- if add_audio_to_video(video_path, temp_audio.name, final_video.name):
 
 
729
  final_video_path = final_video.name
730
  try:
731
  os.unlink(video_path)
 
88
  </style>
89
  """, unsafe_allow_html=True)
90
 
91
+ def detect_best_aspect_ratio(image):
92
+ """Detect the best aspect ratio for the image"""
93
+ height, width = image.shape[:2]
94
+ current_ratio = width / height
95
+
96
+ ratios = {
97
+ "16:9": 16/9,
98
+ "9:16": 9/16,
99
+ "4:5": 4/5,
100
+ "1:1": 1
101
+ }
102
+
103
+ # Find closest ratio
104
+ best_ratio = min(ratios.items(), key=lambda x: abs(x[1] - current_ratio))
105
+
106
+ return best_ratio[0], current_ratio
107
+
108
  def extract_dominant_colors(image, n_colors=3):
109
  """Extract dominant neon-suitable colors from the image"""
110
  # Resize for faster processing
 
264
  result = np.clip(result, 0, 255).astype(np.uint8)
265
  return result
266
 
267
+ def create_human_like_drawing(image, edges, strokes, num_frames, colors, glow_size=20, bg_color=(0, 0, 0), hold_drawn_frames=0, hold_final_frames=0):
268
  """Create drawing animation that progressively reveals the original image with accurate colors"""
269
  height, width = edges.shape
270
  frames = []
 
366
 
367
  # Add final complete frame - show 100% original image
368
  final_frame = image.copy()
369
+ frames.extend([final_frame] * max(hold_final_frames, 25)) # Hold for specified frames or minimum 25
370
 
371
  gc.collect()
372
  return frames
 
484
 
485
  return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
486
 
487
+ def add_audio_to_video(video_path, audio_path, output_path, start_time=0.0, fadeout_duration=2.0):
488
+ """Add audio to video using ffmpeg with start time and fade out"""
489
  import subprocess
490
 
491
  try:
492
+ # Build ffmpeg command with audio filters
493
+ audio_filters = []
494
+
495
+ # Add fade out filter
496
+ if fadeout_duration > 0:
497
+ # Get video duration to calculate fade start
498
+ probe_cmd = [
499
+ 'ffprobe', '-v', 'error', '-show_entries',
500
+ 'format=duration', '-of',
501
+ 'default=noprint_wrappers=1:nokey=1', video_path
502
+ ]
503
+ try:
504
+ result = subprocess.run(probe_cmd, capture_output=True, text=True, timeout=10)
505
+ video_duration = float(result.stdout.strip())
506
+ fade_start = max(0, video_duration - fadeout_duration)
507
+ audio_filters.append(f"afade=t=out:st={fade_start}:d={fadeout_duration}")
508
+ except:
509
+ # If can't get duration, use default fade
510
+ audio_filters.append(f"afade=t=out:d={fadeout_duration}")
511
+
512
+ # Combine filters
513
+ filter_str = ",".join(audio_filters) if audio_filters else None
514
+
515
  cmd = [
516
  'ffmpeg', '-y', '-hide_banner', '-loglevel', 'error',
517
  '-i', video_path,
518
+ '-ss', str(start_time), # Start audio from this time
519
  '-i', audio_path,
520
+ '-c:v', 'copy', # Copy video without re-encoding
 
521
  '-c:a', 'aac',
522
  '-b:a', '192k',
 
 
523
  ]
524
+
525
+ if filter_str:
526
+ cmd.extend(['-af', filter_str])
527
+
528
+ cmd.extend(['-shortest', output_path])
529
+
530
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
531
  if result.returncode != 0:
532
  st.warning(f"Audio mixing warning: {result.stderr}")
533
  return False
 
535
  except FileNotFoundError:
536
  st.error("FFmpeg not found. Please install FFmpeg to add audio.")
537
  return False
538
+ except subprocess.TimeoutExpired:
539
+ st.error("Audio processing timeout. Try a shorter audio file.")
540
+ return False
541
  except Exception as e:
542
  st.error(f"Audio error: {str(e)}")
543
  return False
544
+
545
 
546
  def create_video(frames, fps, output_path, aspect_ratio):
547
  """Create video from frames"""
 
595
 
596
  if uploaded_file:
597
  image = Image.open(uploaded_file)
598
+ st.image(image, caption="Original Image", use_container_width=True)
599
+
600
+ # Auto-detect best aspect ratio
601
+ image_array = np.array(image)
602
+ image_cv = cv2.cvtColor(image_array, cv2.COLOR_RGB2BGR)
603
+ best_ratio, current_ratio = detect_best_aspect_ratio(image_cv)
604
+
605
+ st.success(f"📐 **Recommended Aspect Ratio:** {best_ratio}")
606
+ st.info(f"ℹ️ Current image ratio: {current_ratio:.2f}:1")
607
 
608
  st.markdown("</div>", unsafe_allow_html=True)
609
 
 
613
 
614
  # Simple settings
615
  duration = st.slider("Animation Duration (seconds)", 5, 60, 10)
616
+
617
+ col_hold1, col_hold2 = st.columns(2)
618
+ with col_hold1:
619
+ hold_drawn = st.slider("Hold Drawn Image (sec)", 0, 10, 3)
620
+ with col_hold2:
621
+ hold_final = st.slider("Hold Final Image (sec)", 0, 10, 2)
622
 
623
  st.info("✨ Colors and effects are automatically detected from your image!")
624
 
 
639
 
640
  with col6:
641
  aspect_ratio = st.selectbox("Aspect Ratio", ["16:9", "9:16", "4:5", "1:1"])
642
+
643
+ st.markdown("---")
644
+ st.subheader("🎵 Background Audio")
645
+ audio_file = st.file_uploader("Upload Audio (Optional)", type=['mp3', 'wav', 'ogg', 'm4a'])
646
+
647
+ if audio_file:
648
+ # Audio preview
649
+ st.audio(audio_file, format=f'audio/{audio_file.name.split(".")[-1]}')
650
+
651
+ # Audio controls
652
+ col_audio1, col_audio2 = st.columns(2)
653
+ with col_audio1:
654
+ audio_start_time = st.number_input(
655
+ "Start Time (seconds)",
656
+ min_value=0.0,
657
+ max_value=300.0,
658
+ value=0.0,
659
+ step=0.5,
660
+ help="Audio will start from this time"
661
+ )
662
+ with col_audio2:
663
+ audio_fadeout = st.number_input(
664
+ "Fade Out Duration (sec)",
665
+ min_value=0.0,
666
+ max_value=10.0,
667
+ value=2.0,
668
+ step=0.5,
669
+ help="Smooth fade out at the end"
670
+ )
671
 
672
  with col7:
673
  fps = st.slider("Frame Rate (FPS)", 24, 60, 30)
 
750
  progress_bar.progress(55)
751
 
752
  hold_drawn_frames = int(hold_drawn * fps)
753
+ hold_final_frames = int(hold_final * fps)
754
 
755
  frames = create_human_like_drawing(
756
  image_cv, edges, strokes, num_frames,
757
  colors=neon_colors, glow_size=glow_intensity,
758
+ bg_color=bg_color, hold_drawn_frames=hold_drawn_frames,
759
+ hold_final_frames=hold_final_frames
760
  )
761
 
762
  if not frames:
 
816
  final_video = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
817
  final_video.close()
818
 
819
+ if add_audio_to_video(video_path, temp_audio.name, final_video.name,
820
+ start_time=audio_start_time,
821
+ fadeout_duration=audio_fadeout):
822
  final_video_path = final_video.name
823
  try:
824
  os.unlink(video_path)