10万+的短视频被批量生产了,Python表示不服

论坛 期权论坛 期权     
简说Python   2019-7-13 17:57   4474   0

点击“简说Python”,选择“置顶/星标公众号”
福利干货,第一时间送达!


本文授权转载自AirPython,禁二次转载

阅读文本大概需要 10 分钟。


1
目 标 场 景

做过自媒体的朋友应该都知道,「GIF动画视频」有段时间在各大自媒体平台很受欢迎。

前期有些自媒体大 V 靠搬运一些搞笑、好玩的 GIF,然后利用剪辑软件合成一段视频,再添加一个节奏感强的 BGM 后,上传各大自媒体平台后,能带来不错的阅读量和收益。




本篇文章的目的是带大家利用 Python 实现制作 GIF 动画视频,批量制作短视频这一骚操作。

2
准 备 工 作

首先,对视频和背景音乐的剪辑,这里用到了「moviepy」库,通过 pip3 安装到虚拟环境中。

# moviepy 用于视频剪辑和背景音乐的合成、剪辑pip3 install moviepy

另外,项目中需要利用「PIL」库来分析、获取 GIF 动画中的所有帧图片。

# 将GIF图片转为帧,需要对GIF进行分析pip3 install ffmpeg

编写脚本之前,我们需要提前准备一些 GIF 动画素材。当然,你也可以去爬取一些搞笑、好玩的 GIF 动画。

另外再准备一段 BGM 作为视频的背景音乐。


3
编  写  脚  本

第一步,我们需要把每一个 GIF 动画转为一段视频。

由于 GIF 动画已经是一段包含很多帧的视频了,没法直接通过 moviepy 库转为一段普通视频。

所以,这里需要对 GIF 动画进行分析,将动画转为「静态帧图片」。

def get_gif_frames(gif_path, temp_path):    """    获取一段GIf图片下的所有静态帧    get_gif_frames('./../gifs/3.gif', './../gif_temp/')    :return:    """    # 分析gif图片    mode = analyseImage(gif_path)['mode']    im = Image.open(gif_path)    i = 1    p = im.getpalette()    last_frame = im.convert('RGBA')    try:        while True:            # print("saving %s (%s) frame %d, %s %s" % (gif_path, mode, i, im.size, im.tile))            '''            If the GIF uses local colour tables, each frame will have its own palette.            If not, we need to apply the global palette to the new frame.            '''            if not im.getpalette():                im.putpalette(p)            new_frame = Image.new('RGBA', im.size)            '''            Is this file a "partial"-mode GIF where frames update a region of a different size to the entire image?            If so, we need to construct the new frame by pasting it on top of the preceding frames.            '''            if mode == 'partial':                new_frame.paste(last_frame)            new_frame.paste(im, (0, 0), im.convert('RGBA'))            new_frame.save(temp_path + '/%s-%d.png' % (''.join(os.path.basename(gif_path).split('.')[:-1]), i), 'PNG')            i += 1            last_frame = new_frame            im.seek(im.tell() + 1)    except EOFError:        # print('产生EOFError!!!')        pass

另外,我们下载的 GIF 动画的静态帧图片分辨率大概率是不一致的,所以对图片批量修改分辨率「修改分辨率」变的很有必要。

这里将所有图片的分辨率统一修改为 720*1080,在转换的过程中,如果存在空白部分,就使用黑色进行填充。

def resize_image(target_image_path, target_size):    """    调整图片大小,缺失的部分用黑色填充    :param target_image_path: 图片路径    :param target_size: 分辨率大小    :return:    """    image = Image.open(target_image_path)    iw, ih = image.size  # 原始图像的尺寸    w, h = target_size  # 目标图像的尺寸    scale = min(w / iw, h / ih)  # 转换的最小比例    # 保证长或宽,至少一个符合目标图像的尺寸    nw = int(iw * scale)    nh = int(ih * scale)    image = image.resize((nw, nh), Image.BICUBIC)  # 缩小图像    # image.show()    new_image = Image.new('RGB', target_size, (0, 0, 0, 0))  # 生成黑色图像    # // 为整数除法,计算图像的位置    new_image.paste(image, ((w - nw) // 2, (h - nh) // 2))  # 将图像填充为中间图像,两侧为灰色的样式    # new_image.show()    # 覆盖原图片    new_image.save(target_image_path)


然后,将统一分辨率后的静态帧图片转换为一段普通视频。

在转换为视频之前,我们需要提供一个「合理的转换帧率」来保证视频播放的流畅性。由于最后需要将多段视频合成为一段视频,这里默认指定帧率为 10帧/s。

GIF 动画原始的帧率、播放时长等动画文件属性值可以利用「imgpy」获取到。

