from PIL import Image from moviepy.editor import * import tempfile import gradio as gr def get_video_detail(video_path): info = VideoFileClip(video_path) return 0, info.duration, info.fps, max(info.size) def convert_video_to_gif( input: str, start: float = 0, end: float | None = None, fps: int | None = None, quality: int | None = None ): """ Convert video to GIF image Args: input (str): Path to video file. start (float, optional): Start time in seconds. Defaults to 0. end (float, optional): End time in seconds. Defaults to None. fps (int, optional): Frames per second. Defaults to None (max fps). quality (int, optional): Image quality. Defaults to None (max quality). Returns: str: Path to the GIF file Examples: >>> convert_video_to_gif("input.mp4") """ # Get video input & info clip = VideoFileClip(input) max_fps = clip.fps max_duration = clip.duration max_res = max(clip.size) if end is None: end = max_duration if end > max_duration: raise ValueError(f"End time {end} is longer than video duration {max_duration}") if fps > max_fps: raise ValueError(f"FPS {fps} is greater than video FPS {max_fps}") if quality is None: quality = max_res if quality > max_res: raise ValueError( f"Quality must be less than video max resolution {max_res}, but is {quality}" ) clip = clip.subclip(start, end) target_height = quality aspect_ratio = clip.size[0] / clip.size[1] target_width = int(target_height * aspect_ratio) clip = clip.resize((target_width, target_height)) clip = clip.set_fps(fps) # Create a temporary file with tempfile.NamedTemporaryFile(suffix=".gif") as temp_file: # Write the GIF to the temporary file clip.write_gif(temp_file.name) # Return the path to the GIF file gif_file_path = temp_file.name return gif_file_path # Gradio code... with gr.Blocks( theme = gr.themes.Base( font = [gr.themes.GoogleFont("Outfit"), "Arial", "sans-serif"], ), delete_cache=(86400, 86400) ) as demo: input = gr.Video(interactive=True) save = gr.Text(label="Cache path", interactive=False) with gr.Row(): start = gr.Number( label="Start", info="Video start time in seconds", interactive=True ) end = gr.Number( label="End", info="Video end time in seconds", interactive=True ) with gr.Row(): fps = gr.Number( label="FPS", info="Frame per second", interactive=True ) quality = gr.Number( label="Quality", info="Nax resolution available", interactive=True ) run_btn = gr.Button("Convert") output = gr.File( label="GIF" ) input.change( fn=lambda x: x, inputs=input, outputs=save, queue=False, api_name=False ).then( fn=get_video_detail, inputs=save, outputs=[start, end, fps, quality], queue=False, api_name=False ) run_btn.click( fn=convert_video_to_gif, inputs=[save, start, end, fps, quality], outputs=output, api_name="convert" ) if __name__ == "__main__": demo.queue(max_size=20).launch(show_error=True)