python import gradio as gr import cv2 import random import os import tempfile import numpy as np import yt_dlp def get_random_frame(youtube_url): """ Downloads a video from YouTube and returns a random frame. """ if not youtube_url: raise gr.Error("Please provide a valid YouTube URL.") # Create a temporary directory for the download temp_dir = tempfile.mkdtemp() try: # Configure yt-dlp options ydl_opts = { 'format': 'best[ext=mp4]/best', # Prefer MP4 for better OpenCV compatibility 'outtmpl': os.path.join(temp_dir, '%(id)s.%(ext)s'), 'quiet': True, 'no_warnings': True, } # Download video info first to check validity with yt_dlp.YoutubeDL(ydl_opts) as ydl: try: info = ydl.extract_info(youtube_url, download=False) if 'duration' not in info: raise gr.Error("Could not retrieve video duration. The video might be private or a live stream.") except Exception as e: raise gr.Error(f"Invalid YouTube URL or Video unavailable: {str(e)}") # Download the video ydl.params['quiet'] = False # Show progress info = ydl.extract_info(youtube_url, download=True) video_path = ydl.prepare_filename(info) # Open the video file using OpenCV cap = cv2.VideoCapture(video_path) if not cap.isOpened(): raise gr.Error("Could not open the video file after downloading.") # Get total number of frames total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if total_frames == 0: raise gr.Error("Video has no frames.") # Select a random frame index random_frame_idx = random.randint(0, total_frames - 1) # Set the frame position cap.set(cv2.CAP_PROP_POS_FRAMES, random_frame_idx) # Read the frame ret, frame = cap.read() cap.release() if not ret: raise gr.Error("Failed to read the selected frame.") # Convert BGR (OpenCV default) to RGB (Gradio/Image default) frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) return frame_rgb except gr.Error: raise except Exception as e: raise gr.Error(f"An unexpected error occurred: {str(e)}") finally: # Clean up temporary files import shutil if os.path.exists(temp_dir): shutil.rmtree(temp_dir, ignore_errors=True) # Gradio 6 Application with gr.Blocks() as demo: # Header with required link gr.HTML("""

YouTube Frame Randomizer

Enter a YouTube URL to extract a random frame from the video.

Built with anycoder
""") with gr.Row(): with gr.Column(scale=1): url_input = gr.Textbox( label="YouTube URL", placeholder="https://www.youtube.com/watch?v=...", lines=1 ) randomize_btn = gr.Button("Get Random Frame", variant="primary", size="lg") gr.Markdown(""" ### How it works: 1. Paste a YouTube link. 2. Click the button. 3. The app downloads the video (this may take a moment). 4. A random timestamp is selected and the frame is displayed. """) with gr.Column(scale=2): output_image = gr.Image( label="Random Frame", type="numpy", interactive=False ) # Event listener randomize_btn.click( fn=get_random_frame, inputs=url_input, outputs=output_image, api_visibility="public" ) # Launch the app with Gradio 6 syntax # Note: theme, css, and footer_links are now parameters of demo.launch() demo.launch( theme=gr.themes.Soft( primary_hue="blue", secondary_hue="cyan", ), footer_links=[ {"label": "Gradio", "url": "https://gradio.app"}, {"label": "Hugging Face", "url": "https://huggingface.co"}, {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"} ] )