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__": 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()