使用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截图:

用python制作动画 python制作动画代码_opencv


确认you-get下载成功截图:

用python制作动画 python制作动画代码_python_02


(2)、将视频转换为GIF图的工具,我这里使用的是迅捷视频转换器。

迅捷视频转换器下载地址:https://www.xunjieshipin.com/video-converter

迅捷视频转换器使用界面截图:

用python制作动画 python制作动画代码_ide_03


(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 本地保存路径 视频链接

下载视频过程截图:

用python制作动画 python制作动画代码_用python制作动画_04


这样我们就成功将视频下载到本地

用python制作动画 python制作动画代码_ide_05

3、截取GIF图

接下来将下载后的视频进行GIF截取,我这里使用的是迅捷视频转换器。注意:截取视频时长尽量不能太长,否则在进行ASCII转换时会因为内存不够而报错,每次截取3s。

迅捷视频转换器截取GIF过程截图:

用python制作动画 python制作动画代码_用python制作动画_06


用python制作动画 python制作动画代码_用python制作动画_07


将截取出来的gif文件安装顺序1、2、3将gif命名。

用python制作动画 python制作动画代码_ide_08

4、将GIF转换为ASCII

使用ASCII Animator将截取的GIF每一帧图片转换为ASCII。注意:需要设置每100个像素宽度的字符数(我设置的是75)和输出类型选择动画ASCII(.gif)。

使用ASCII Animator截图。由于转换后图片占用内存太大,所以只用一个gif进行举例。

用python制作动画 python制作动画代码_图像处理_09


我们可以在输出路径里面找到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已经按照每一帧的顺序排列好了,后续处理时按照图片名称进行处理就行了。

重命名后的图片:

用python制作动画 python制作动画代码_用python制作动画_10

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的函数

转换后的图片:

用python制作动画 python制作动画代码_python_11

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')      # 调用图片转换为视频函数

最终的效果:

用python制作动画 python制作动画代码_opencv_12

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')      # 调用图片转换为视频函数