抖音最强python_装逼篇 | 抖音超火的九宫格视频是如何生成的,Python 告诉你答案...

1. 场景

如果你经常刷抖音和微信朋友圈,一定发现了最近九宫格短视频很火!

从朋友圈九宫格图片,到九宫格视频,相比传统的图片视频,前者似乎更有个性和逼格

除了传统的剪辑软件可以实现,是否有其他更加快捷方便的方式?比如:一键生成,批量生成?

废话不多说,本篇文章将大家使用 Python 一键生成九宫格短视频,优雅地帮你在朋友圈装一次逼!

2.准备

在开始实战之前,使用 pip 安装 2 个依赖,分别是:

1、视频处理依赖 moviepy

2、图片处理依赖 PIL

# 安装两个依赖

# 视频处理

pip3 install moviepy

# 图片处理依赖

pip3 install Pillow

3.实战一下

在实战之前,先准备一段原始视频素材

下面通过 6 个步骤,将原始视频转换为九宫格视频

1、新建处理文件夹

新建一个临时文件夹和一个视频输出文件夹

def mkdir_folder(file_path):

"""

创建一个文件夹,如果不存在就创建;否则不做处理

:param file_path:

:return:

"""

if os.path.exists(file_path):

return

os.mkdir(file_path)

# 新建临时文件夹和输出文件夹

mkdir_folder(self.path_temp)

mkdir_folder(self.path_output)

2、获取视频的音频文件及视频基础信息

首先,根据原始视频,使用 moviepy 构建一个 VideoFileClip 对象,从而获取到视频的宽、高、帧率、时长等信息

self.video_raw_clip = VideoFileClip(file_path)

# 宽、高

self.video_width, self.video_height = self.video_raw_clip.w, self.video_raw_clip.h

# 帧率

self.fps = self.video_raw_clip.fps

# 视频时长

self.during = self.video_raw_clip.duration

接着,从视频中提取 BGM 音频对象,并写入到文件中

def get_audio_from_video(video_raw_clip, output_path):

"""

从视频中提取音频

:param video_raw_clip: 视频Clip对象

:param output_path: 输出音频文件完整路径

:return:

"""

audio = video_raw_clip.audio

audio.write_audiofile(output_path)

return output_path

3、处理视频帧

我们使用原始视频 Clip 对象的 iter_frames() 方法,循环获取所有的视频帧图片

需要指出的是,为了保证后面视频合成的便捷性,这里对视频帧的文件名按顺序进行命令

i = 1

for frame in self.video_raw_clip.iter_frames():

image = Image.fromarray(frame)

# 视频帧图片保存的临时路径(完整路径)

frame_file_complete_path = self.path_temp + "%04d.jpg" % i

i += 1

视频每一帧都被裁剪成 9 张图片,我们可以显式指定图片之间的距离,然后计算出新画布的宽和高,最后绘制一个白底背景的图片

# 1、剪成9张图片,计算每张图片的宽、高

item_width = int(self.video_width / 3)

item_height = int(self.video_height / 3)

# 2、新的宽、高

item_width_new = self.video_width + self.item_space * 2

item_height_new = self.video_height + self.item_space * 2

# 3、重新建一个画布背景

new_image = Image.new(image.mode, (item_width_new, item_height_new),

color='white')

接着,获取每一块区域的坐标值,针对横向、纵向第 2、3 个图片区域加上间隔偏移,粘贴到上面新建的图片上即可

# 4、裁剪图片,然后粘贴到新的画布中去

# i:横向、j:纵向

for i in range(0, 3):

for j in range(0, 3):

# 裁剪区域

box = (j * item_width, i * item_height, (j + 1) * item_width, (i + 1) * item_height)

# 根据区域,裁剪图片

crop_image = image.crop(box)

# 横向、纵向第2块和第3块,要加上偏移距离

x = 0 if j == 0 else (item_width + self.item_space) * j

y = 0 if i == 0 else (item_height + self.item_space) * i

# 将9张图片,按照上面计算的坐标值,粘贴到背景中去

new_image.paste(crop_image, (int(x), int(y)))

# 保存图片到本地

