Spaces:
Running
Running
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): | |
# 获取 GIF 图像中第一帧的 duration | |
duration = gif.info.get("duration", 100) | |
# 返回每一帧的 duration | |
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) | |
# 将修改后的帧作为新的 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__": | |
iface = 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"), | |
gr.Image(label="下载动图 Download GIF", type="filepath"), | |
], | |
title="请确保视频上传完整后再点击提交,若时长大于五秒可先在线裁剪<br>Please make sure the video is completely uploaded before clicking Submit, you can crop it online first if the video size is >5s", | |
allow_flagging="never", | |
) | |
iface.launch() | |