MoviePy是一个用于视频编辑的Python模块,它可被用于一些基本操作(如剪切、拼接、插入标题)、视频合成(即非线性编辑)、视频处理和创建高级特效。它可对大多数常见视频格式进行读写,包括GIF。

示例如下(IPython Notebook环境) 

moviepy库的SubtitlesClip_ide

用户手册

下载与安装

安装

pip安装方式:如果你安装了pip,只需要在终端输入如下命令(若没有安装ez_setup,则会自动安装)

(sudo) pip install moviepy

如果你既没有安装setuptools也没有安装ez_setup,那么上述命令就会运行失败。在这种情况下,你需要在安装前运行:

(sudo) pip install ez_setep

手动安装方式:从 PyPI 或者 Github (开发版本)上下载源码。将所有文件解压到同一文件夹,打开终端并输入

(sudo) python setup.py install

MoviePy依赖 Numpy 、 imageio 、 Decorator 和 tqdm ,他们将在安装MoviePy的同时自动安装。运行平台为Windows/Mac/Linux,并使用Python2.7以上的版本和Python3。如果在安装MoviePy及其依赖包的过程中存在问题,请提供反馈。

MoviePy依赖FFMPEG软件对视频进行读写。不用对此担心,在你第一次使用MoviePy的时候,FFMPEG将会自动由ImageIO下载和安装(不过需要花一些时间)。如果你想使用FFMPEG的特定版本,你可以设置FFMPEG_BINARY环境变量。详见moviepy/config_defaults.py

可选但有用的依赖包

ImageMagick 只有在你想要添加文字时需要用到。它可作为一个后端用在GIF上,但如果不安装ImageMagick,你也可以用MoviePy处理GIF。

一旦你安装了ImageMagick,它会被MoviePy自动检测到,除了Windows环境! Windows用户在手动安装MoviePy之前,应在moviepy/config_defaults.py文件中指定ImageMagick binary的路径,并叫做convert。看起来应该像是这样:

IMAGEMAGICK_BINARY = "C:\\Program Files\\ImageMagick_VERSION\\convert.exe"

你也可以设置IMAGEMAGICK_BINARY环境变量,详见moviepy/config_defaults.py

PyGame 在视频和声音预览中会使用到。不过如果你想要在服务器上使用MoviePy,但的确需要手动进行高级的视频编辑,Pygame就没什么用处啦。

对于高级的图片处理,你至少需要一个以下所列的包。例如使用clip.resize方法,就至少需要安装Scipy、PIL、Pillow或OpenCV其中一个。

  • Python图片库(PIL)或它的分支 Pillow 更好。
  • Scipy (用于追踪、分割等)可在没有安装PIL和OpenCV的情况下用于调整视频剪辑的大小。
  • Scikit Image 可能被用于高级的图片处理。
  • OpenCV 2.4.6 或更高版本(在cv2包中提供)可能被用于高级的图片处理。

如果你使用linux,这些软件都一定在你的仓库中。

MoviePy入门

此页面为你讲解如何使用MoviePy进行编辑。想了解更多的话,详阅作品展示脚本示例

快速准备

这个章节说明了使用MoviePy的场合以及工作原理。

我需要MoviePy吗?

这些是你想用Python编辑视频的理由:

  • 你需要用很复杂的方法来处理或组成大量的视频;
  • 你想在web服务器(Django、Flask等)自动生成视频或GIF动图;
  • 你想自动完成无聊的任务,如插入标题、追踪对象、剪切场景、制作结尾的演职人员表、字幕等等;
  • 你想用代码实现视频编辑软件所不能达到的视频效果;
  • 你想将从别的Python库里(如Matplotlib、Mayavi、Gizeh、scikit-images等)生成的图片制作成动画。

