深圳幻海软件技术有限公司 欢迎您!

用Python处理MP4与GIF格式互转,简单到爆!

2023-02-28

上次公众号写文章的时候,遇到个问题,公众号插入视频文件太繁琐,一个很小的视频,作为视频传上去平台还要审核,播放的时候也没gif来的直接。于是想着找个工具将mp4转换成gif。网上搜一下,在线的工具好多,但是各种套路,有些要点广告,有些要先扫二维码。还是国外的网站好,没那么多套路。我想Python肯定

上次公众号写文章的时候,遇到个问题,公众号插入视频文件太繁琐,一个很小的视频,作为视频传上去平台还要审核,播放的时候也没gif来的直接。

于是想着找个工具将mp4转换成gif。网上搜一下,在线的工具好多,但是各种套路,有些要点广告,有些要先扫二维码。还是国外的网站好,没那么多套路。

我想Python肯定也可以处理这种问题,毕竟万能的Python除了不会生孩子,什么都能做。这样后面我把它做成一个在线工具,方便自己也顺便可以给其他人使用。

mp4转gif的原理其实很简单,就是将mp4文件的帧读出来,然后合并成一张gif图。用cv2和PIL这两个库就可以轻松搞定

import glob

import cv2
from PIL import Image


def convert_mp4_to_jpgs(input_file):
    # 先将mp4文件的所有帧读取出保存为图片
    video_capture = cv2.VideoCapture(input_file)
    still_reading, image = video_capture.read()
    frame_count = 0
    while still_reading:
        cv2.imwrite(f"output/frame_{frame_count:03d}.jpg", image)
        # read next image
        still_reading, image = video_capture.read()
        frame_count += 1


def convert_images_to_gif(output_file):
    # 读取目录下图片,用Pillow模块的Image和所有图片合并
    # 成一张gif
    images = glob.glob(f"output/*.jpg")
    images.sort()
    frames = [Image.open(image) for image in images]
    frame_one = frames[0]
    frame_one.save(output_file, format="GIF", append_images=frames[1:],
                   save_all=True, duration=40, loop=0)


def convert_mp4_to_gif(input_file, output_file):
    convert_mp4_to_jpgs(input_file)
    convert_images_to_gif(output_file)


if __name__ == "__main__":
    convert_mp4_to_gif("demo.mp4", "output.gif")
  • 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.

执行完成后,发现gif文件大小暴增:

可以尝试通过减少帧的数量来优化gif的大小,比如这个视频一共有60帧,我们只取30帧,大小就会减半;

frame_one.save(output_file, format="GIF", append_images=[f for i, f in enumerate(frames[1:]) if i % 2 == 0],
                   save_all=True, duration=40, loop=0)
  • 1.
  • 2.

实现逻辑是用enumerate函数过滤取偶数张图片来合成,最小大小从3.9M压缩到2M。

写完这个代码后,发现还有另一个牛逼的库moviepy,2行代码就可以搞定;

def mp4_to_gif2():
    clip = VideoFileClip("demo.mp4")
    clip.write_gif("output2.gif")
  • 1.
  • 2.
  • 3.

moviepy把实现细节已经封装非常简约了,然后提供了一大堆参数可以让开发者自行配置。但使用moviepy转的文件有9M,我相信可以用参数来优化调整。

你不得不承认Python生态就是库多,各种各样的轮子都有,没有做不到的,只有你找不到的。

当然,你也可以将gif转回成MP4格式,比如你看到一些搞笑的gif将它转换成mp4放到短视频平台,说不定就火了。

def convert_gif_to_mp4():
    import moviepy.editor as mp
    clip = mp.VideoFileClip("demo.gif")
    clip.write_videofile("output.mp4")
  • 1.
  • 2.
  • 3.
  • 4.

最后,如果你稍微懂点运营,把它做成工具,挂到网上,又是一个吸粉的神器,岂不美哉。