mindfull / simple_video_gen.py
IamSamk
Mindfull Gradio Space deploy
27caffe
Raw
History Blame Contribute Delete
8.53 kB
"""
Simple Video Generation using SadTalker
Integrates with our Mindfull pipeline
"""
import os
import sys
import subprocess
import tempfile
import shutil
from pathlib import Path
import cv2
import numpy as np
def generate_video_simple(image_path, audio_path, output_path):
"""
Generate video using SadTalker with fallback options
"""
try:
# Use SadTalker with skip_wav2lip - this should work reliably now
print("Attempting SadTalker video generation...")
success = generate_with_sadtalker(image_path, audio_path, output_path)
if success and os.path.exists(output_path):
size = os.path.getsize(output_path)
print(f"βœ“ Video generation successful: {output_path} (size: {size} bytes)")
return True
else:
print(f"βœ— SadTalker failed to generate video")
return False
except Exception as e:
print(f"βœ— Video generation error: {e}")
return False
def generate_with_sadtalker(image_path, audio_path, output_path):
"""
Use enhanced SadTalker + Wav2Lip pipeline for video generation
"""
try:
# Apply patches first
import python313_compat_patch
# Try to import SadTalker components
sadtalker_path = "sadtalker+wav2lip"
if os.path.exists(sadtalker_path):
# Try enhanced pipeline first
enhanced_script = os.path.join(sadtalker_path, "enhanced_pipeline.py")
if os.path.exists(enhanced_script):
# Use enhanced pipeline with automatic quality detection
cmd = [
sys.executable,
enhanced_script,
"--source_image", image_path,
"--audio", audio_path,
"--output", output_path,
"--use_wav2lip" # Let the pipeline decide based on quality
]
else:
# Fallback to simple pipeline
cmd = [
sys.executable,
os.path.join(sadtalker_path, "simple_pipeline.py"),
"--source_image", image_path,
"--audio", audio_path,
"--output", output_path,
"--skip_wav2lip" # Skip Wav2Lip to preserve SadTalker animation
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=600)
print(f"Enhanced Pipeline STDOUT:\n{result.stdout}")
if result.stderr:
print(f"Enhanced Pipeline STDERR:\n{result.stderr}")
# Check if pipeline successfully created the output file
if result.returncode == 0 and os.path.exists(output_path):
size = os.path.getsize(output_path)
if size > 0:
print(f"βœ“ Enhanced video generated successfully: {output_path} (size: {size} bytes)")
return True
else:
print(f"βœ— Enhanced pipeline output file is empty: {output_path}")
return False
else:
print(f"βœ— SadTalker pipeline failed or output not created")
print(f"Return code: {result.returncode}")
return False
else:
print("βœ— SadTalker directory not found")
return False
except Exception as e:
print(f"βœ— SadTalker generation failed: {e}")
return False
def generate_basic_video(image_path, audio_path, output_path):
"""
Generate basic video by combining static image with audio
"""
try:
# Use FFmpeg to create video from static image + audio
cmd = [
"ffmpeg", "-y",
"-loop", "1",
"-i", image_path,
"-i", audio_path,
"-c:v", "libx264",
"-c:a", "aac",
"-b:a", "192k",
"-shortest",
"-pix_fmt", "yuv420p",
output_path
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
if result.returncode == 0 and os.path.exists(output_path):
print(f"βœ“ Basic video generated: {output_path}")
return True
else:
print(f"βœ— FFmpeg failed: {result.stderr}")
return False
except subprocess.TimeoutExpired:
print("βœ— FFmpeg generation timed out")
return False
except Exception as e:
print(f"βœ— Basic video generation failed: {e}")
return False
def generate_placeholder_video(image_path, audio_path, output_path):
"""
Create a placeholder video with simple effects
"""
try:
import soundfile as sf
import moviepy.editor as mp
# Load audio to get duration
try:
audio_data, sample_rate = sf.read(audio_path)
duration = len(audio_data) / sample_rate
except:
duration = 5.0 # Default 5 seconds
# Load and prepare image
image = cv2.imread(image_path)
if image is None:
raise ValueError(f"Could not load image: {image_path}")
# Resize image to standard video dimensions
height, width = image.shape[:2]
target_width, target_height = 640, 480
if width != target_width or height != target_height:
image = cv2.resize(image, (target_width, target_height))
# Create video with slight zoom/movement effect
fps = 25
total_frames = int(duration * fps)
# Ensure output directory exists
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# Create temporary video file
temp_video = output_path.replace('.mp4', '_temp.mp4')
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(temp_video, fourcc, fps, (target_width, target_height))
for frame_num in range(total_frames):
# Add slight zoom effect
zoom_factor = 1.0 + 0.05 * np.sin(frame_num * 0.1)
if zoom_factor != 1.0:
center_x, center_y = target_width // 2, target_height // 2
new_width = int(target_width / zoom_factor)
new_height = int(target_height / zoom_factor)
x1 = max(0, center_x - new_width // 2)
y1 = max(0, center_y - new_height // 2)
x2 = min(target_width, x1 + new_width)
y2 = min(target_height, y1 + new_height)
cropped = image[y1:y2, x1:x2]
frame = cv2.resize(cropped, (target_width, target_height))
else:
frame = image.copy()
out.write(frame)
out.release()
# Combine with audio using FFmpeg
cmd = [
"ffmpeg", "-y",
"-i", temp_video,
"-i", audio_path,
"-c:v", "libx264",
"-c:a", "aac",
"-shortest",
output_path
]
result = subprocess.run(cmd, capture_output=True, text=True)
# Clean up temp video
if os.path.exists(temp_video):
os.remove(temp_video)
if result.returncode == 0 and os.path.exists(output_path):
print(f"βœ“ Placeholder video generated: {output_path}")
return True
else:
print(f"βœ— Placeholder video generation failed")
return False
except Exception as e:
print(f"βœ— Placeholder video generation failed: {e}")
return False
if __name__ == "__main__":
# Test video generation
test_image = "avatar_assets/officer.png"
test_audio = "outputs/test_audio_simple.wav"
test_output = "outputs/test_video.mp4"
print("Testing video generation...")
if os.path.exists(test_image) and os.path.exists(test_audio):
if generate_video_simple(test_image, test_audio, test_output):
print("βœ“ Video generation successful")
else:
print("βœ— Video generation failed")
else:
print(f"βœ— Missing test files:")
print(f" Image: {test_image} - {'βœ“' if os.path.exists(test_image) else 'βœ—'}")
print(f" Audio: {test_audio} - {'βœ“' if os.path.exists(test_audio) else 'βœ—'}")