☞ ░ 前往老猿Python博文目录 ░
一、引言
在《moviepy音视频剪辑:moviepy中的剪辑基类Clip详解》介绍了剪辑基类的fl、fl_time、fx方法,在《moviepy音视频剪辑:视频剪辑基类VideoClip的属性及方法详解》介绍了fl_image和subfx方法,
在《Python+moviepy音视频剪辑:视频帧数据的本质、Clip的fl方法进行变换处理的原理以及滚屏案例》及《moviepy音视频剪辑:使用fl_time进行诸如快播、慢播、倒序播放等时间特效处理的原理和可能遇到的坑》分别介绍了fl和fl_time进行视频剪辑变换的原理及使用方法。
实际上moviepy所有视频变换的方法都是以Clip的fl方法为基础衍生出来的,最后都会调用到fl方法实施真正的变换,只是变换处理的逻辑由上次方法提供,如fl_time就是针对剪辑的时间线进行变换、fl_image就是针对剪辑的内容进行变换,开发者也可以根据自己的需要实现自己的变换方法。
为了支持一些常规的变换处理,moviepy提供了一系列常用的变换函数,开发者可以直接使用这些方法进行变换,这些函数都在moviepy.video.fx包下,基本上一个函数就是一个文件,在moviepy.editor通过import moviepy.video.fx.all as vfx
中将这些函数都加载到了vfx模块下,可以直接通过vfx.函数名方式调用,也可以通过VideoClip类+函数名直接调用,这是因为在moviepy.editor执行录入如下语句:
for method in [
"afx.audio_fadein",
"afx.audio_fadeout",
"afx.audio_normalize",
"afx.volumex",
"transfx.crossfadein",
"transfx.crossfadeout",
"vfx.crop",
"vfx.fadein",
"vfx.fadeout",
"vfx.invert_colors",
"vfx.loop",
"vfx.margin",
"vfx.mask_and",
"vfx.mask_or",
"vfx.resize",
"vfx.rotate",
"vfx.speedx",
]:
exec("VideoClip.%s = %s" % (method.split(".")[1], method))
将这些函数动态赋值给了VideoClip的同名实例变量,但这些实例变量是在moviepy.editor中定义的,因此在VideoClip的派生子类中不能这样使用。
这些函数的调用可以通过Clip的fx方法和VideoClip的subfx方法进行调用,具体调用语法请参考上面介绍的博文内容。
由于变换函数比较多,老猿将其以自己的标准分为了大小变换、时间变换、颜色变换、内容变换四个部分分别介绍,这种分法不一定非常对,比如有些部分的变换可能既和时间相关又和内容相关,两个归类都可以,大家就不必深究了。
本文主要介绍和剪辑大小相关的变换函数,包括crop、even_size、margin和resize。
二、crop函数
crop函数从剪辑中获取一个矩形区域的剪辑内容作为新的剪辑。
调用语法:
crop( clip, x1=None, y1=None, x2=None, y2=None, width=None, height=None, x_center=None, y_center=None)
参数:
- x1、y1:代表矩形区域左上角坐标
- x2、y2:代表矩形区域右下角坐标
- width、height:是宽度和高度
- x_center、y_center:表示x1的坐标为x_center-width/2,x2的坐标为x_center+width/2,y_center类似处理
数据计算逻辑
下面以横坐标系数据为例来说明矩形位置坐标(单位:像素)的计算逻辑:
- 横坐标系数据 x1、x2、width只要出现任意2个就能算出另外1个
- x_center如果出现,则可以计算出x1和x2
- 如果 x1、x2、width只出现1个或者都未出现,则x1、x2其中未出现的则取原剪辑的左上角或右下角的横坐标,因此单独出现width没有意义
以上计算过程是有顺序的,只有前面的不满足才会执行后面的。纵坐标系数据同样如此。
案例:
if __name__=='__main__':
threads = 8
clipVideo = VideoFileClip(r"F:videoWinBasedWorkHard_src.mp4").fx(vfx.crop,0,260)
clipVideo.write_videofile(r"F:videocrop.mp4", threads=threads)
clipVideo.close()
原剪辑和执行代码后存储剪辑对应帧图像对比:
上图中左边为原视频的帧图像,右边为上述代码执行后视频帧的图像。
三、even_size函数
even_size函数是将剪辑的宽和高变成偶数,如果这两个值有为奇数的,则剪辑的帧在丢弃一行或一列像素。这是因为ffmpeg编码规则要求宽和高必须是偶数,相当于一个纠错处理的函数,并没有实际处理的意义。其调用参数就是一个clip。
四、margin函数
margin函数在剪辑的四周增加一个外边框。
调用语法如下:
margin(clip, mar=None, left=0, right=0, top=0, bottom=0, color=(0, 0, 0), opacity = 1.0)
说明:
- mar:外边框的宽度,以像素为单位,如果mar指定了有效值,则 left、right、top、bottom设定值不起作用
- left、right、top、bottom:边框左、右、顶和底的宽度
- color:边框颜色
- opacity :边框的不透明度,如果为0表示完全透明,1则完全不透明
增加边框的剪辑,其宽度和高度都会相应增加,因此剪辑大小会变大。
案例:
if __name__== '__main__':
threads = 8
clip = VideoFileClip(r"F:videoWinBasedWorkHard_src.mp4").crop(0, 300, 540, 660)
newclip = clip.fx(vfx.margin, 3, color=(0, 0, 255), opacity=0.5)
newclip.write_videofile(r"F:videoWinBasedWorkHard_margin.mp4", threads=threads)
视频效果:
五、resize函数
resize函数用于调整剪辑的大小,包括缩小或放大。
调用语法:resize(clip, newsize=None, height=None, width=None, apply_to_mask=True)
说明:
- 使用resize必须先安装了OpenCV、Scipy或PIL图像处理模块中的一个,否则不能使用
- newsize可以是返回新剪辑的宽和高二元组,也可以是大小变化的比例如0.5或2,还可以是一个和剪辑帧时间t相关的函数来返回前面2种值中的一个
- width、height:剪辑的宽或高,二者指定一个,另一个会自动计算
六、小结
本文主要介绍和剪辑大小相关的变换函数,包括crop、even_size、margin和resize,相关的函数会在原剪辑大小的基础上进行大小变化,包括裁取其中一部分、给剪辑增加边框和调整剪辑大小等,返回新剪辑。
更多moviepy的介绍请参考《PyQt+moviepy音视频剪辑实战文章目录》或《moviepy音视频开发专栏》。
关于收费专栏
老猿的付费专栏《使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏加起来只需要19.9元,都适合有一定Python基础但无相关专利知识的小白读者学习。这2个收费专栏都有对应免费专栏,只是收费专栏的文章介绍更具体、内容更深入、案例更多。
收费专栏文章目录:《moviepy音视频开发专栏文章目录》、《使用PyQt开发图形界面Python应用专栏目录》,本文收费专栏对应文章为《moviepy音视频剪辑:与大小相关的视频变换函数详解》。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。