Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import os | |
| import tempfile | |
| import subprocess | |
| from pathlib import Path | |
| def merge_videos_clips(video_files): | |
| """ | |
| Merge multiple video clips smoothly without gaps between them. | |
| Uses ffmpeg to concatenate videos with a filter to ensure seamless transitions. | |
| """ | |
| if not video_files or len(video_files) < 2: | |
| return None, "Please upload at least 2 video clips to merge." | |
| try: | |
| # Create a temporary directory for processing | |
| with tempfile.TemporaryDirectory() as temp_dir: | |
| # Create a file list for ffmpeg concatenation | |
| file_list_path = os.path.join(temp_dir, "file_list.txt") | |
| with open(file_list_path, 'w') as f: | |
| for video_file in video_files: | |
| # Write the file path in the format ffmpeg expects | |
| f.write(f"file '{video_file}'\n") | |
| # Output file path | |
| output_path = os.path.join(temp_dir, "merged_video.mp4") | |
| # Use ffmpeg to concatenate videos with a filter to ensure seamless transitions | |
| # The concat filter ensures no gaps between clips | |
| cmd = [ | |
| 'ffmpeg', | |
| '-f', 'concat', | |
| '-safe', '0', | |
| '-i', file_list_path, | |
| '-c', 'copy', | |
| '-vf', 'setpts=N/FRAME_RATE/TB', # Ensure consistent timing | |
| '-af', 'apad=pad_dur=0', # No audio padding | |
| '-shortest', | |
| output_path | |
| ] | |
| # Run ffmpeg command | |
| result = subprocess.run(cmd, capture_output=True, text=True) | |
| if result.returncode != 0: | |
| return None, f"Error during video merging: {result.stderr}" | |
| # Check if output file was created | |
| if not os.path.exists(output_path): | |
| return None, "Failed to create merged video file." | |
| return output_path, "β Videos merged successfully! No gaps between clips." | |
| except Exception as e: | |
| return None, f"Error during video processing: {str(e)}" | |
| def create_video_merger_app(): | |
| """Create the Gradio application for video merging.""" | |
| with gr.Blocks(title="Video Clip Merger - Smooth Concatenation", theme=gr.themes.Soft()) as demo: | |
| # Header with title and description | |
| gr.Markdown( | |
| """ | |
| <div style="text-align: center; margin-bottom: 20px;"> | |
| <h1>π¬ Video Clip Merger (Smooth Concatenation)</h1> | |
| <p>Upload multiple video clips and merge them seamlessly without gaps</p> | |
| <p style="color: #666; font-size: 0.9em;"> | |
| This tool eliminates pauses between clips and ensures smooth playback. | |
| Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #1976d2;">anycoder</a> | |
| </p> | |
| </div> | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π€ Upload Video Clips") | |
| gr.Markdown( | |
| """ | |
| Upload 2 or more video clips in MP4, MOV, or AVI format. | |
| Videos will be merged in the order they appear in the list. | |
| """ | |
| ) | |
| video_input = gr.Files( | |
| label="Upload Video Clips", | |
| file_types=["video"], | |
| type="filepath" | |
| ) | |
| gr.Markdown("### βοΈ Settings") | |
| merge_btn = gr.Button("π Merge Videos", variant="primary", size="lg") | |
| with gr.Column(scale=1): | |
| gr.Markdown("### πΉ Merged Result") | |
| video_output = gr.Video( | |
| label="Merged Video", | |
| elem_classes="video-output" | |
| ) | |
| status_output = gr.Textbox( | |
| label="Status", | |
| lines=3, | |
| placeholder="Status messages will appear here..." | |
| ) | |
| # Example section | |
| gr.Markdown( | |
| """ | |
| ### βΉοΈ How to Use | |
| 1. Upload at least 2 video clips using the file uploader | |
| 2. Click the "Merge Videos" button | |
| 3. Wait for processing to complete | |
| 4. Download your smoothly merged video | |
| ### π― Features | |
| - β Seamless video concatenation without gaps | |
| - β Supports MP4, MOV, AVI formats | |
| - β Maintains original video quality | |
| - β Preserves audio tracks | |
| """ | |
| ) | |
| # Event handler for merge button | |
| merge_btn.click( | |
| fn=merge_videos_clips, | |
| inputs=video_input, | |
| outputs=[video_output, status_output], | |
| api_name="merge_videos", | |
| api_visibility="public" | |
| ) | |
| # Add footer with link | |
| gr.Markdown( | |
| """ | |
| <div style="text-align: center; margin-top: 30px; padding: 20px; background: #f5f5f5; border-radius: 10px;"> | |
| <p>Made with β€οΈ using Gradio & FFmpeg</p> | |
| <p>For more tools like this, visit <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a></p> | |
| </div> | |
| """ | |
| ) | |
| return demo | |
| # Create and launch the app | |
| if __name__ == "__main__": | |
| app = create_video_merger_app() | |
| app.launch( | |
| theme=gr.themes.Soft(), | |
| footer_links=[ | |
| {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"} | |
| ] | |
| ) |