vidvstudio / app.py
arxivgpt kim
Update app.py
eb8da3e verified
import gradio as gr
from moviepy.editor import VideoFileClip, CompositeVideoClip
import cv2
import numpy as np
import tempfile
import shutil
import moviepy.video.fx.all as vfx
import os
from moviepy.editor import ImageSequenceClip
def remove_green_background(overlay_video_bytes):
overlay_temp = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
overlay_temp.write(overlay_video_bytes)
overlay_temp.close()
overlay_video_path = overlay_temp.name
cap = cv2.VideoCapture(overlay_video_path)
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
fps = cap.get(cv2.CAP_PROP_FPS)
no_bg_temp = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
out = cv2.VideoWriter(no_bg_temp.name, cv2.VideoWriter_fourcc(*'mp4v'), fps, (frame_width, frame_height), True)
while True:
ret, frame = cap.read()
if not ret:
break
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_green = np.array([36, 25, 25])
upper_green = np.array([86, 255,255])
mask = cv2.inRange(hsv, lower_green, upper_green)
mask_inv = cv2.bitwise_not(mask)
bg_removed = cv2.bitwise_and(frame, frame, mask=mask_inv)
out.write(bg_removed)
cap.release()
out.release()
return no_bg_temp.name
position_map = {
"Top Left": ('left', 'top'),
"Top Center": ('center', 'top'),
"Top Right": ('right', 'top'),
"Middle Left": ('left', 'center'),
"Middle Center": ('center', 'center'),
"Middle Right": ('right', 'center'),
"Bottom Left": ('left', 'bottom'),
"Bottom Center": ('center', 'bottom'),
"Bottom Right": ('right', 'bottom'),
}
def remove_green_background_and_save_images(overlay_video_path):
cap = cv2.VideoCapture(overlay_video_path)
frame_idx = 0
temp_dir = tempfile.mkdtemp()
while True:
ret, frame = cap.read()
if not ret:
break
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_green = np.array([36, 25, 25])
upper_green = np.array([86, 255,255])
mask = cv2.inRange(hsv, lower_green, upper_green)
mask_inv = cv2.bitwise_not(mask)
bgra = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
bgra[:, :, 3] = mask_inv
cv2.imwrite(os.path.join(temp_dir, f"frame_{frame_idx:05d}.png"), bgra)
frame_idx += 1
cap.release()
return temp_dir
def combine_videos(background_video_bytes, overlay_video_bytes, position, scale):
background_temp = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
background_temp.write(background_video_bytes)
background_temp.close()
background_video_path = background_temp.name
overlay_temp = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
overlay_temp.write(overlay_video_bytes)
overlay_temp.close()
overlay_video_path = overlay_temp.name
temp_image_sequence_dir = remove_green_background_and_save_images(overlay_video_path)
overlay_clip = ImageSequenceClip(temp_image_sequence_dir, fps=24).resize(scale / 10)
background_clip = VideoFileClip(background_video_path)
pos = position_map[position]
final_clip = CompositeVideoClip([background_clip, overlay_clip.set_position(pos)], size=background_clip.size)
output_video_path = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4').name
final_clip.write_videofile(output_video_path, codec='libx264', audio_codec='aac')
shutil.rmtree(temp_image_sequence_dir)
os.unlink(background_temp.name)
os.unlink(overlay_temp.name)
return output_video_path
css = """
footer {
visibility: hidden;
}
"""
iface = gr.Interface(css=css,
fn=combine_videos,
inputs=[
gr.File(type="binary", label="Background Video"),
gr.File(type="binary", label="Overlay Video"),
gr.Dropdown(["Top Left", "Top Center", "Top Right", "Middle Left", "Middle Center", "Middle Right", "Bottom Left", "Bottom Center", "Bottom Right"], label="Position"),
gr.Slider(minimum=1, maximum=100, value=5, label="Scale (x0.1)"),
],
outputs=gr.Video(label="Combined Video")
)
if __name__ == "__main__":
iface.launch()