Spaces:
Runtime error
Runtime error
from moviepy.editor import * | |
from PIL import Image | |
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: | |
Image.Image: GIF image | |
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) | |
# Read the GIF from the temporary file | |
gif_image = Image.open(temp_file.name) | |
return gif_image | |
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.Gallery( | |
label="GIF", | |
format="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) |