File size: 2,602 Bytes
66a8b39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4377031
66a8b39
 
 
 
 
 
 
 
 
 
 
 
 
383acb1
66a8b39
 
4377031
66a8b39
4377031
66a8b39
 
 
 
 
 
 
4377031
 
66a8b39
4377031
383acb1
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import os
import math
import shutil
import gradio as gr
from PIL import Image, ImageSequence
from moviepy.editor import VideoFileClip

TMP_DIR = "./__pycache__"


def clean_cache(tmp_dir=TMP_DIR):
    if os.path.exists(tmp_dir):
        shutil.rmtree(tmp_dir)

    os.mkdir(tmp_dir)
    return f"{tmp_dir}/input.gif"


def get_frame_duration(gif: Image):
    duration = gif.info.get("duration", 100)
    return [
        frame.info.get("duration", duration) for frame in ImageSequence.Iterator(gif)
    ]


def resize_gif(
    target_width: int,
    target_height: int,
    input_path=f"{TMP_DIR}/input.gif",
    output_path=f"{TMP_DIR}/output.gif",
):
    # Open the GIF image
    gif = Image.open(input_path)
    # Create a list to hold the modified frames
    modified_frames = []
    # Loop through each frame of the GIF
    for frame in ImageSequence.Iterator(gif):
        # Resize the frame
        resized_frame = frame.resize((target_width, target_height), Image.LANCZOS)
        # Append the resized frame to the list
        modified_frames.append(resized_frame)

    frame_durations = get_frame_duration(gif)
    modified_frames[0].save(
        output_path,
        format="GIF",
        append_images=modified_frames[1:],
        save_all=True,
        duration=frame_durations,
        loop=0,
    )

    return output_path


def infer(video_path: str, speed: float):
    target_w = 640
    gif_path = clean_cache()
    try:
        with VideoFileClip(video_path, audio_fps=16000) as clip:
            if clip.duration > 5:
                raise ValueError("The uploaded video is too long")

            # clip.write_gif(gif_path, fps=12, progress_bar=True)
            clip.speedx(speed).to_gif(gif_path, fps=12)
            w, h = clip.size

        target_h = math.ceil(target_w * h / w)
        return os.path.basename(video_path), resize_gif(target_w, target_h)

    except Exception as e:
        return f"{e}", None


if __name__ == "__main__":
    gr.Interface(
        fn=infer,
        inputs=[
            gr.Video(label="Upload video"),
            gr.Slider(
                label="Speed",
                minimum=0.5,
                maximum=2.0,
                step=0.25,
                value=1.0,
            ),
        ],
        outputs=[
            gr.Textbox(label="Filename", show_copy_button=True),
            gr.Image(label="Download GIF", type="filepath"),
        ],
        title="Please make sure the video is completely uploaded before clicking Submit, you can crop it online first if the video size is >5s",
        flagging_mode="never",
    ).launch()