但在以下情况中,MoviePy并非最好的选择:

  • 你只需要对视频进行逐帧分析(如人脸识别或其他有趣的东西),使用MoviePy和别的库可以联合完成。但是事实上,仅使用 imageio、 OpenCV 或者SimpleCV这些专用库即可达到要求。
  • 你只需要视频文件转换,或者将一系列图片文件转换成视频。在这种情况下,直接调用ffmpeg(或avconv、mencoder等)将比使用MoviePy更快速、更有效率地使用内存。
优势与局限性

MoviePy在以下方面表现出色:

  • 易于上手:一行即可完成一项基本操作。对于新手来说,代码易学易懂。
  • 灵活:视频和音频的每一帧都尽在掌握,创作属于自己的特效就像Python一样简单。
  • 便携:代码使用十分常见的软件(Numpy和FFMPEG),而且可以在几乎所有版本的Python和几乎所有的机器上运行。

局限性:MoviePy目前还无法对流媒体进行处理(从摄像头或者远程设备获取视频),并且MoviePy并不是被设计成用来对电影的连续帧进行处理(例如视频去抖,你需要寻找另外的软件)。如果你同时处理大量视频,音频以及图片序列(数量大于100)可能会出现内存问题,但是这个问题会在将来的版本当中进行修复。

代码示例

在典型的MoviePy脚本是这样的:加载视频或音频、修改、将他们连接在一起并最后生成一个新视频文件。作为一个示例,我们加载一个关于我上个假期的视频,降低音量,在前十秒添加标题在视频的中央,然后写入一个文件:

# Import everything needed to edit video clips
from moviepy.editor import *

# Load myHolidays.mp4 and select the subclip 00:00:50 - 00:00:60
clip = VideoFileClip("myHolidays.mp4").subclip(50,60)

# Reduce the audio volume (volume x 0.8)
clip = clip.volumex(0.8)

# Generate a text clip. You can customize the font, color, etc.
txt_clip = TextClip("My Holidays 2013",fontsize=70,color='white')

# Say that you want it to appear 10s at the center of the screen
txt_clip = txt_clip.set_pos('center').set_duration(10)

# Overlay the text clip on the first video clip
video = CompositeVideoClip([clip, txt_clip])

# Write the result to a file (many options available !)
video.write_videofile("myHolidays_edited.webm")
MoviePy的工作原理

MoviePy使用ffmpeg软件来读取和导出视频和音频文件。也使用(可选)ImageMagick来生成文字和制作GIF文件。不同媒体的处理依靠Python的快速的数学库Numpy。高级效果和增强功能使用一些Python的图片处理库(PIL,Scikit-image,scipy等)。

moviepy库的SubtitlesClip_Python_02

基本概念

在MoviePy中,核心对象是剪辑,可以使用AudioClipsVideoClips来处理。剪辑可被修改(剪切、降低速度、变暗等)或与其他剪辑混合组成新剪辑。剪辑可被预览(使用PyGame或IPython Notebook),也可生成文件(如MP4文件、GIF文件、MP3文件等)。以VideoClips为例,它可以由一个视频文件、一张图片、一段文字或者一段卡通动画而来。它可以包含音频轨道(即AudioClip)和一个遮罩(一种特殊的VideoClip),用于表明当两个剪辑混合时,哪一部分的画面被隐藏)。详见生成与导出视频剪辑混合剪辑

