使用python实现代码动画视频
前言
最近看到一个将视频转换为由代码组成的视频,所以想自己写一个。
功能:使用python实现将动画转换为有字符组成的视频。
实现方法分为如下几步:
1、将视频从网站上面下载下来
2、将视频截取为GIF,把截取的GIF进行ASCII字符转换
3、将转换好的字符gif根据每一帧的顺序进行重命名,然后排序
4、将排序后的每一帧gif图片转换为jpg图片
5、将字符图片合成视频
实现步骤
1、准备阶段
想要将视频制作出来,我们想要用到如下几个工具:
(1)、将视频下载下来的工具,我这里使用的是you-get。
you-get安装方法:
下载的命名:
pip install you-get
下载you-get截图:
确认you-get下载成功截图:
(2)、将视频转换为GIF图的工具,我这里使用的是迅捷视频转换器。
迅捷视频转换器下载地址:https://www.xunjieshipin.com/video-converter
迅捷视频转换器使用界面截图:
(3)、将GIF转换为字符的工具,我这里使用的是ASCII Animator
ASCII Animator下载地址:http://www.qqpr.com/
(4)、在文件中需要使用到的库:cv2、os、opecv-python
下载需要使用的命名:
pip install cv2 # 用于处理图像的库
pip install os # 用于处理文件的库
pip install opencv-python # 用于处理图像的库
2、下载视频
通过you-get将视频下载到本地,我这里使用的是《如果历史是一群喵第六季》的op。
《如果历史是一群喵第六季》视频链接:
https://www.bilibili.com/bangumi/play/ep399825 下载视频使用的命令:
you-get -o 本地保存路径 视频链接
下载视频过程截图:
这样我们就成功将视频下载到本地
3、截取GIF图
接下来将下载后的视频进行GIF截取,我这里使用的是迅捷视频转换器。注意:截取视频时长尽量不能太长,否则在进行ASCII转换时会因为内存不够而报错,每次截取3s。
迅捷视频转换器截取GIF过程截图:
将截取出来的gif文件安装顺序1、2、3将gif命名。
4、将GIF转换为ASCII
使用ASCII Animator将截取的GIF每一帧图片转换为ASCII。注意:需要设置每100个像素宽度的字符数(我设置的是75)和输出类型选择动画ASCII(.gif)。
使用ASCII Animator截图。由于转换后图片占用内存太大,所以只用一个gif进行举例。
我们可以在输出路径里面找到gif每一帧转换的ASCII的gif,将gif复制到python项目下material/img文件夹中,以便后续的处理(在复制文件时按照自己的需求确定复制路径)。
5、gif文件重命名
思路:使用os.listdir(path)读取路径下所有的文件名称,然后通过for遍历每一个文件、使用os.rename(src, dst)对文件重命名。
实现代码:
# 导入包
import os
import cv2
from PIL import Image
# 定义重命名的函数
def rename_gif(gif_path):
"""
定义重命名的函数
:param gif_path: gif图片存储的路径
:return:
"""
# 使用os.listdir(path)读取路径下所有的文件名称
file_list = os.listdir(gif_path)
# 使用len()获取文件夹下文件的数量
n = len(file_list)
# 使用for循环遍历文件夹下的所有文件
for i in range(n):
s = str(file_list[i]) # 获取第i个文件的名称
src = gif_path + s # 重命名前名称
dst = gif_path + s[8: 10] + s[-4:] # 重命名后名称
os.rename(src, dst) # 对文件重命名
rename_gif('./material/img/') # 调用重命名函数
gif重命名后,所有的gif已经按照每一帧的顺序排列好了,后续处理时按照图片名称进行处理就行了。
重命名后的图片:
6、将gif转换为jpg图片
按照帧顺序排列的gif转换为jpg图片。注意:不能直接将文件后缀名该为jpg,那样文件格式还是没有变,使用cv2读取时会为空。
思路:
1、使用os.listdir(path)读取路径下所有的文件名称
2、使用Image.open(path)读取gif格式的图片
3、使用im.convert(‘RGB’)将图片格式转换为jpg格式
4、使用frame.save()将转换后的图片写回文件夹。
实现的代码:
# 导入包
import os
import cv2
from PIL import Image
# 定义用于迭代图片数据的函数
def iter_frames(im):
try:
i = 0
while 1:
im.seek(i)
imframe = im.copy()
if i == 0:
palette = imframe.getpalette()
else:
imframe.putpalette(palette)
yield imframe
i += 1
except EOFError:
pass
# 定义将gif图片转换为jpg图片的函数
def gif2jpg(gif_path, jpg_path):
"""
定义将gif图片转换为jpg图片的函数
:param gif_path: 存储gif图片的路径
:param jpg_path: 存储jpg图片的路径
:return:
"""
# 获取所有gif图片名称
file_list = os.listdir(gif_path)
# 将图片排序,以名称字符串的数字进行排列
file_list.sort(key=lambda x: int(x[: -4]))
# 使用for循环读取所有的gif图片
for img in file_list:
# 判断是否为gif格式的图片
if img[-4:] == '.gif':
im = Image.open(gif_path + img) # 打开图片
im = im.convert('RGB') # 转换格式
# 当存储jpg图片的路径不存在时创建路径
if not os.path.exists(jpg_path):
os.makedirs(jpg_path)
# 进行图片的转换
for i, frame in enumerate(iter_frames(im)):
frame.save(jpg_path + img[0: -4] + '.jpg', **frame.info)
gif2jpg('./material/img/', './img/') # 调用将gif转换为jpg的函数
转换后的图片:
7、将图片合成视频
思路:
1、使用os.listdir(path)读取路径下所有的文件名称
2、使用cv2.VideoWriter_fourcc(‘m’, ‘p’, ‘4’, ‘v’)确定视频格式为.mp4
3、使用Image.open(path)打开一张图片,用于确定合成视频的宽度和高度。
4、使用cv2.VideoWriter(video_path, fourcc, fps, im.size)创建视频,video_path确定视频存储路径,fourcc确定视频格式,fps确定视频每一秒帧数,im.size确定视频宽度和高度。
5、使用cv2.imread(path)读取需要插入视频的图片
6、使用video_writer.write(frame)将图片写入视频中。
7、使用video_writer.release()将视频释放。
实现过程的代码:
# 导入包
import os
import cv2
from PIL import Image
# 定义图片转换为视频的函数
def jpg2video(jpg_path, video_path):
"""
定义图片转换为视频的函数
:param jpg_path: jpg图片所在文件夹
:param video_path: 视频存储路径
:return:
"""
# 使用os.listdir(path)获取所有jpg图片名称
jpg_list = os.listdir(jpg_path)
# 将图片排序,以名称字符串的数字进行排列
jpg_list.sort(key=lambda x: int(x[: -4]))
fps = 21 # 定义每一秒的帧数
# 视频格式为mp4格式
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
im = Image.open(jpg_path + jpg_list[0]) # 打开第一张图片
# 设置写入视频的要求,参数(写入的路径, 格式, 每一秒的帧数,视频宽高)
video_writer = cv2.VideoWriter(video_path, fourcc, fps, im.size)
print(jpg_list)
# 使用for循环将图片写入视频中
for jpg_i in jpg_list:
frame = cv2.imread(jpg_path + jpg_i) # 使用cv2导入图片
print('开始将' + jpg_i + '加入视频')
video_writer.write(frame) # 将图片加入视频
video_writer.release() # 释放video_writer
jpg2video('./img/', './video.mp4') # 调用图片转换为视频函数
最终的效果:
8、完整的代码
"""
功能:将图片合成一个视频
"""
# 导入包
import os
import cv2
from PIL import Image
# 第一步将gif图像重命名
# 定义重命名的函数
def rename_gif(gif_path):
"""
定义重命名的函数
:param gif_path: gif图片存储的路径
:return:
"""
# 使用os.listdir(path)读取路径下所有的文件名称
file_list = os.listdir(gif_path)
# 使用len()获取文件夹下文件的数量
n = len(file_list)
# 使用for循环遍历文件夹下的所有文件
for i in range(n):
s = str(file_list[i]) # 获取第i个文件的名称
src = gif_path + s # 重命名前
dst = gif_path + s[8: 10] + s[-4:] # 重命名后
os.rename(src, dst) # 对文件重命名
# 第二步将gif图片转换为jpg图片
# 定义用于迭代图片数据的函数
def iter_frames(im):
try:
i = 0
while 1:
im.seek(i)
imframe = im.copy()
if i == 0:
palette = imframe.getpalette()
else:
imframe.putpalette(palette)
yield imframe
i += 1
except EOFError:
pass
# 定义将gif图片转换为jpg图片的函数
def gif2jpg(gif_path, jpg_path):
"""
定义将gif图片转换为jpg图片的函数
:param gif_path: 存储gif图片的路径
:param jpg_path: 存储jpg图片的路径
:return:
"""
# 获取所有gif图片名称
file_list = os.listdir(gif_path)
# 将图片排序,以名称字符串的数字进行排列
file_list.sort(key=lambda x: int(x[: -4]))
# 使用for循环读取所有的gif图片
for img in file_list:
# 判断是否为gif格式的图片
if img[-4:] == '.gif':
im = Image.open(gif_path + img) # 打开图片
im = im.convert('RGB') # 转换格式
# 当存储jpg图片的路径不存在时创建路径
if not os.path.exists(jpg_path):
os.makedirs(jpg_path)
# 进行图片的转换
for i, frame in enumerate(iter_frames(im)):
frame.save(jpg_path + img[0: -4] + '.jpg', **frame.info)
# 第三步将图片转换为视频
# 定义图片转换为视频的函数
def jpg2video(jpg_path, video_path):
"""
定义图片转换为视频的函数
:param jpg_path: jpg图片所在文件夹
:param video_path: 视频存储路径
:return:
"""
# 使用os.listdir(path)获取所有jpg图片名称
jpg_list = os.listdir(jpg_path)
# 将图片排序,以名称字符串的数字进行排列
jpg_list.sort(key=lambda x: int(x[: -4]))
fps = 21 # 定义每一秒的帧数
# 视频格式为mp4格式
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
im = Image.open(jpg_path + jpg_list[0]) # 打开第一张图片
# 设置写入视频的要求,参数(写入的路径, 格式, 每一秒的帧数,视频宽高)
video_writer = cv2.VideoWriter(video_path, fourcc, fps, im.size)
print(jpg_list)
# 使用for循环将图片写入视频中
for jpg_i in jpg_list:
frame = cv2.imread(jpg_path + jpg_i) # 使用cv2导入图片
print('开始将' + jpg_i + '加入视频')
video_writer.write(frame) # 将图片加入视频
video_writer.release() # 释放video_writer
# rename_gif('./material/img/') # 调用重命名函数
#gif2jpg('./material/img/', './img/') # 调用将gif转换为jpg的函数
jpg2video('./img/', './video.mp4') # 调用图片转换为视频函数