def get_gif_info(gif_path):    """    获取gif文件的详细信息    每一个gif的帧率不一样,有的10fps    :param gif_path:    :return:    """    with Img(fp=gif_path) as im:        # 1.有多少帧        frame_count = im.frame_count        # 2.图片信息        # {'version': b'GIF89a', 'background': 31, 'duration': 70, 'extension': (b'NETSCAPE2.0', 795), 'loop': 0}        duration_pre = im.info.get('duration')        # 根据规律,除以7位实际的播放时长        duration = duration_pre / 7        # 6.color palette        # print(im.mode_desc)        # print((frame_count, duration))        # 返回帧率和时长        return (frame_count / duration), duration

最后,我们利用 moviepy 库中的「ImageSequenceClip」类将这些图片写入到一个视频文件中。

def pics_to_video(pics_path, output_path, fps, duration):    """    图片转为视频    pics_to_video('./../gif_temp/', './../video_temp/temp1.mp4', 20)    :param pics_path:    :param output_path:    :return:    """    image_paths = list(map(lambda x: pics_path + x, os.listdir(pics_path)))    # 注意:这里必须进行一次排序,保证所有帧的顺序是一致    image_paths = sort_strings_with_emb_numbers(image_paths)    # 过滤掉非图片    image_paths = list(filter(lambda image_path: image_path.endswith('.png'), image_paths))    # 图片剪辑类    clip = ImageSequenceClip(image_paths,                             fps=fps)    # 写成视频之前,需要把gif都转成同一个分辨率    clip.write_videofile(output_path)


循环上面的操作,就可以将所有的 GIF 动画转换为一个普通视频文件。

第二步是将所有的视频文件进行剪辑,写入一个单独的文件中。利用 moviepy 库下面的 「 VideoFileClip 」可以非常快捷方便地完成这一操作。

def compound_a_video(self, videos_path):        """        合成一个视频        :param videos_output:视频集合的完整目录        :return:        """        # 定义一个数组        L = []        for video_path in videos_path:            # 载入视频            video = VideoFileClip(video_path)            # 添加到数组            L.append(video)        # 拼接视频        final_clip = concatenate_videoclips(L)        # 生成目标视频文件        final_clip.to_videofile(self.video_output_temp, fps=self.fps, remove_temp=False)

最后一步是往视频中添加背景音乐。

首先是通过 AudioFileClip 和 VideoFlieClip 获取到视频文件和音频文件的播放时长,对播放时长较长的文件进行截取处理。

# 1.音频文件audioclip = AudioFileClip(self.bgm_path)# 2.视频文件 videoclip = VideoFileClip(self.video_output_temp)# 3.获取视频和音频的时长video_time = videoclip.durationaudio_time = audioclip.durationprint('视频时长:%f,音频时长:%f' % (video_time, audio_time))# 4.对视频或者音频进行裁剪if video_time > audio_time:      # 视频时长>音频时长,对视频进行截取      ideoclip_new = videoclip.subclip(0, audio_time)      audioclip_new = audioclipelse:      # 音频时长>视频时长,对音频进行截取      videoclip_new = videoclip      audioclip_new = audioclip.subclip(0, video_time)

然后把音频文件通过 set_audio() 添加到视频操作类中,最后重新写入到一个新的视频文件当中。

# 5.视频中加入音频video_with_new_audio = videoclip_new.set_audio(audioclip_new)# 6.写入到新的视频文件中video_with_new_audio.write_videofile("mp4_with_audio.mp4",                                             codec='libx264',                                             audio_codec='aac',                                             temp_audiofile='temp-audio.m4a',                                             remove_temp=True                                             )

4
结 果 结 论

以上的脚本会对指定文件夹的的 GIF 动画文件分别生成一段普通视频,然后把所有的视频合成一段视频,然后再添加一段 BGM 背景音乐,最后写入到一个新的视频文件中,如此,就完成了制作一个 GIF 视频的操作。

当然,本文只是提供一个思路,让 Python 爬取一些有趣好玩的 GIF 动画进而批量做成视频,上传各大自媒体平台,应该也能获取到不错的阅读量。

我已经将全部源码上传到后台上,关注公众号后回复「 10万 」即可获得。

如果你觉得文章还不错,请大家点赞分享下。你的肯定是我最大的鼓励和支持。
仔细阅读下面四篇文章,2小时快速掌握Python基础知识要点。
完整Python基础知识要点
Python小知识 | 这些技能你不会?(一)
Python小知识 | 这些技能你不会?(二)
Python小知识 | 这些技能你不会?(三)
Python小知识 | 这些技能你不会?(四)
我是老表,欢迎转发分享本文。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:20
帖子:4
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP