MoviePy - 中文文档2-快速上手-MoviePy-Clips变换与特效

回到目录

下面是MoviePy中的几种对clip的修改:

  • 非常常见的修改clip属性的方法有:clip.set_duration, clip.set_audio, clip.set_mask, clip.set_start 等.
  • 已经实现的特效.clip.subclip(t1,t2):截取t1到t2时间段内的片段;还有一些高级效果,loop:让clip循环播放、time_mirror:让clip倒播,这些方法位于特殊的模块moviepy.video.fx, moviepy.audio.fx,应用clip.fx方法,比如clip.fx(time_mirror)让视频倒播。
  • 可你自己创造一些需要的特效。

以上的特效其实本质上并不是原地直接修改的(没有对原始视频修改),而是根据修改产生新的clip。所以,我们如果想让修改生效,需要将修改过的产生的clip赋值给某clip,保存修改。举个栗子。

my_clip = VideoFileClip("some_file.mp4")
my_clip.set_start(t=5) #没有做任何改变,修改会丢失
my_new_clip = my_clip.set_start(t=5) #这样才对。moviepy中,修改过的clip要重新赋值给变量,修改才会被保存

所以,当我们写出clip.resize(width=640),moviepy并不是立刻就逐帧修改clip。一般只会先修改第一帧,其他的左右的帧只有在需要的时候(最后写入文件或者预览)才会被resize。

另一方面,可以这样讲,创建一个clip,几乎是不会占用时间和内存的,几乎所有的计算其实发生在最后转换的时刻。

moviepy中的时间表示

很多方法都接受时间参数,clip.subclip(t_start,t_end),截取两个时间点之间的clip片段,在这个方法中,时间既可以用(t_start=230.54),以秒的时间来表示,也可以用(t_start=(3,50.54)),以3分50.54秒的形式来表示,还可以 (t_start=(0,3,50.54))或者 (t_start=(00:03:50.54)),以,小时,分钟,秒的形式老表示。

大多数没有赋值的时间参数会有一个默认值,比如clip.subclip(t_start=50),t_end的默认值就是视频的长度,clip.subclip(t_end=50),那么t_start就默认为0.当时间是负数的时候,代表倒数n秒。比如,clip.subclip(-20, -10)会截取倒数20秒到倒数10秒之间的片段。

改变clip属性的方法

clip.fx

假定我们很多修改clip的方法。这些方法呢,都是输入一个clip和一些参数,输出一个新的clip。

effect_1(clip, args1) -> new clip
effect_2(clip, args2) -> new clip
effect_3(clip, args3) -> new clip

如果我们要按顺序,依次修改clip,那么你可能会这样写:

newclip =  effect_3( effect_2( effect_1(clip, args3), args2), args1)

但是上面的代码可读性不高,我们可以利用clip.fx来实现一种更简练的写法。

newclip = (clip.fx( effect_1, args1)
               .fx( effect_2, args2)
               .fx( effect_3, args3))

看上去是不是好多了。在模块moviepy.video.fxmoviepy.audio.fx中已经实现来一些修改clip的方法,这些fx的方法会自动的作用到和clip相关的声音和mask上,所以我们在修改clip的时候并不需要去关心声音和mask的处理,除非我们确实要对声音或者mask做一些特殊的处理。

在实际应用中,当我们使用from moviepy import.editor *的时候,这两个模块会被加载为vfxafx,所以我们会像下面这样写

from moviepy.editor import *
clip = (VideoFileClip("myvideo.avi")
        .fx( vfx.resize, width=460) # 尺寸变化,保持纵横比
        .fx( vfx.speedx, 2) # 2倍速
        .fx( vfx.colorx, 0.5)) # 画面调暗

为方便起见,当我们使用moviepy.editor的时候,比如我们使用resize的时候,我们经常会使用clip.resize(...)这样的简便的写法来代替clip.fx( vfx.resize, ...)的写法。

创建用户自定义特效的方法

clip.fl

我们可以使用clip.fl_timeclip.fl_image或者更普遍的clip.fl来修改一个clip。

我们可以使用clip.fl_time修改clip的时间线,像下面这样

modifiedClip1 = my_clip.fl_time(lambda t: 3*t)
modifiedClip2 = my_clip.fl_time(lambda t: 1+sin(t))

现在,modifiedClip1是my_clip的三倍速度播放效果。modifiedClip2只会在t=0s和t=2s之间播放。在后一个例子中,我们已经创建了一个无限持续的clip(现在并不会出什么问题)。

我们也可以用clip.fl_image来修改一个clip的显示。接下来,将会把一个clip每一帧的绿色和蓝色通道转换。

def invert_green_blue(image):
    return image[:,:,[0,2,1]]
modifiedClip = my_clip.fl_image(invert_green_blue)

接下来,我没还有可能需要同时对时间和每一帧的画面都做处理,我们用clip.fl(filter)方法也是可以实现的,这个filter必须是一个传入两个参数,返回一个画面的函数。第一个参数是get_frame方法(例如:g(t)给定一个时刻,然后返回在那一时刻这个clip中对应的一帧),第二个参数就是时间。

def scroll(get_frame, t):
    '''
    这个函数返回:当前帧的一个‘区域’
    上述所说的‘区域’的位置依赖于第二个参数,时间
    '''
    frame = get_frame(t)
    frame_region = frame[int(t):int(t)+360,:]
    return frame_region
modifiedClip = my_clip.fl(scroll)

以上代码,将会向下滚动360个像素高度。

当我们在编写一些新的效果的时候,应该尽可能地使用fl_timefl_image,而不是fl。原因在于,在这些效果被应用于ImageClip的时候,MoviePy会认为这些方法不需要应用于每一帧,渲染速度会更快。

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

QQ群:MoviePy中文 :819718037

回到目录

你可能感兴趣的:(MoviePy,MoviePy实战应用)