new_image.save(frame_file_complete_path)

4、一篮子图片重新合成视频

把上一步生成的帧图片,按照原视频的帧率转为视频

需要注意的是,为了保证生成的视频不会错乱,最好对帧图片按照名称进行一次排序

def pics_to_video(pics_path, output_path, fps):

"""

图片转为视频

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('.jpg'), image_paths))

# 图片剪辑类

clip = ImageSequenceClip(image_paths,

fps=fps)

clip.write_videofile(output_path)

5、加入 BGM 背景音乐

将原始视频的音频文件设置到上一步生成的视频文件,然后写入一个新的文件中去

def video_with_audio(path_video_raw, path_bgm_raw, output):

"""

视频合成音频

:return:

"""

videoclip = VideoFileClip(path_video_raw)

audioclip = AudioFileClip(path_bgm_raw)

# 设置视频音频,并写入到文件中去

videoclip.set_audio(audioclip).write_videofile(output,

codec='libx264',

audio_codec='aac',

temp_audiofile='temp-audio.m4a',

remove_temp=True

)

6、删除临时文件

利用 shutil将上面视频处理的临时文件,包含帧图片、临时视频文件删除掉

def remove_folder(file_path):

"""

删除文件夹

:param file_path:

:return:

"""

shutil.rmtree(file_path)

# 删除临时文件

remove_folder(self.path_temp)

7、查看效果

4.最后

通过上面的一系列操作,我们实现了将一段视频处理成九宫格视频

我已经将文中全部源码,包含:生成九宫格视频和图片两套代码 上传到后台,关注公众号后回复「九宫格 」即可获得全部源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434248.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gin redis 链接不上_Redis 高并发问题,及解决方案!

(一)redis技术的使用:redis真的是一个很好的技术,它可以很好的在一定程度上解决网站一瞬间的并发量,例如商品抢购秒杀等活动。。。redis之所以能解决高并发的原因是它可以直接访问内存,而以往我们用的是数据…

任务管理平台_软件品质评测系统任务分发管理平台

testkuaibao|软件测试自学公众号1●为什么需要任务分发平台●在一个基本的评测系统中我们有了评测执行工具、评测数据、评测环境就能进行一次评测任务的执行,但现在是大数据时代,我们更多的需求是针对大量数据进行评测。比如在输入法评测中我们有10000个…

用mingw链接msvc生成的库时,无定义chkstk问题的解决

在用mingw链接msvc生成的库时常常产生这样的链接错误: undefined reference to _chkstk 这是因为chkstk is a stack-probing thing that MSVC generates whenallocating big stack frames), and that GCC has an equivalent inlibgcc (called _alloca).也…

[转载]Visual Studio 2010敏捷利剑:详解Scrum

Visual Studio 2010敏捷利剑:详解Scrum 【IT168 专稿】随着微软Visual Studio 2010 Ultimate Beta2版本的发布,除了它提供协同一致的ALM(应用程序生命周期)管理工具外,MSF for Agile Software Development过程框架从4.2升级到5.0,并且是以Scr…

网站收录工具(php导航自动收录源码)_10步把企业网站优化做到极致,SEO优化的核心知识...

对于企业网站优化,重要的就3点,内容原创、外链建设、内部优化,其它网站优化也会涉及到这些,但是企业站就变的简单的多了,下面10步让你把企业网站优化做到极致。第一步:首先域就是让搜索引擎选择我们网站的主…

“无法解析外部符号 __security_cookie”问题解决

编译VC工程时出现了标题所示问题,资料搜索一下,在微软网站找到答案了,解决方法如下:1)选择“项目”-》“属性”-》“C/C”-》“代码生成”-》“缓冲区安全检查”,设为“否”2)选择“项目”-》“…

mysql not is null_转!!mysql 字段 is not null 和 字段 !=null

今天在查询数据时,查到包含一条某个时间startTime(该字段默认为null ) 为null的记录,想把它过滤,加了 startTime! null 的条件,结果记录都没了,应该用条件 is not null。转自:https://segmentfault.com/a/1…

WindowManager.LayoutParams类

WindowManager.LayoutParams 是 WindowManager 接口的嵌套类;继承于 ViewGroup.LayoutParams 。 它的内容十分丰富。其实WindowManager.java的主要内容就是由这个类定义构成。下面来分析一下这个类:定义public static class WindowManager.LayoutParam…

myeclipse mysql连接_MyEclipse连接Mysql数据库的方法(一)

准备工作:MyEclipse使用的是2013版,mysql Ver 14.14 Distrib 5.6.281.jar包的下载(jdbc驱动)我下载的是:mysql-connector-java-5.1.7-bin.jar2.打开MyEclipse---->选择window---->选择open perspecctive---->myeclipse Database Exp…

Qt+VS2005(配置步骤)

在VS2005中安装了QT4.4.3,由于目前的QT版本已经很高了,很难找到QT4.3.2之类的版本了,还有另外一个原因:QT在VS2005上的插件的版本也很高了。因此,很多QT与VS2005结合的文章,现在都不太适用了;不…

c malloc 头文件_C/C++笔试题:主要考察C/C++语言基础概念算法及编程,附参考答案...

1.编写my_strcpy函数,实现与库函数strcpy类似的功能,不能使用任何库函数;答:char *strcpy(char *strDest, const char *strSrc){if ( strDest NULL || strSrc NULL)return NULL ;if ( strDest strSrc)returnstrDest ;char *tem…

置换加密算法

1 #include "stdio.h"2 #include "stdlib.h"3 #define column 34 typedef char DataType;5 6 7 /************************************************************************/8 /* 置换加密算法。9 content为需要加密的内容,index为置换的密匙…

SQLlite数据导入到mySQL_如何批量导入数据到Sqlite数据库

做android和ios开发的一般都用Sqlite数据库,有的时候数据需要批量导入,那么如何导入呢?在这里,介绍2种方法供大家参考。一、用sqlite命令以windows系统为例,linux下命令是一样的。1.安装sqlite工具包首先要安装有sqlit…

c/c++ 运行库

11.2 C/C运行库 11.2.1 C语言运行库 任何一个C程序,它的背后都有一套庞大的代码来进行支撑,以使得该程序能够正常运行。这套代码至少包括入口函数,及其所依赖的函数所构成的函数集合。当然,它还理应包括各种标准库函数的实现。…

下面哪个字段是http请求中必须具备的_理解HTTP协议-HTTP协议详解总结

一、HTTP协议的演进HTTP(HyperText Transfer Protocol)协议是基于TCP的应用层协议,它不关心数据传输的细节,主要是用来规定客户端和服务端的数据传输格式,最初是用来向客户端传输HTML页面的内容。默认端口是80。1、HTTP 0.9版本 1991年这个版…

查看一个结构体成员的方法

find / *.h -name|xargs grep 结构体名 这个方法并不是很凑效。。。 万能的gdb 法: int main(void){type var;return 0;}gcc -g a.cgdb a.outb mainrp varset print pretty onp varp main::v转载于:https://www.cnblogs.com/mathzzz/archive/2012/09/24/2700796.htm…

ad电阻原理图_负载电阻的原理及应用

在开始主题之前,我们需要了解的是:负载电阻是什么?将其拆分:负载和电阻;负载,顾名思义,是指连接在电路中的电源两端的电子元件。主要功能就是将电能转换成其他形式的能,以实现能量的…

终于搞定android驱动USB摄像头了!

多亏了stackoverflow看到的一篇帖子,其中有几句关键的话,然后顺藤摸瓜解决了问题。帖子大意:讨论的前提是你的USB摄像头是UVC兼容的(如今大部分摄像头兼容)默认Android不提供访问外部摄像头的API,所以你要考…

mysql怎么回复.from的数据库_mysql怎么回复.from的数据库

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航,为用户…

python dataframe 新列_Python第二十四课:Pandas库(四)

Python第二十四课:Pandas库(四)点击上方“蓝字”,关注我们.不知不觉,我们已经跨越了千难万险,从零开始,一步步揭开了Python神秘的面纱。学到至今,回过头,才晓得自己在不知不觉已经学会了如此多的…