分享

MoviePy

 大傻子的文渊阁 2020-01-20

回到目录

创建和导出video clips

video 和 audio clips是moviepy中的核心的对象。这篇博文,我们会介绍不同的短clip,展示如何创建他们,以及如何将它们导出到文件中。关于修改和处理vedio clip的信息点这里。关于将clips合成点这里。关于在生成文件之前预览clip点这里

 接下来的代码是总结好的我们可以通过moviepy创建的一些基本的clips。

  1. # VIDEO CLIPS
  2. clip = VideoClip(make_frame, duration=4) # 自定义动画
  3. clip = VideoFileClip("my_vedio_file.mp4") # 文件格式还可以是avi、webm、 gif等
  4. clip = ImageSequenceClip(['imagefile.jpeg', ... ], fps=24)
  5. clip = ImageClip('my_picture.png') # 文件格式还可以是 png、tiff等
  6. clip = TextClip('Hello!', font="Amiri-Bold", fintsize=70, color='black')
  7. clip = ColorClip(size=(460, 380), color=[R,G,B])
  8. # AUDIO CLIPS
  9. clip = AudioFileClip("my_audio_file.mp3") #文件格式还可以是ogg、wav或者也可以是一个vedio
  10. clip = AudioArrayClip(numpy_array, fps=44100) # 一个numpy数组
  11. clip = AudioClip(make_frame, duration=3) # 使用一个方法make_frame(t)

video clip的分类

video clip好比是较长的video的积木块。从技术上讲,这些clip都是使用clip.get_frame(t)方法,在某一时间t获得的HxWx3 numpy 格式的剪辑帧的数组。主要有两种分类,首先是动画形式的clip(包括VideoClip、VideoFileClip);其次是非动画形式的clip,循环显示相同的画面(包括ImageClip、TextClip、ColorClip都在此列)。还有一种特殊的clip,那就是masks,它属于上面的类别,但是他输出的灰色帧表示在另一个剪辑中哪些部分是可见的还有哪些部分是不可见的。

VideoClip

VideoClip是movipy中其他所有的vedio clips的父类。如果你的需求仅仅是编辑视频文件,你是不会用到他的。事实上,一般只有在我们通过一些第三方的库生成动画的时候才会用到这个类。我们所需要做的,就是定义一个make_frame(t)函数,这个函数在一个给定的时刻t返回HxWx3形式的numpy数组。下面是一个使用第三方图像库Gizeh的例子:

  1. import gizeh
  2. import moviepy.editor as mpy
  3. def make_frame(t):
  4. surface = gizeh.Surface(128, 128) # 宽、高
  5. radius = W*(1+ (t*(2-t))**2 )/6 # 半径随时间变化
  6. circle = gizeh.circle(radius, xy=(64,64), fill(1,0,0))
  7. circle.draw(surface)
  8. return surface.getnpimage() # 返回一个8bit RGB数组
  9. clip = mpy.VideoClip(make_frame, duration=2)
  10. clip.write_gif('circle.gif', fps=15)

注意:在上面的make_frame函数并没有一个默认的帧率,所以我们必须给write_gif或者write_videofile提供一个fps(frames per second).

VideoFileClip

VideoFileClip就是从视频文件(大部分的视频格式都支持)或者GIF格式文件读取生成的clip。我们可以像下面这样去加载一个video。

  1. myclip = VideoFileClip("some_video.avi")
  2. myclip = VideoFileClip("some_animation,gif")

 每一个clip都有一个fps参数,当我们使用write_videofilewrite_gif等去将一个clip切分成小的clip去保存的时候,原有的clip的fps会默认地传递给新产生的clip。

  1. myclip = VideoFileClip("some_video.avi")
  2. print(myclip.fps) # 输出为30
  3. # 剪辑这个clip 的10s-25s,这会保存fps
  4. myclip2 = myclip.subclip(10, 25)
  5. myclip2.write_gif("test.gif") # 这个gif文件的fps=30

ImageSequenceClip

顾名思义,就是一系列图片创建的clip,你可以像下面这样调用:

clip = ImageSequenceClip(images_list, fps=25)

images_list可以有三种形式:

  1. 图片name list,将会按照list顺序播放
  2. 一个目录,这个目录下面的所有的图片都会被播放,按照字母或者数字的顺序播放
  3. 一系列frames (Numpy arrays),从其他的clip剪辑得到的,顺序是按照list顺序播放

当我们使用第一种或者第二种的时候,我们可以通过选择load_images=True来指定是否将所有的图片直接加载到RAM中。当然,这样的操作仅仅是在我们的图片不是很多,且每张图片都被使用超过1次的时候。

ImageClip

ImageClip就是一个一直播同一张图片的vedio clip,我们可以按照下面的方式创建:

  1. myclip = ImageClip("some_pic.jpeg")
  2. myclip = ImageClip(some_array) # 一个(高 × 宽 × 3)RGB numpy 数组
  3. myclip = some_video_clip.to_ImageClip(t = '01:00:00') # 在1h时刻的帧画面

