Python代码解决视频转GIF动图,FFmpeg方案使用了moviepy、imageio和PIL等库。解决动图太大如何压缩、动图只能单次循环、帧率大小调整、转换太慢以及转换后卡顿等问题。底部效果图

问题描述

       最近准备写些文章,遇到要将 mp4 视频转换为 gif 格式图片 。最开始想的是找些免费的在线转换的工具试试,但是用了不久发现白嫖一两次之后要么需要注册要么需要收费。那有没有永久免费方式呢,也有使用一些工具软件比如ps等等也能做到,但为了转个 gif 图片还要安装一个工具软件,不免太过麻烦。既然如此,那就用代码解决吧。这里记录下在使用python解决的时候遇到的一些问题。方便后续查看。主要问题如下

1、使用moviepy库进行视频转换为gif图片问题如下:

  • 动态图片帧率非常低、一卡一卡的。
  • 转换后格式过大,不符合主流博客网站的上传限制,知乎是1M以内csdn5M以内;

2、之后我就想办法看如何压缩gif图片,这里使用的是imageio库和PIL库进行的压缩。遇到问题如下:

  • 百度现成的代码报错,有计算帧率的参数报错KeyError: 'duration';
  • 压缩之后的动态图片还是不理想占用的内存空间比较大。
  • 图片上传博客网站后只进行了一次循环,无法重复循环。

3、当然还有就是不使用imageio库进行压缩方案,只是用PIL库进行的压缩。

  • 这个方案呢,可以将大小压缩,但是帧率问题不可调节,会有一卡一卡的问题,但是可以解决重复循环的问题。

解决方案

流程如下:

1、首先,既然我们要解决问题,首先我们要这些用到的python库使用起来才行。安装命令如下:

(1)、安装 moviepy 库

pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple

(2)、安装 imageio 库

pip install imageio -i https://pypi.tuna.tsinghua.edu.cn/simple

(3)、安装 PIL 库

pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple

2、 接下来,库安装完成了,我们就要写代码进行转换和压缩操作才行。

(1)、使用 moviepy 库进行视频转换为 gif 代码
# -*- coding:utf-8 -*-

'''
实现功能
    使用 moviepy 库,视频转gif动图处理
'''
import moviepy.editor as mpy

# 视频文件的本地路径
content = mpy.VideoFileClip("E:\\录像\\01-录制\\05-球体相册.mp4")
# 剪辑0分0秒到0分5秒的片段。resize为修改清晰度、0.5参数代表缩小0.5倍
# c1 = content.subclip((0, 0), (0, 5)).resize((1416,732))
c1 = content.subclip((0, 0), (0, 5)).resize(0.5)
# 将片段保存为gif图到python的指定路径,fps指定帧率,抽帧技术主要解决转换后内存过大的问题
c1.write_gif("E:\\录像\\02-已转\\05-球体相册.gif",fps=15)

# 提示作用
print('转换完成!!!')
(2)、使用 imageio 库和 PIL 库进行的压缩代码
# -*- coding:utf-8 -*-

'''
实现功能
    使用ImageIo 和PIL库,对gif动图进行压缩处理
'''

import imageio
from PIL import Image, ImageSequence

# 设置压缩尺寸,这里设置压缩尺寸为500
rp = 500

img_list = []

# 读取原gif动图
img = Image.open("E:\\录像\\02-已转\\05-球体相册.gif")

# 对原动图进行压缩,并存入img_list
for i in ImageSequence.Iterator(img):
    i = i.convert('RGBA') # 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。设置不同的参数效果不同、内存大小不同
    if max(i.size[0], i.size[1]) > rp:
        i.thumbnail((rp, rp))
    img_list.append(i)

# 计算帧的频率
# durt = (img.info)['duration'] / 1000 #这句已经更改了
durt = 1/24 * 1000

# 读取img_list合成新的gif,loop=0是设置只循环一次的问题
imageio.mimsave('E:\\录像\\03-已压缩\\05-球体相册.gif', img_list, duration=durt,loop=0)


print('压缩完成!!!')

(3)、只是用 PIL 库进行的压缩代码
# -*- coding:utf-8 -*-


'''
实现功能
    只使用PIL库,对gif动图进行压缩处理
'''

import imageio
from PIL import Image, ImageSequence

# 设置压缩尺寸,这里设置压缩尺寸为500
rp = 400

img_list = []

# 读取原gif动图
# img = Image.open("E:\\录像\\02-已转\\04-发光球体.gif")
img = Image.open("E:\\录像\\02-已转\\05-球体相册.gif")

# 对原动图进行压缩,并存入img_list
for i in ImageSequence.Iterator(img):
    i = i.convert('RGBA') # 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。
    if max(i.size[0], i.size[1]) > rp:
        i.thumbnail((rp, rp))
    img_list.append(i)

# 让不循环的gif循环起来,这是一步非常重要的代码,主要解决csdn不循环测试
img_list[0].save("E:\\录像\\out.gif", save_all=True, append_images=img_list[1:])


print('压缩完成!!!')

问题总结

  • 问题描述中的大部分问题都在注释中有标注。其中你比如说刚开转换的动图一卡一卡的,主要解决方案就是imageio库进行动图的帧重组,并进行计算好帧率,这个库在重设帧率这一块有些代码使用的从动图属性中获取这个参数,但是有时候要压缩的动图没有这个参数 (出现这个情况是因为可以使用这个库对多组图片实现轮播效果的动图,该步骤下的动图是一般是有这个属性的),这时你就可以自己设定一个固定的参数, 1/24 * 1000 这个值是以每秒24帧计算出来的。
  • 还有比如转换格式过大,在视频转动图的代码中,我们可以设置想要的分辨率,分辨率越低,内存占用越低,或者设置原始分辨率的0.5倍、还有设定像fps=15参数可以抽帧降低内存空间。当然用imageio库PIL库进行图片的压缩,这其中有一个明显效果的是,i.convert('RGBA')该方法的参数可以设置不同的颜色格式参数。不同参数压缩的大小也不同,实践得出的是RGBA要比RGB更省内存空间;还有就是调整分辨率大小也可以改变压缩大小。至于动图只有单次循环的效果的话,解决方法就是在imageio.mimsave方法中添加loop=0的参数,虽然我查看api解释说0代表循环往复1则代表单次循环,默认的是0,但是不写的话却是单次循环,所以还是写一下这个参数,因为时间关系就不深究了。代码如有错误,欢迎指正交流,本文只是记录一下问题总结,没有非常严谨的考究,所以细节不一定很到位,也欢迎大家评论交流。

效果如下

在这里插入图片描述

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

博扬java张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值