<|begin_of_box|>import gradio as gr import numpy as np import cv2 import tempfile import os from PIL import Image import time # Simulated outpainting function (in a real application, this would use a proper model) def outpaint_video_with_reference(input_video, reference_image, outpaint_ratio=0.5): """ Simulate video outpainting to match reference image height. In a real implementation, this would use a diffusion model or similar. """ try: # Create temporary files for processing with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as temp_video: temp_video_path = temp_video.name with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as temp_ref: temp_ref_path = temp_ref.name # Save uploaded files with open(input_video, 'wb') as f: f.write(open(input_video, 'rb').read()) with open(reference_image, 'wb') as f: f.write(open(reference_image, 'rb').read()) # Get video and reference image dimensions cap = cv2.VideoCapture(input_video) ref_img = Image.open(reference_image) ref_height = ref_img.height ref_width = ref_img.width # Get original video dimensions original_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) original_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # Calculate new dimensions to match reference height new_height = ref_height scale_factor = new_height / original_height new_width = int(original_width * scale_factor) # Create output video writer fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(temp_video_path, fourcc, 30.0, (new_width, new_height)) frame_count = 0 total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) while cap.isOpened(): ret, frame = cap.read() if not ret: break # Resize frame to match new dimensions resized_frame = cv2.resize(frame, (new_width, new_height)) # Simulate outpainting by adding a border that matches reference style # In a real implementation, this would use AI to generate content border_size = int(new_width * outpaint_ratio) if border_size > 0: # Create a border that tries to match the reference image style border_color = np.mean(resized_frame, axis=(0, 1)) bordered_frame = cv2.copyMakeBorder( resized_frame, 0, 0, border_size, border_size, cv2.BORDER_CONSTANT, value=border_color ) out.write(bordered_frame) else: out.write(resized_frame) frame_count += 1 if frame_count % 10 == 0: yield f"Processing frame {frame_count}/{total_frames}..." cap.release() out.release() # Return the processed video yield temp_video_path except Exception as e: yield f"Error: {str(e)}" finally: # Clean up temporary files try: if 'temp_video_path' in locals() and os.path.exists(temp_video_path): os.unlink(temp_video_path) if 'temp_ref_path' in locals() and os.path.exists(temp_ref_path): os.unlink(temp_ref_path) except: pass # Create the Gradio interface with gr.Blocks() as demo: gr.Markdown("# 🎬 Video Outpainting with Reference Height Matching") gr.Markdown("Upload a video and a reference image. The video will be outpainted to match the height of the reference image.") with gr.Row(): with gr.Column(): gr.Markdown("### Input Video") video_input = gr.Video(label="Upload Video", type="filepath") gr.Markdown("### Reference Image") reference_input = gr.Image(label="Upload Reference Image", type="filepath") outpaint_ratio = gr.Slider( minimum=0.1, maximum=1.0, value=0.3, step=0.1, label="Outpaint Ratio (percentage of new width)" ) process_button = gr.Button("Process Video", variant="primary") with gr.Column(): gr.Markdown("### Output") output_video = gr.Video(label="Processed Video") status_text = gr.Textbox(label="Status", interactive=False) # Process function def process_video(video, reference, ratio): if not video or not reference: return None, "Please upload both video and reference image" status_text = "" for status in outpaint_video_with_reference(video, reference, ratio): if isinstance(status, str): status_text = status yield None, status_text else: yield status, "Processing complete!" process_button.click( fn=process_video, inputs=[video_input, reference_input, outpaint_ratio], outputs=[output_video, status_text], api_visibility="public" ) # Launch the app with modern theme demo.launch( theme=gr.themes.Soft( primary_hue="blue", secondary_hue="indigo", neutral_hue="slate", font=gr.themes.GoogleFont("Inter"), text_size="lg", spacing_size="lg", radius_size="md" ).set( button_primary_background_fill="*primary_600", button_primary_background_fill_hover="*primary_700", block_title_text_weight="600", ), footer_links=[{"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}] )<|end_of_box|>