mini-demo-982 / utils.py
Cri123's picture
Deploy Gradio app with multiple files
09979af verified
import numpy as np
import cv2
from PIL import Image, ImageEnhance
import tempfile
import os
from moviepy.editor import ImageClip, AudioFileClip, CompositeVideoClip
import librosa
import soundfile as sf
import subprocess
def process_image_for_video(image, style="static"):
"""
Process image for video creation based on style
Args:
image: PIL Image
style: Animation style
Returns:
str: Path to processed image
"""
# Convert to RGB if necessary
if image.mode != 'RGB':
image = image.convert('RGB')
# Enhance image quality
enhancer = ImageEnhance.Contrast(image)
image = enhancer.enhance(1.2)
enhancer = ImageEnhance.Sharpness(image)
image = enhancer.enhance(1.1)
# Save processed image
temp_path = os.path.join(tempfile.gettempdir(), f"processed_{uuid.uuid4().hex}.jpg")
image.save(temp_path, quality=95)
return temp_path
def extend_audio_to_duration(audio_path, target_duration):
"""
Extend audio to target duration by looping and fading
Args:
audio_path: Path to original audio file
target_duration: Target duration in seconds
Returns:
str: Path to extended audio file
"""
# Load audio
y, sr = librosa.load(audio_path)
original_duration = len(y) / sr
if original_duration >= target_duration:
return audio_path
# Calculate how many times to loop
loops_needed = int(target_duration / original_duration) + 1
# Create extended audio
extended_audio = np.tile(y, loops_needed)
# Trim to exact duration
target_samples = int(target_duration * sr)
extended_audio = extended_audio[:target_samples]
# Apply fade in/out
fade_samples = int(0.5 * sr) # 0.5 second fade
extended_audio[:fade_samples] *= np.linspace(0, 1, fade_samples)
extended_audio[-fade_samples:] *= np.linspace(1, 0, fade_samples)
# Save extended audio
output_path = os.path.join(tempfile.gettempdir(), f"extended_{uuid.uuid4().hex}.wav")
sf.write(output_path, extended_audio, sr)
return output_path
def create_video_with_audio(image_path, audio_path, duration):
"""
Create video by combining image and audio
Args:
image_path: Path to image file
audio_path: Path to audio file
duration: Video duration in seconds
Returns:
str: Path to output video file
"""
# Create video clip from image
image_clip = ImageClip(image_path, duration=duration)
# Create audio clip
audio_clip = AudioFileClip(audio_path)
# Set audio to video
video_clip = image_clip.set_audio(audio_clip)
# Set fps
video_clip.fps = 24
# Output path
output_path = os.path.join(tempfile.gettempdir(), f"video_{uuid.uuid4().hex}.mp4")
# Write video file
video_clip.write_videofile(
output_path,
codec='libx264',
audio_codec='aac',
temp_audiofile=os.path.join(tempfile.gettempdir(), f"temp_audio_{uuid.uuid4().hex}.m4a"),
remove_temp=True
)
# Close clips
image_clip.close()
audio_clip.close()
video_clip.close()
return output_path
def cleanup_temp_files(file_paths):
"""Clean up temporary files"""
for file_path in file_paths:
try:
if os.path.exists(file_path):
os.remove(file_path)
except Exception as e:
print(f"Error removing {file_path}: {e}")
def apply_video_effects(image_path, style, duration):
"""
Apply video effects to create animated video from static image
Args:
image_path: Path to image
style: Animation style
duration: Duration in seconds
Returns:
str: Path to animated video
"""
# Read image
image = cv2.imread(image_path)
height, width = image.shape[:2]
# Create temporary video path
temp_video = os.path.join(tempfile.gettempdir(), f"animated_{uuid.uuid4().hex}.mp4")
# Setup video writer
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(temp_video, fourcc, 30.0, (width, height))
frames = int(duration * 30)
for i in range(frames):
progress = i / frames
if style == "zoom_in":
# Zoom in effect
scale = 1.0 + (progress * 0.5)
new_height = int(height / scale)
new_width = int(width / scale)
y_start = (height - new_height) // 2
x_start = (width - new_width) // 2
frame = image[y_start:y_start+new_height, x_start:x_start+new_width]
frame = cv2.resize(frame, (width, height))
elif style == "zoom_out":
# Zoom out effect
scale = 1.5 - (progress * 0.5)
new_height = int(height / scale)
new_width = int(width / scale)
y_start = (height - new_height) // 2
x_start = (width - new_width) // 2
frame = image[y_start:y_start+new_height, x_start:x_start+new_width]
frame = cv2.resize(frame, (width, height))
elif style == "pan_left":
# Pan left effect
offset = int(progress * (width * 0.3))
frame = image[:, offset:offset+width] if offset+width <= width else image[:, -width:]
elif style == "pan_right":
# Pan right effect
offset = int((1 - progress) * (width * 0.3))
frame = image[:, offset:offset+width] if offset+width <= width else image[:, -width:]
else: # static
frame = image
out.write(frame)
out.release()
return temp_video