Spaces:
Runtime error
Runtime error
| <|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|> |