TextClip

生成一个TextClip需要安装ImageMagick,并且和moviepy关联。

下面是一个创建TextClip的案例

myclip = TextClip('Hello!', font='Amiri-Bold')

注意:这里的font可以是任何安装在你的电脑上的font,如果照抄这里的代码,有可能会有问题,因为你的电脑上并没有这个样式。那么如何查看当前设备可用的样式呢?

TextClip.list('fonts') # 可以获得当前设备所有可用的fonts

ImageMagick对样式也有自己的指定的名称,比如:通常的normal Amiri被称为Amiri-Regular,Impact font被称为Impact-Normal

查找所有给定字体相关的所有字体,使用下面的方法:

TextClip.search('Amiri','fonts') # 查找所有包含Amiri的字体

注意:使用笔划或者(轮廓)的话,对于较小的字母来说不会有很好的结果。如果我们需要一个小的具有轮廓的TextClip,我们最好是先生成一个大点的文字,然后再将它缩小,这样的效果才会好。

myclip = TextClip('Hello!', fontsize=70, stroke_width=5).resize(height=15)

TextClip是有很多很多的可选项的,对齐、字距(字母距离)、笔划大小、背景、字体环绕等等。如果需要详细的信息,可以去官网参考手册去找或者等待后续中文文档更新。

Mask clips

mask clip是一种特殊的vide clip,当一个带有mask的video clip -- A和其他的video clips合成的时候,可以用来指示哪些像素是可见的,哪些是不显示的。在导出GIF或者PNG文件的时候,mask也可以用来定义透明度。

mask clip和普通的vedio clip最基本的不同在于:

  • 标准的clip的每一帧中的每一个像素是由3个色元即R-G-B组合成的,取值范围是0-255。(0-255, 0-255,0-255)
  • mask clip每个像素仅一个色元组件, 取值范围只有0-1。要么着一个像素可见,要么这个像素透明。

另一方面看,mask只有灰色的通道。

当我们创建或者加载一个带有mask 的clip的时候,我们会像下面这样声明:

  1. maskclip = VideoClip(makeframe, duration=4, ismask=True)
  2. maskclip = ImageClip('my_mask.jpeg', ismask=True)
  3. maskclip = VideoFileClip("myvideo.mp4", ismask=True)

将一个mask clip覆盖在一个和他同样尺寸的clip时使用

myclip.set_mask(mask_clip)

一些通过一个alpha 层来支持透明度的图片格式,比如PNG,moviepy中应该使用mask来对应:
 

  1. myclip = ImageClip("image.png", transparent=True) # 默认为True
  2. myclip.mask # 图片的alpha层

任何一个video clip都可以通过clip.to_mask()转换为一个mask,任何一个mask也可以通过my_mask_clip.to_RGB()转换为标准的RGB video clip.

导出video clips

video文件(.mp4 , .webm, .ogv...)

将一个clip写入一个文件

  1. myclip.write_videofile('movie.mp4') # 默认编码 'libx264', 24 fps
  2. myclip.write_videofile('movie.mp4', fps=15)
  3. myclip.write_videofile('movie.webm')
  4. myclip.write_videofile('movie.webm', audio=False) # 不使用音频

MoviePy对于大多数的扩展名都有默认的编解码,如果我们希望使用其他的编解码,或者我们不喜欢默认的编解码的话,我们可以通过codec='mpeg4'来使用自己指定的编解码。当我们导出为一个文件的时候,也有许多的可选项(比特率,是否将音频也导出,文件大小优化,使用处理器个数,等等)

有些时候,我们使用moviepy是无法获得一个clip的duration这个值的。然后,duration这个必须通过clip.set_duration()来指定:

  1. # 创建一个clip,显示一个花的图片5秒钟
  2. my_clip = Image('flower.jpeg') # 现在是无限时间,不停地循环
  3. my_clip.write_videofile('flower.mp4') # 这一步将会出错,因为没有指定duration
  4. my_clip.set_duration(5).write_videofile('flower.mp4') # 正确执行

GIF 动画

将vedio clip导出为一个gif动画

my_clip.write_gif('test.gif', fps=12)

注意:需要安转ImageMagick。此外,我们还可以通过添加选项program=‘ffmpeg‘来使用ffmpeg生成gif动画。使用ffmpeg生成gif动图,虽然要快一点,但是看起来效果可能会不太好,而且没有办法去优化。

导出图片

我们可以将某一帧导出为图片

  1. myclip.save_frame('frame.png') # 默认保存第一帧画面
  2. myclip.save_frame('frame.jpeg', t='01:00:00') # 保存1h时刻的帧画面

如果这些clip有mask的话,mask将会作为图片的alpha层被保存。除非我们使用withmask=False指定不保存mask。

 

一起交流,一起进步,群内提问答疑

QQ群:MoviePy中文 :819718037

回到目录

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多