moviepy底层使用ffmpeg读取和导出视频以及音频文件。它使用ImageMagic对视频插入文字以及生成GIF(可选)。对于不同的媒体文件的处理是通过python高效的数值计算库numpy来完成的。一些特效处理等使用到了python的图像处理库比如PIL,scikit-images以及科学计算库scipy等。
关于moviepy的一些基础概念。moviepy的核心概念是clips,可以是AudioCLips 和 VideoClips 。这些clips可以被修改(剪切,降低播放速度,调整亮度等)或者和其他的clips混合到一起组成新的clips。然后这些clips可以通过pygame或者Ipython(jupyter notebook)预览,或者导出为videos文件或者GIF。VideoClips可以通过一个视频文件,图像文件或者文字以及动画来创建,这些VideoClips还可以有音轨(audio track)即 AudioCLips以及mask(这种一种特殊的VideoClips,当其他的clips混合在一起的时候,这个mask决定哪些clips可以显示出来)。具体操作下面我们主要以代码的形式展示。
Sample Code – clip_array的使用
#!/usr/bin/env python3
# encoding: utf-8
“””
@version: 0.1
@author: lyrichu
@license: Apache Licence
@contact: 919987476@qq.com
@site: http://www.github.com/Lyrichu
@file: clip_array.py
@time: 2018/05/19 14:38
@description:
stacking is done by clips_array
“””
from moviepy.editor import VideoFileClip,clips_array,vfx
clip1 = VideoFileClip(“sources/xq.mp4”).margin(10) # 增加10piexl的边框
clip2 = clip1.fx(vfx.mirror_x) # 水平翻转
clip3 = clip1.fx(vfx.mirror_y) # 垂直翻转
# downsize to 60% size
clip4 = clip1.resize(0.6)
# stack all videos together like arrays
final_clip = clips_array([[clip1,clip2],
[clip3,clip4]
]
)
final_clip.resize(width=480).write_videofile(“sources/stack.mp4”)
Sample Code – CompositeVideoClips
#!/usr/bin/env python3
# encoding: utf-8
“””
@version: 0.1
@author: lyrichu
@license: Apache Licence
@contact: 919987476@qq.com
@site: http://www.github.com/Lyrichu
@file: CompositeVideoClips.py
@time: 2018/05/19 14:51
@description:
CompositeVideoClip class,play sevral videos together
“””
from moviepy.editor import VideoFileClip,CompositeVideoClip
clip1 = VideoFileClip(“sources/xq.mp4”)
clip2 = VideoFileClip(“sources/girl.mp4”).set_position(“left”).set_start(3).crossfadein(1)
clip3 = VideoFileClip(“sources/dogs.mp4”).set_position(“right”).set_start(6).crossfadein(2)
final_clip = CompositeVideoClip([clip1,clip2,clip3])
final_clip.write_videofile(“sources/composite.mp4”)
上面的代码还是将三个clip组合到一起形成一个新的clip,只不过这次对每一个clip都做了一些操作,比如上面的 set_start 方法就是设置视频开始播放的时间, set_position 是设置clip的位置, crossfadein 是设置连接视频渐变的时间,还有很多其他的方法可以具体参考文档,使用这些方法,我们就可以将视频剪辑的更加丰富多彩,符合我们的要求。
Sample Code – Compositing audio clips
#!/usr/bin/env python3
# encoding: utf-8
“””
@version: 0.1
@author: lyrichu
@license: Apache Licence
@contact: 919987476@qq.com
@site: http://www.github.com/Lyrichu
@file: set_methods.py
@time: 2018/05/19 15:16
@description:
set_xxx methods
“””
from moviepy.editor import VideoFileClip,AudioFileClip,vfx
clip = VideoFileClip(“sources/xq.mp4”)
# create a audio clip
aclip = AudioFileClip(“sources/22.mp3”).subclip(50,55)
aclip.write_audiofile(“sources/22_clip.mp3”)
# 设置音频
clip = clip.set_audio(aclip) # 注意一定要赋值,否则不会有任何改变
# 1s 以后开始
clip = clip.set_start(1)
# 设置持续时间为3s
clip = clip.set_duration(3)
clip.write_videofile(“sources/set_xq.mp4”)
# 设置宽度,设置颜色变为更暗,速度变为原来的两倍
clip1 = clip.fx(vfx.resize,width=360).fx(vfx.colorx,0.5).fx(vfx.speedx,2)
clip1.write_videofile(“sources/xq1.mp4”)
上面的代码逻辑不难理解。首先构建了一个 VideoClip 对象,然后使用 subclip 方法截取音频50-55秒,然后保存为新的音频文件。接着对视频clip对象采用 set_audio 方法设置audio track,这里需要注意的是clip的很多方法都是采用”流式”操作,即 clip.set_xxx 放回的仍然是一个clip,因此可以连续使用set_xxx方法,所以需要注意使用set_xxx之后需要将结果保存到一个新的对象,否则设置是无效的。最后需要注意 clip.fx 是通用的设置clip的方法,具体用法可以查看文档。
Sample code – Create custom effects
#!/usr/bin/env python3
# encoding: utf-8
“””
@version: 0.1
@author: lyrichu
@license: Apache Licence
@contact: 919987476@qq.com
@site: http://www.github.com/Lyrichu
@file: change_attribute.py
@time: 2018/05/19 15:43
@description:
change video attribute
“””
from moviepy.editor import VideoFileClip
from math import sin
clip = VideoFileClip(“sources/xq.mp4”)
# make video 3 times faster
clip1 = clip.fl_time(lambda x:3*x).set_duration(3)
# 按照正弦timeline 播放,视频播放会非常抖动
clip2 = clip.fl_time(lambda x:1+sin(x)).set_duration(3)
clip1.write_videofile(“sources/xq2.mp4”)
clip2.write_videofile(“sources/xq3.mp4”)
def invert_green_blue(image):
”’
将图片的green channel 和 blue channel 转换
:param image: input image
:return: new image
”’
return image[:,:,[0,2,1]]
clip3 = clip.fl_image(image_func=invert_green_blue)
clip3.write_videofile(“sources/xq4.mp4”)
def scroll(get_frame, t):
“””
This function returns a ‘region’ of the current frame.
The position of this region depends on the time.
“””
frame = get_frame(t)
frame_region = frame[int(20*t):int(20*t)+100,:] # 得到部分区域
return frame_region
clip4 = clip.fl(fun=scroll)
clip4.write_videofile(“sources/xq5.mp4”)
上面的代码展示了如何使用clip的 fl 和 fl_time 以及 fl_image 方法来生成一些特效。
fl_time方法接收一个函数,对video的时间轴进行修改,该函数接收的是视频的时间属性t,所以上面的clip.fl_time(lambda x:3*x) 会让视频的播放速度加快3倍,而
clip.fl_time(lambda x:1+sin(x)) 则让视频按照正弦的timeline播放,视频会有些抖动。 fl_image 对视频每一帧图像进行修改,其接收的也是一个函数作为参数,该函数的参数为image(ndarray),所以上面的 invert_green_blue 函数做的工作就是将图片的green channel 和 blue channel 转换。而 fl函数是一个更一般的函数,其也是接收一个函数作为参数,该函数的参数有两个,一个是 get_frame 函数,一个是当前帧的时间t,函数需要返回一个image(ndarray),而不难看出上面的scroll 函数就是让视频随着时间的变化在水平方向向下移(展示图片的一部分,高度始终不变),在竖直方向上不改变。
Sample Code –
make videos from list of images
#!/usr/bin/env python3
# encoding: utf-8
“””
@version: 0.1
@author: lyrichu
@license: Apache Licence
@contact: 919987476@qq.com
@site: http://www.github.com/Lyrichu
@file: ImageSequenceClip.py
@time: 2018/05/19 17:15
@description:
create videos or gif from sequences of images
“””
import numpy as np
from glob import glob
from PIL import Image
from scipy.misc import imresize,imsave
imgs = glob(“sources/images/*.jpg”)
def preprocess_imgs(imgs,size = (900,1200)):
”’
把所有的图片resize成相同大小
:param imgs: list of images names
:param size: resized size
:return: None
”’
for img in imgs:
m = np.array(Image.open(img))
m = imresize(m,size)
imsave(img,m)
preprocess_imgs(imgs)
from moviepy.editor import ImageSequenceClip
clip = ImageSequenceClip(imgs,fps=2)
# export gif
clip.write_gif(“sources/xq_new.gif”)
不难发现,使用 ImageSequenceClip更为简单一点,但是要求所有的图片必须具有相同的大小,上面的 preprocess_imgs函数就是将所有的图片resize成相同的大小。
** 如果此篇文章有帮助到你,欢迎点击下方/页面上任意广告,支持我们,谢谢!