video-to-gif / app.py
eienmojiki's picture
Update
5fe23d6
raw
history blame
3.19 kB
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)