你可使用MoviePy的很多效果对一个剪辑进行修改(如clip.resize(width="360")clip.subclip(t1,t2)clip.fx(vfx.black_white)或使用用户自行实现的效果。MoviePy提供许多函数(如clip.fl、clip.fx等),可以用简单的几行代码实现你自己的效果。详见视频转换与效果。

你还可以在moviepy.video.tools找到一些高级的效果来对视频中的对象进行追踪、画简单的形状和颜色渐变(对于遮罩来说很有用)、生成字幕和结束时的演职人员表等。参见高级工具中的详细描述。

最后,尽管MoviePy没有生动的用户界面,它也有许多方法来预览剪辑,使你能够调试脚本,从而确保你的视频在高质量的同时一切正常。详见如果更有效率地使用MoviePy。

混合剪辑

视频合成,也称为非线性编辑,事实上就是把许多视频剪辑放在一起,变成一个新剪辑。这个视频就是一个很好的例子,告诉你可以用MoviePy做些什么样的合成:

原视频链接已失效

在开始之前要注意,一般来说视频剪辑都会带有音轨和遮罩,他们也同样是剪辑。当你将这些剪辑组合在一起时,音轨和剪辑的遮罩将会自动生成音轨和最终剪辑的遮罩。所以在大多数情况下,你并不必为混合音频和遮罩担心。

堆叠和连接剪辑

有两种简单的方法能将剪辑放在一起:一是连接(使它们变成一个更长的剪辑,一个接一个播放),二是堆起来(使他们并排组成画面更大的剪辑)。

使用concatenate_videoclips函数进行连接操作。

from moviepy.editor import VideoFileClip, concatenate_videoclips
clip1 = VideoFileClip("myvideo.mp4")
clip2 = VideoFileClip("myvideo2.mp4").subclip(50,60)
clip3 = VideoFileClip("myvideo3.mp4")
final_clip = concatenate_videoclips([clip1,clip2,clip3])
final_clip.write_videofile("my_concatenation.mp4")

final_clip是一个剪辑,使clip 1、2和3一个接一个播放。注意,剪辑不一定必须要相同尺寸。如果各剪辑尺寸不同,那么它们将被居中播放,而画面大小足够包含最大的剪辑,而且你可以选择一种颜色来填充边界部分。你还有许多其它可选项(详见函数的文档),例如你可以通过transition=my_clip选项来在剪辑之间加一个过场。

使用clip_array函数对剪辑进行堆叠操作。

from moviepy.editor import VideoFileClip, clips_array, vfx
clip1 = VideoFileClip("myvideo.mp4").margin(10) # add 10px contour
clip2 = clip1.fx( vfx.mirror_x)
clip3 = clip1.fx( vfx.mirror_y)
clip4 = clip1.resize(0.60) # downsize 60%
final_clip = clips_array([[clip1, clip2],
                          [clip3, clip4]])
final_clip.resize(width=480).write_videofile("my_stack.mp4")

从而你可以获得一个看起来是这样的剪辑:

moviepy库的SubtitlesClip_ide_03

合成视频剪辑

CompositeVideoClip类提供了一个非常灵活的方法来合成剪辑,但它比concatenate_videoclipsclips_array更复杂一些。

video = CompositeVideoClip([clip1,clip2,clip3])

当前video播放clip1clip2clip1的上层,而clip3clip1clip2的上层。举例来说,如果clip2clip3clip1有同样的尺寸,那么只有在顶层的clip3能在视频中可见,除非clip3clip2被遮罩隐藏了一部分。注意,在默认情况下,合成的视频和第一个剪辑的尺寸相同(因为它通常是一个背景)。但是有时,你想让你的剪辑在更大的合成视频里浮动,所以你需要像这样特意修改最终合成视频的尺寸:

video = CompositeVideoClip([clip1,clip2,clip3], size=(720,460))
起始和终止时间

在一个合成剪辑中,所有的剪辑开始的时间都被clip.start属性所指定。你可以像这样设定开始时间:

clip1 = clip1.set_start(5) # start after 5 seconds

例如你的剪辑看起来会是这样:

video = CompositeVideoClip([clip1, # starts at t=0
                            clip2.set_start(5), # start at t=5s
                            clip3.set_start(9)]) # start at t=9s

在上面的例子中,clip2可能先于clip1的结束时间开始。在这种情况下,你可以给clip2添加一个1秒钟的淡入效果:

video = CompositeVideoClip([clip1, # starts at t=0
                            clip2.set_start(5).crossfadein(1),
                            clip3.set_start(9).crossfadein(1.5)])
剪辑的定位

如果clip2clip3都比clip1小,你可以决定他们出现在视频中的位置。在这里,我们指定了剪辑左上角像素的坐标:

video = CompositeVideoClip([clip1,
                            clip2.set_pos((45,150)),
                            clip3.set_pos((90,100))])

有很多方法可以指定位置:

clip2.set_pos((45,150)) # x=45, y=150 , in pixels

clip2.set_pos("center") # automatically centered

# clip2 is horizontally centered, and at the top of the picture
clip2.set_pos(("center","top"))

# clip2 is vertically centered, at the left of the picture
clip2.set_pos(("left","center"))

# clip2 is at 40% of the width, 70% of the height of the screen:
clip2.set_pos((0.4,0.7), relative=True)

# clip2's position is horizontally centered, and moving down !
clip2.set_pos(lambda t: ('center', 50+t) )

当指定坐标的时候请记住,y坐标的0位置在图片的最上方:

moviepy库的SubtitlesClip_ci_04

合成音频剪辑

当你将视频剪辑混合在一起时,MoviePy将会把它们各自的音轨自动合成为最终剪辑的音轨,所以不用担心需要自行合成音轨啦。 如果你想使用许多音频源来自定义音轨,可以使用CompositeAudioClipconcatenate_audioclips来进行混音。

from moviepy.editor import *
# ... make some audio clips aclip1, aclip2, aclip3
concat = concatenate_audioclips([aclip1, aclip2, aclip3])
compo = CompositeAudioClip([aclip1.volumex(1.2),
                            aclip2.set_start(5), # start at t=5s
                            aclip3.set_start(9)])

如何更有效率地使用MoviePy

这一节总结了一些技巧和诀窍,可以帮助你充分利用全球范围内已知的经验来使用MoviePy。

使用IPython Notebook是使用MoviePy的最好方法。它使得预览剪辑变得很容易(在此节中会介绍到),有自动完成功能,而且可以显示库里不同方法的文档。

我应该使用moviepy.editor吗?

这篇文档里的大部分示例使用了moviepy.editor子模块,但是这个子模块并不适用于所有需求。简单来说,如果你使用MoviePy手动编辑视频,那就建议使用此子模块;如果你在更大的库、更大的项目或web服务器上使用MoviePy,最好避免使用它,转而加载你需要的函数。

moviepy.editor模块能以以下三种方式加载:

from moviepy.editor import * # imports everything, quick and dirty
import moviepy.editor as mpy # Clean. Then use mpy.VideoClip, etc.
from moviepy.editor import VideoFileClip # just import what you need

通过这些代码,moviepy.editor模块会做许多幕后工作:它将获取MoviePy里最常见的类、函数和子包,初始化一个PyGame会话(在PyGame已安装的情况下)使得视频剪辑可被预览,并执行一些快捷方式,例如对剪辑添加resize变换。以这种方式,你可以使用clip.resize(width=240)来替代更长的clip.fx(resize,width=240)写法。总之,moviepy.editor提供了你所需要的播放和剪辑功能,但是需要一些时间来加载(大约1秒)。所以如果你所需要的一或两个效果在别的库里,直接将你所需要的导入是更好的选择,就像这样:

from moviepy.video.io.VideoFileClip import VideoFileClip
from moviepy.video.fx.resize import resize
预览剪辑的多种方法

当你使用MoviePy通过不断尝试来编辑视频或试图达到某种效果的时候,生成每个示例的视频的时间可能会很长。这一节提供了一些提高速度的小窍门。

clip.save_frame

很多时候,只需要视频中的一帧,即可说明你是否正确操作。你可以像这样保存剪辑中的一帧:

my_clip.save_frame("frame.jpeg") # saves the first frame
my_clip.save_frame("frame.png", t=2) # saves the frame a t=2s
clip.show and clip.preview

使用clip.showclip.preview方法,使剪辑在Pygame的窗口中可视。这两个方法是预览的最快方法,当剪辑在生成和播放的同事,它们还可以获得坐标和像素的颜色。这些方法需要PyGame的支持,以及moviepy.editor模块的使用。

clip.show模块可以在没有写入文件的情况下预览剪辑里的一帧。如下是如何在PyGame窗口中显示一帧:

my_clip.show() # shows the first frame of the clip
my_clip.show(10.5) # shows the frame of the clip at t=10.5s
my_clip.show(10.5, interactive = True)

最后一行(有interactive=True的一行)以一种交互的形式显示一帧:如果你单击这一帧的任意一处,它将输出位置和像素的颜色。当你结束查看时,按下esc键。

如下代码可预览剪辑:

my_clip.preview() # preview with default fps=15
my_clip.preview(fps=25)
my_clip.preview(fps=15, audio=False) # don't generate/play the audio.
my_audio_clip.preview(fps=22000)

如果你单击正在预览的视频剪辑中某帧的任意一处,将输出单击的位置和像素的颜色。按esc结束预览。

注意,如果剪辑很复杂而且你的电脑速度也不够快,剪辑的预览速度将会比真实速度慢。在这种情况下,你可以尝试降低帧率(例如将为10),或者用clip.resize降低剪辑的尺寸。

ipython_display

使用IPython Notebook来显示剪辑很实用,尤其是你不想用clip.show()clip.preview()时。看起来就像这样:

moviepy库的SubtitlesClip_Python_05

通过使用ipython_display,你可以从文件或直接从片段里潜入视频、图片或声音:

ipython_display(my_video_clip) # embeds a video
ipython_display(my_imageclip) # embeds an image
ipython_display(my_audio_clip) # embeds a sound

ipython_display("my_picture.jpeg") # embeds an image
ipython_display("my_video.mp4") # embeds a video
ipython_display("my_sound.mp3") # embeds a sound

只有当ipython_display在一个笔记本单元的最后一行才有效。你也可以调用ipython_display作为一个剪辑方法:

my_video_clip.ipython_display()

如果对所呈现的视频的帧率有所要求,你可以在ipython_display里指定fps=25

如果你只需要播放一个视频剪辑在时间t的快照,可以这样写:

my_video_clip.ipython_display(t=15) # will display a snapshot at t=15s

你还可以提供有效的HTML5选项作为关键词的参数。例如,如果剪辑太大,你可以这么写:

ipython_display(my_clip, width=400) # HTML5 will resize to 400 pixels

例如,当你编辑一个GIF动画,而且想检查它是否正确循环,你可以使视频自动启动和循环(即无限重复):

ipython_display(my_clip, autoplay=1, loop=1)

重要的是,ipython_display实际上是将剪辑嵌入了你的笔记本里。优势在于你可以移动笔记本或将其放在网络上发布,视频将会运行。缺陷在于笔记本的文件尺寸会变得非常巨大。根据你的浏览器,多次重新计算和播放视频会在cache和RAM中占用一些空间(仅当密集使用时出现此问题)。重启浏览器即可解决问题。

使用matplotlib

自定义动画

MoviePy提供了一种生成自定义动画的方式:通过定义一个函数,以numpy数组的形式返回一个在给定的时间内一帧的动画。

例如,在如下的工作流中:

from moviepy.editor import VideoClip

def make_frame(t):
    """Returns an image of the frame for time t."""
    # ... create the frame with any library here ...
    return frame_for_time_t # (Height x Width x 3) Numpy array

animation = VideoClip(make_frame, duration=3) # 3-second clip

这个动画可以像通常一样导出:

# export as a video file
animation.write_videofile("my_animation.mp4", fps=24)
# export as a GIF
animation.write_gif("my_animation.gif", fps=24) # usually slower
matplotlib的简易实例

一个使用matplotlib的动画实例如下:

import matplotlib.pyplot as plt
import numpy as np
from moviepy.editor import VideoClip
from moviepy.video.io.bindings import mplfig_to_npimage

x = np.linspace(-2, 2, 200)

duration = 2

fig, ax = plt.subplots()
def make_frame(t):
    ax.clear()
    ax.plot(x, np.sinc(x**2) + np.sin(x + 2*np.pi/duration * t), lw=3)
    ax.set_ylim(-1.5, 2.5)
    return mplfig_to_npimage(fig)

animation = VideoClip(make_frame, duration=duration)
animation.write_gif('matplotlib.gif', fps=20)
在Jupyter Notebook中运行

如果你在Jupyter Notebook中运行,你可以体会到用ipython_display方法将视频剪辑嵌入在输出单元中的优势。示例如下:

import matplotlib.pyplot as plt
import numpy as np
from moviepy.editor import VideoClip
from moviepy.video.io.bindings import mplfig_to_npimage

x = np.linspace(-2, 2, 200)

duration = 2

fig, ax = plt.subplots()
def make_frame(t):
    ax.clear()
    ax.plot(x, np.sinc(x**2) + np.sin(x + 2*np.pi/duration * t), lw=3)
    ax.set_ylim(-1.5, 2.5)
    return mplfig_to_npimage(fig)

animation = VideoClip(make_frame, duration=duration)
animation.ipython_display(fps=20, loop=True, autoplay=True)

MoviePy的音频操作

这个章节会告诉你如何使用MoviePy去创建和编辑音频剪辑。

注意,当你使用MoviePy来剪切、混合或连接视频剪辑时,音频是自动处理的。如果你有兴趣来编辑音频文件,或者你想自定义视频的音频剪辑,请阅读此章。

音频剪辑的构成

在MoviePy中,音频剪辑和视频剪辑很相似:它们拥有长度,能以同样的方式被剪辑和组成,等等。一个显著的差异是audioclip.get_frame(t)

创建一个新的音频剪辑

音频剪辑可由一个音频文件创建,或从视频剪辑的音轨里提取出来。

from moviepy.editor import *
audioclip = AudioFileClip("some_audiofile.mp3")
audioclip = AudioFileClip("some_video.avi")

详见AudioFileClip

或者你也可以得到一个已创建的视频剪辑的音轨。

videoclip = VideoFileClip("some_video.avi")
audioclip = videoclip.audio
合成音频剪辑
导出和预览音频剪辑

你也可以导出分配一个音频剪辑当作视频剪辑的音轨。

videoclip2 = videoclip.set_audio(my_audioclip)

生成和导出视频剪辑

视频和音频剪辑是MoviePy里的核心对象。在此节里我们展示了如何生成不同种类的剪辑,以及如何将它们写入文件。关于修改剪辑信息(剪切、特效等),见视频转换与效果。关于如何将多个视频进行合成,见混合剪辑。关于如何在导出前预览视频,见如何更有效率地使用MoviePy

下面的代码总结了你可以用MoviePy生成的剪辑基本类型。

# VIDEO CLIPS
clip = VideoClip(make_frame, duration=4) # for custom animations (see below)
clip = VideoFileClip("my_video_file.mp4") # or .avi, .webm, .gif ...
clip = ImageSequenceClip(['image_file1.jpeg', ...], fps=24)
clip = ImageClip("my_picture.png") # or .jpeg, .tiff, ...
clip = TextClip("Hello !", font="Amiri-Bold", fontsize=70, color="black")
clip = ColorClip(size=(460,380), color=[R,G,B])

# AUDIO CLIPS
clip = AudioFileClip("my_audiofile.mp3") # or .ogg, .wav... or a video !
clip = AudioArrayClip(numpy_array, fps=44100) # from a numerical array
clip = AudioClip(make_frame, duration=3) # uses a function make_frame(t)
视频剪辑的类型

长视频是由视频剪辑组成的。这些剪辑可以使用专门的clip.get_frame()方法输出一个HxWx3的numpy数组来表示剪辑在时间t时的一帧。它们分为两类,一种是动态剪辑(由VideoFileClipVideoClip组成),另一种是非动态剪辑,在任意无限长的持续时间中展示同一图片(ImageClipTextClipColorClip)。还有一种特殊的视频剪辑叫做遮罩,同属于上面的类别,但是输出灰度值帧以表示另一个剪辑里的可见部分。一个视频剪辑可以携带一个音频剪辑clip.audio作为她的音轨,和一个遮罩剪辑。

VideoClip

VideoClip是MoviePy中所有其它视频剪辑里最基本的种类。如果你只想编辑视频文件,你就永远不会用到它。当你想通过从别的库里生成的帧来生成动画时,这个类就会很有用。你需要做的只是定义一个make_frame(t)函数,使它返回一个HxWx3的numpy数组(8位整数)来代表时间t时的帧。这里是一个使用制图库Gizeh的例子:

import gizeh
import moviepy.editor as mpy

def make_frame(t):
    surface = gizeh.Surface(128,128) # width, height
    radius = W*(1+ (t*(2-t))**2 )/6 # the radius varies over time
    circle = gizeh.circle(radius, xy = (64,64), fill=(1,0,0))
    circle.draw(surface)
    return surface.get_npimage() # returns a 8-bit RGB array

clip = mpy.VideoClip(make_frame, duration=2) # 2 seconds
clip.write_gif("circle.gif",fps=15)

moviepy库的SubtitlesClip_ide_06

注意,剪辑使用make_frame并没有一个精确的帧速率,所以你必须要为write_gifwrite_videofile,以及需要遍历每一帧的方法提供帧速率(fps,每秒的帧数)。

VideoFileClip

视频文件剪辑是由视频文件(支持大多数格式)或GIF文件中读取的剪辑。你可以像这样加载一个视频:

myclip = VideoFileClip("some_video.avi")
myclip = VideoFileClip("some_animation.gif")

注意,这些剪辑都有fps(帧速率)属性,当你对剪辑做小改动时,帧速率将会被传送,而且会以write_videofilewrite_gif等的默认设置会使用。例如:

myclip = VideoFileClip("some_video.avi")
print (myclip.fps) # prints for instance '30'
# Now cut the clip between t=10 and 25 secs. This conserves the fps.
myclip2 = myclip.subclip(10, 25)
myclip2.write_gif("test.gif") # the gif will have 30 fps

详见VideoFileClip。

ImageSequenceClip

这是一种由一系列图片组成的剪辑,你可以这样调用:

clip = ImageSequenceClip(images_list, fps=25)

作品展示

脚本示例

移动的字母

我认为这个例子很好地展示了基于脚本编辑的有趣之处(想象是手动实现它的)。



代码如下:

import numpy as np
from moviepy.editor import *
from moviepy.video.tools.segmenting import findObjects

# WE CREATE THE TEXT THAT IS GOING TO MOVE, WE CENTER IT.

screensize = (720,460)
txtClip = TextClip('Cool effect',color='white', font="Amiri-Bold",
                   kerning = 5, fontsize=100)
cvc = CompositeVideoClip( [txtClip.set_pos('center')],
                        size=screensize)

# THE NEXT FOUR FUNCTIONS DEFINE FOUR WAYS OF MOVING THE LETTERS


# helper function
rotMatrix = lambda a: np.array( [[np.cos(a),np.sin(a)], 
                                 [-np.sin(a),np.cos(a)]] )

def vortex(screenpos,i,nletters):
    d = lambda t : 1.0/(0.3+t**8) #damping
    a = i*np.pi/ nletters # angle of the movement
    v = rotMatrix(a).dot([-1,0])
    if i%2 : v[1] = -v[1]
    return lambda t: screenpos+400*d(t)*rotMatrix(0.5*d(t)*a).dot(v)
    
def cascade(screenpos,i,nletters):
    v = np.array([0,-1])
    d = lambda t : 1 if t<0 else abs(np.sinc(t)/(1+t**4))
    return lambda t