viral-clip-generator / utils /video_processor.py
yasvanthkumar's picture
Create utils/video_processor.py
c55b141 verified
import cv2
import subprocess
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip, AudioFileClip
from moviepy.video.fx import all as vfx
import numpy as np
from pathlib import Path
import tempfile
class VideoProcessor:
def __init__(self):
self.temp_dir = tempfile.mkdtemp()
def extract_audio(self, video_path):
"""Extract audio from video file"""
try:
video = VideoFileClip(video_path)
audio_path = Path(self.temp_dir) / "audio.wav"
video.audio.write_audiofile(str(audio_path), logger=None)
video.close()
return str(audio_path)
except Exception as e:
raise Exception(f"Audio extraction failed: {str(e)}")
def extract_clip(self, video_path, start_time, end_time):
"""Extract a segment from video"""
try:
video = VideoFileClip(video_path)
clip = video.subclip(start_time, end_time)
# Resize to 9:16 for shorts
target_width = 1080
target_height = 1920
# Calculate scaling
scale = max(target_width / clip.w, target_height / clip.h)
new_w = int(clip.w * scale)
new_h = int(clip.h * scale)
# Resize and crop
clip_resized = clip.resize((new_w, new_h))
# Center crop
x_center = new_w / 2
y_center = new_h / 2
x1 = int(x_center - target_width / 2)
y1 = int(y_center - target_height / 2)
clip_cropped = clip_resized.crop(
x1=x1, y1=y1,
x2=x1 + target_width,
y2=y1 + target_height
)
output_path = Path(self.temp_dir) / f"clip_{start_time}_{end_time}.mp4"
clip_cropped.write_videofile(
str(output_path),
codec='libx264',
audio_codec='aac',
logger=None
)
video.close()
clip.close()
clip_resized.close()
clip_cropped.close()
return str(output_path)
except Exception as e:
raise Exception(f"Clip extraction failed: {str(e)}")
def add_captions(self, video_path, captions_data):
"""Add animated captions to video"""
try:
video = VideoFileClip(video_path)
clips = [video]
for caption in captions_data['captions']:
# Create text clip
txt_clip = TextClip(
caption['text'],
fontsize=captions_data['fontsize'],
color=captions_data['color'],
stroke_color=captions_data['stroke_color'],
stroke_width=captions_data['stroke_width'],
font='Arial-Bold',
method='caption',
size=(video.w * 0.9, None)
)
# Position and timing
txt_clip = txt_clip.set_position(('center', 'center'))
txt_clip = txt_clip.set_start(caption['start'])
txt_clip = txt_clip.set_duration(caption['duration'])
# Add animation
if captions_data['animation'] == 'pop':
txt_clip = txt_clip.crossfadein(0.2)
clips.append(txt_clip)
# Compose final video
final_video = CompositeVideoClip(clips)
output_path = video_path.replace('.mp4', '_captioned.mp4')
final_video.write_videofile(
output_path,
codec='libx264',
audio_codec='aac',
logger=None
)
video.close()
final_video.close()
return output_path
except Exception as e:
raise Exception(f"Caption addition failed: {str(e)}")
def add_sound_effects(self, video_path, sound_effects):
"""Add sound effects to video at specific timestamps"""
try:
# This would integrate with sound effect library
# For now, return original video
return video_path
except Exception as e:
raise Exception(f"Sound effect addition failed: {str(e)}")