MoviePy,一个超强的Python库(文末送书)
moviepy简介及基本概念
moviepy概述
剪辑和合并视频:MoviePy 允许你从现有视频中选择特定的片段,然后将它们合并成一个新的视频文件。 添加文本和图形: 你可以在视频中添加文本、图形和其他元素,以创建字幕、水印或其他视觉效果。 视频效果:MoviePy 提供了一系列内置的视频效果,如模糊、旋转、缩放等,使用户能够轻松地对视频进行编辑和改进。 音频处理: 除了视频,MoviePy 还支持音频处理,你可以添加音轨、调整音量等。 格式转换: 通过 MoviePy,你可以将视频文件转换为不同的格式,以适应不同的设备和平台。 自定义效果: 如果内置效果不够,你还可以使用 MoviePy 提供的 API 来创建自定义的视频效果。
可以通过 pip 来安装 MoviePy,命令如下:
pip install moviepy
视频剪辑中的mask
👉点击领取:最全Python资料合集
RGB、灰度、RGBA、ARGB和PARGB
合成图像的像素显示颜色=源图像像素颜色 X alpha + 背景图像像素颜色 X (1- alpha)
HSL 和HSV
色相(Hue):描述颜色的种类(如红色、绿色、蓝色等),通常表示为一个角度,范围从0°到360°。 饱和度(Saturation):描述颜色的强度,饱和度从0%(灰色)到100%(全色)。 亮度(Lightness)和明度(Value):描述颜色的明亮程度。0%表示全黑,100%表示全白。几乎等价于灰度值。
image-20231201210337806
image-20231201210245407
| HSL | HSV | |
|---|---|---|
| 饱和度 | 总是从完全饱和色变化到等价的灰色 | 在极大值V时,从全饱和色变化到白色 |
| 亮度 | 从黑色经过选择的色相到白色的完整范围 | V分量只走一半行程,从黑到选择的色相 |
剪辑基类Clip
image-20231209104209584
Clip类的属性
秒,例如75.35 分钟和秒组成的元组,例如(1,15.35) 时、分、秒组成的元组,例如(0,1,15.35) 用冒号分隔的时间字符串,例如’0:1:15.35’
如果为False剪辑的end值保持不变,当end存在有效值时,剪辑的时长被设置为end-start 默认为True,当duration存在有效值,end属性被更改为:start+duration
设置end属性时,如果start属性已经被设置,则剪辑的duration属性会被设置为end-start 如果start属性还没有设置,则start修改为end-duration,并限制最小值为0
set_duration调用语法:set_duration(self, t, change_end=True)
if change_end:self.end = None if (t is None) else (self.start + t)else:if self.duration is None:raise Exception("Cannot change clip start when new""duration is None")self.start = self.end - t
Clip类的方法
copy方法
get_frame(t)方法
fl方法
fun:参数fun是对剪辑帧进行变换的函数,要求带2个参数,第一个参数gf表示当前剪辑的get_frame方法,第二个参数为以秒为单位的剪辑位置t,t会作为gf的参数。fun函数的返回值为经过变换后的帧 apply_to:apply_to表示变换过滤器fl是否需要同时作用于剪辑的音频和遮罩,其值可以为’mask’、‘audio’、[‘mask’,‘audio’] keep_duration:如果为True表示不改变剪辑的duration属性
img
下面我们先实现一个简单的需求,让视频向上滚动(在整个时间时长内滚动三次):
from moviepy.editor import VideoFileClipsrc = VideoFileClip("t.mp4")w, h = src.sizeduration = src.durationdef fl(gf, t):frame = gf(t)dh = int(h*t*3/duration) % hreturn np.vstack((frame[dh:], frame[:dh]))newclip = src.fl(fl, apply_to='mask')newclip.write_videofile("r.mp4")
下面我们实现视频在前一半时间内从底部恢复到顶部的效果(素材被设置为2秒的时长):
from moviepy.editor import VideoFileClipsrc = VideoFileClip("t.mp4")w, h = src.sizeduration = 2src = src.set_duration(duration)def fl(gf, t):frame = gf(t).copy()frame[:max(0, h-round(h*t*2/duration))] = (0, 0, 0)return framenewclip = src.fl(fl, apply_to='mask')newclip.write_videofile("r.mp4")
时间为0时,黑色蒙版的宽度为0->w;时间到一半时长时,黑色蒙版的宽度降低到w->w。最终达到视频从左下角到右上角滚动的效果。
def fl(gf, t):frame = gf(t).copy()frame[:max(0, h-round(h*t*2/duration))] = (0, 0, 0)frame[:, round(w*t*2/duration):w] = (0, 0, 0)return frame
如果我们考虑右侧蒙版不必重复修改右上角的黑色蒙版区域,那需要限制高度范围,高度变化为起始点h->h,结束点0->h:
def fl(gf, t):frame = gf(t).copy()x = round(w*t*2/duration)y = round(h*t*2/duration)frame[:max(0, h-y)] = (0, 0, 0)frame[max(0, h-y):h, x:w] = (0, 0, 0)return frame
fl_time方法
t_func:参数t_func是对剪辑帧进行变换的函数,它将t时刻的帧替换为原剪辑t_func(t)位置的帧 apply_to:apply_to表示变换是否需要同时作用于剪辑的音频和遮罩,其值可以为’mask’、‘audio’、[‘mask’,‘audio’] keep_duration:如果为True表示不改变剪辑的duration属性,缺省为False,如果变化修改了duration需要设置为False。剪辑的duration属性修改后必须调用set_duration设置duration属性,并在设置后返回新剪辑。
示例:
modifiedClip1 = my_clip.fl_time(lambda t: 3*t)modifiedClip2 = my_clip.fl_time(lambda t: 1+sin(t))
fx方法
这个方法的用途是当需要使用一系列方法依次调用处理剪辑且每个方法返回的新剪辑作为下次调用者时可以简化语句。
如:clip.fx( mirrorx ).fx( volumex, 0.5).fx( resize, 0.3)
等同于:resize(volumex(mirrorx(clip), 0.5), 0.3)
set_fps/set_ismask方法
is_playing方法
subclip方法
cutout方法
iter_frames方法
fps往往存在默认值,不需要手动指定 dtype无需设置,当读取到的数组类型不是uint8时,可以设置为uint8进行转换减少内存消耗,因为8个字节正好能够存储每个颜色通道0-255的颜色值。 默认只返回对应帧,如果参数with_times为True,则同时返回对应帧的时刻位置 logger参数用于指定日志信息打印相关的类
close方法
视频剪辑基类VideoClip
VideoClip的构造方法和属性
make_frame:帧的构建方法,被get_frame调用,默认从已有剪辑中获取,也可以自定义; ismask:是否作为遮罩使用 duration:构建剪辑的时长 has_constant_size:表示是否所有帧长宽大小都相同,add_mask函数被调用时会使用该函数判断。如果该参数会True,add_mask函数会生成ColorClip(self.size, 1.0, ismask=True)的遮罩;如果为False,则获取每一帧的size生成动态大小的遮罩。正常情况下视频的尺寸都是恒定的,即使不恒定也应该先调整到固定大小写,所以该参数设置True即可。
add_mask:添加透明度固定为1(完全不透明)的遮罩 set_opacity:添加透明度透明度固定为指定值的遮罩 set_mask:设置自己创建的遮罩
官网自定义make_frame示例:
import gizehimport moviepy.editor as mpydef make_frame(t):surface = gizeh.Surface(128,128) # width, heightradius = W*(1+ (t*(2-t))**2 )/6 # the radius varies over timecircle = gizeh.circle(radius, xy = (64,64), fill=(1,0,0))circle.draw(surface)return surface.get_npimage() # returns a 8-bit RGB arrayclip = mpy.VideoClip(make_frame, duration=2) # 2 secondsclip.write_gif("circle.gif",fps=15)
VideoClip的访问方法
save_frame方法
write_videofile方法
write_videofile方法用于将视频剪辑输出到文件,调用语法如下:
write_videofile(self, filename, fps=None, codec=None,bitrate=None, audio=True, audio_fps=44100,preset="medium",audio_nbytes=4, audio_codec=None,audio_bitrate=None, audio_bufsize=2000,temp_audiofile=None,rewrite_audio=True, remove_temp=True,write_logfile=False, verbose=True,threads=None, ffmpeg_params=None,logger='bar')
filename:视频文件名,ffmpeg支持的视频格式都可以,例如 .ogv, .mp4, .mpeg, .avi, .mov等 fps:帧率,每秒编码的帧数 codec:用于图像编码的编解码器,可以是ffmpeg支持的任何编解码器。如果文件名的扩展名为“.mp4”、“.ogv”、“.webm”,则会自动设置相应编解码器,也可以指定其他编解码器。 bitrate:输出视频的比特率,也即码率BPS(Bits Per Second),指每秒传送的数据位数 audio:是否保存音频,如果为False则保存的视频无音频,如果为音频文件名字符串,则使用目标文件中的音频作为最终视频的音频。 audio_fps:声音的采样频率 preset:设置FFMPEG用于优化压缩的时间。字符串类型,可选值有:ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、 placebo。设置越快,则压缩率越低,文件越大;反正越慢,压缩率越高,文件越小。 audio_xxx相关参数含义可以查看AudioClip的说明。 temp_audiofile:如果输出由音频,则该参数用于指定要生成并合并到电影中的临时音频文件的名称,否则使用默认的临时文件名 rewrite_audio:这个参数在1.0.3版本中没有作用 remove_temp:是否删除生成的临时音频文件 write_logfile:如果为True,将为音频和视频输出记录日志文件。日志文件名为filename+'.log' verbose:已废弃。 threads:指定ffmpeg处理时所使用的线程数 ffmpeg_params:需额外传递的其他ffmpeg参数,用列表传递,形如:[‘-option1’,‘value1’,‘-option2’,‘value2’] logger:字符串类型,"bar"表示进度条、None 表示不设置、或任何程序日志记录器的名字
‘libx264’:视频压缩效果好的一款编解码器,MP4的缺省编解码器,视频质量通过bitrate参数调节 ‘mpeg4’:一种可选的MP4编解码器,可以替代’libx264’,可以获得更好的视频质量 ‘rawvideo’:完美的视频质量,但文件会巨大,对应视频文件为’.avi’ ‘png’:完美的视频质量,对应视频文件为’.avi’,但文件大小比’rawvideo’小 ‘libvorbis’:是一种完全开放、免费的编解码器,有不错的视频格式,但使用不广,对应视频文件为’.ogv’ ‘libvpx’:一种很适合在HTML5中使用的网络视频轻量级编开源解码器,对应视频文件为’.webm’
write_images_sequence方法
write_images_sequence方法用于将剪辑输出到一系列文件中,调用语法如下:
write_images_sequence(self, nameformat, fps=None, verbose=True,withmask=True, logger='bar')
nameformat:输出文件名的规则,使用nameformat % i生成图片文件名,i表示迭代出来的第几帧(从零开始)。 fps:每秒输出帧数,如果没指定则按剪辑的fps进行输出 withmask:是否将遮罩作为图像的alpha通道输出,用于生成png透明图片 verbose:是否输出处理信息 logger:字符串类型,"bar"表示进度条、None 表示不设置、或任何程序日志记录器的名字
write_gif方法
write_gif将剪辑转换成gif动画输出到文件中,调用语法:
def write_gif(self, filename, fps=None, program='imageio',opt='nq', fuzz=1, verbose=True,loop=0, dispose=False, colors=None, tempfiles=False,logger='bar'):
program:用来进行转换的软件,支持imageio、ImageMagick或者是ffmpeg。 opt:应用优化的选项,仅program使用ImageMagick时有效,opt可以是“optimizeplus”或“OptimizeTransparency”。 fuzz:仅program使用ImageMagick时有效,通过考虑小于fuzz%的颜色差异实际上是相同的来压缩GIF文件大小 loop:表示GIF文件播放时循环播放多少次,如果为0就一直不停地播放,否则播放设定次数后就停止,该参数由GIF文件头控制 dispose:仅program使用ImageMagick时有效,表示播放动画时渲染当前帧时,如何处理前一帧,该参数由GIF文件头控制,默认值为False实际值为1,否则设置True实际值为2。根据GIF中该控制参数的取值含义: False表示当前帧只需在上一帧的基础上做局部刷新,上一帧中没有被当前帧覆盖的像素区域将继续展示。 True表示绘制当前帧之前,会先把前一帧的绘制区域恢复成背景色,这种方式常用于优化很多帧背景相同的情况,上一帧的背景色能通过当前帧的透明区域显示 colors:仅ImageMagick支持的参数,表示颜色的总个数。由于 GIF 格式颜色数的有效范围通常是 2 到 256 色,所以该参数设置2-256,设置更小的数值,文件会更小,但颜色失真也越多。 tempfiles:将每个帧写入一个临时文件,而不是写入到内存中,ImageMagick和ffmpeg支持。
subfx方法
subfx(self, fx, ta=0, tb=None, **kwargs)
fx:用于对剪辑进行变换处理的函数名 ta和tb:分别是剪辑段开始位置和结束位置。如果tb为None,则tb被设置为原剪辑的duration,如果tb为负数,则tb被设置为剪辑的duration + tb kwargs调用fx函数时需要传入的关键字参数
newclip = clip.subfx(vfx.speedx, 3, 6,factor = 0.5)
注:speedx本身是moviepy.video.fx.speedx下的一个函数,在moviepy.editor中被动态赋予了VideoClip类作为实例方法:
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))
fl_image方法
image_func:对剪辑帧进行图像变换的函数,仅一个参数就是要处理的帧,这个帧直接通过get_frame去获取,image_func函数的返回值为经过变换后的帧 apply_to:apply_to表示变换是否需要同时作用于剪辑的音频和遮罩,其值可以为’mask’、‘audio’、[‘mask’,‘audio’]
示例:
def invert_green_blue(image):return image[:,:,[0,2,1]]modifiedClip = my_clip.fl_image( invert_green_blue )
fill_array方法
shape小于pre_array本身的宽或高,则丢弃多余的部分。
add_mask/to_mask/to_RGB方法on_color方法
on_color(self, size=None, color=(0, 0, 0), pos=None, col_opacity=None)
color:设定的背景色RGB颜色组 pos:原剪辑对应的剪辑在新剪辑的框架上的位置 col_opacity:以背景色构造的底部剪辑的不透明度,0表示完全透明,为1表示完全不透明。
例如我们可以给视频添加一个20px的蓝色透明边框:
clipVideo = VideoFileClip("t.mp4")h,w = clipVideo.sizenewclip = clipVideo.on_color(size=(h+20,w+20),color=(0,0,255),col_opacity=0.6)
set方法(audio/mask/opacity/position)
像素坐标 (“center”,“top”):设定水平居中,垂直位置到顶部,类似的设置还有’bottom’、‘right’、‘left’ (factorX,factorY):基于剪辑的大小设置相对位置为(0,1)之间的浮点数。
例如我们将一个视频扩展到三倍宽度后分别放置:
threads = 4clipVideo = VideoFileClip("t.mp4")w, h = clipVideo.sizebgclip = clipVideo.on_color(size=(w*3+40, h+30), color=(0, 0, 255), col_opacity=0.6)newclip = CompositeVideoClip([bgclip, clipVideo.set_position(('left', 'top')), clipVideo.set_position((w+20, 'center')), clipVideo.set_position((w*2+40, 'bottom'))], bg_color=(255, 0, 0), use_bgclip=True)newclip.write_videofile("r.mp4", threads=threads)newclip.close()
image-20231201160444480
to_ImageClip方法
说明:输出文件时要指定codec类型,否则可能播放失败。
newclip = clipVideo.to_ImageClip(duration=1).set_fps(8)newclip.write_videofile("img.mp4",threads=threads)
without_audio方法
afx方法
VideoClip子类使用案例
DataVideoClip
data:用于生成视频剪辑的原始数据集列表 data_to_frame:将data数据集的某一秒的数据处理为帧 fps:生成剪辑的帧率
UpdatedVideoClip
world.clip_t :与world状态对应的剪辑时间 world.update()方法:更新world的状态(包括增加clip_t一个时间步)的方法 world.to_frame()方法:根据world的状态生成一个帧的方法
ImageClip
img:任何图像文件或代表一个RGB图像的数组(例如一个视频剪辑的帧数据) ismask:设置为True时,图片的Red通道值构建剪辑 transparent:设置为True时,图片的alpha层作为剪辑的遮罩,图像的背景层作为视频剪辑,当前剪辑是一个带有遮罩的剪辑 fromalpha:设置为True时,图片的alpha层构建剪辑
如果图片不带alpha层,transparent和fromalpha会被忽略。fromalpha、ismask和transparent参数互斥,优先使用fromalpha=True的设置,其次使用ismask=True的设置,最后应用transparent=True的设置。具体实现为:
if img.shape[2] == 4:if fromalpha:img = 1.0 * img[:, :, 3] / 255elif ismask:img = 1.0 * img[:, :, 0] / 255elif transparent:self.mask = ImageClip(1.0 * img[:, :, 3] / 255, ismask=True)img = img[:, :, :3]elif ismask:img = 1.0 * img[:, :, 0] / 255
示例:
from moviepy.editor import ImageClip, vfx, VideoFileClip, CompositeVideoClipsrc = VideoFileClip("t.mp4")w, h = src.sizeclip = ImageClip("mask.png", duration=src.duration)clip = clip.fx(vfx.resize, (w-40, h//3))r = CompositeVideoClip([src, clip])r.write_videofile("r.mp4", fps=8)
image-20231207171557513
image-20231207171248529
fl方法:与父类的VideoClip.fl等效,但返回VideoClip对象 fl_image方法:与父类相同,实现上仅处理第一帧,再全部返回这被处理的第一帧数据 fl_time方法:ImageClip的fl_time方法对ImageClip不进行任何处理,但该方法可能会影响剪辑的遮罩或音频,返回ImageClip对象
ColorClip
size:剪辑的大小,一个宽和高组成的元组 color:如果ismask为False,则为RGB颜色(默认为黑色全0),如果ismask为True,则color代表灰度值,为一个0到1之间的浮点数(col已被废弃使用color替代) ismask:是否将剪辑作为遮罩 duration:剪辑时长
示例:
colClip = ColorClip((360,360),color = (255,0,0),ismask=False,duration=5).set_fps(1)colClip.write_videofile("red.mp4", codec='mpeg4')
TextClip
TextClip构造方法语法如下:
__init__(self, txt=None, filename=None, size=None, color='black',bg_color='transparent', fontsize=None, font='Courier',stroke_color=None, stroke_width=1, method='label',kerning=None, align='center', interline=None,tempfilename=None, temptxt=None,transparent=True, remove_temp=True,print_cmd=False)
txt:需要在剪辑中显示的文字,这个参数和参数filename可以相互替换,二者同时存在时txt优先 filename:存储需要在剪辑中显示文字的文件名 size:剪辑的大小,如果method参数为’label’可以设置为None,由moviepy自动根据文字设定,但如果method参数为’caption’,则必须设置,此时高度也可以设置为None,由moviepy根据文字数量、大小以及宽度自动设置 color:文字显示的前景色,请参考下面介绍list方法时的说明 bg_color:剪辑的背景色 fontsize:文字字体大小 font:字体设置,字体和运行机器相关,在机器上能使用的字体请参考下面介绍list方法时的说明 stroke_color:文字轮廓线的颜色,如果为None则没有轮廓线 stroke_width:轮廓线的宽度,可以为浮点数 method:可以设置为’label’或’caption’,设置为’label’时,图片将自动调整大小以适合剪辑的大小,这是该参数的缺省值。设置为’caption’时,文字将在size参数指定范围内显示,此时文字会自动换行,但自动换行功能由于使用的ImageMagick库的问题有时不能正确工作 kerning:更改字母之间的默认间距。例如kerning=-1与默认间距相比,将使字母之间的间距更接近1个像素 align:文字的对齐方式,仅在method设置为caption时生效,确实值为center,可选择的值包括:center 、 East 、 West 、 South 、 North interline:整型,以像素为单位的显示文字行之间的行间距,对应ImageMagick的命令行参数interline-spacing tempfilename:中间输出的临时文件名,这个中间临时文件是将文本转换成png图片先输出时的临时文件,该临时文件后续被moviepy调用ImageClip的构造方法进行处理生成剪辑,如果需要查看临时文件图片可以指定该文件名好方便查看 temptxt:临时文件名,用于在显示文本通过参数txt传值时,处理时将显示文本临时输出到临时文件,创建临时文件的目的老猿经阅读源代码认为是为了统一txt传参和filename传参的处理方式。如果该参数为None,moviepy将自动创建一个随机的临时文件,否则使用指定临时文件名创建临时文件 transparent:如果要考虑图像的透明度需要设置为True,这也是缺省值 remove_temp:是否删除临时文件 print_cmd:是否输出提交给ImageMagick处理的命令
该方法是一个静态方法,直接带类名就可以调用。如:
TextClip.list('font')TextClip.list('color')
search(string, arg)方法:就是对list方法的结果进行过滤,也是一个静态方法。例如:
>>> TextClip.search(b'red','color')[b'DarkRed', b'IndianRed', b'IndianRed1', b'IndianRed2', b'IndianRed3', b'IndianRed4', b'MediumVioletRed', b'OrangeRed', b'OrangeRed1', b'OrangeRed2', b'OrangeRed3', b'OrangeRed4', b'PaleVioletRed', b'PaleVioletRed1', b'PaleVioletRed2', b'PaleVioletRed3', b'PaleVioletRed4', b'red', b'red1', b'red2', b'red3', b'red4', b'VioletRed', b'VioletRed1', b'VioletRed2', b'VioletRed3', b'VioletRed4']>>> TextClip.search('GB','font')['仿宋_GB2312']
VideoFileClip
构造方法:
__init__(self, filename, has_mask=False,audio=True, audio_buffersize=200000,target_resolution=None, resize_algorithm='bicubic',audio_fps=44100, audio_nbytes=2, verbose=False,fps_source='tbr')
filename:视频文件名,可以带路径 has_mask:是否有遮罩 , 如果视频包含rgba颜色,则可以将透明度作为遮罩层,但视频一般不支持。 audio:如果不希望加载视频文件的音频,可以将audio参数设置为False audio_buffersize:音频文件读取缓冲区大小,字节为单位,一般用缺省值足够,如果audio_buffersize比一个音频帧的大小还要小,会自动使用音频帧的大小代替 target_resolution:设置为加载后需要变换到的分辨率,是(width, height)形式的二元组,允许其中一个为None,则自动等比例缩放。使用该方法调整视频读取的分辨率,往往比后期修改视频分辨率快很多。 resize_algorithm:要改变加载后的视频分辨率,可以通过resize_algorithm指定调整分辨率的算法,缺省值为 “bicubic”,还可以是 “bilinear” 、"fast_bilinear"等。关于算法的更多信息请参考:https://ffmpeg.org/ffmpeg-scaler.html audio_fps:声音的采样频率 audio_nbytes:声音采样的位数 verbose:是否在标准输出设备上显示处理信息 fps_source:从视频的元数据metadata哪个数据中获取fps值,默认设置为’tbr’,但可以设置为’fps’,这可能有助于导入慢动作视频,否则可能会出意外。
CompositeVideoClip合成
clips:多个视频剪辑的列表,列表中的每个元素都是VideoClip类型的对象。列表中的每个剪辑都将显示在列表中其后面出现的剪辑的下面(参考下面合成剪辑的一些属性处理逻辑的最后一条)。每个剪辑的pos属性决定剪辑放置在最终合成剪辑屏幕的位置,每个剪辑的mask遮罩属性决定每个剪辑哪部分可见哪部分不可见 size:最终剪辑的大小(分辨率),如果size为None,则将clips中第一个剪辑的size作为最终剪辑的size bg_color:设置合成剪辑的背景色,背景色用于剪辑未填充且无遮罩的区域,如果要一个透明剪辑,则设置为None,否则为一个代表RGB颜色的三元组,如(0,0,0)代表黑色,也即透明色。该参数只有use_bgclip为False的情况下使用,实际上是通过构建一个由bg_color指定颜色的ColorClip来实现的 use_bgclip:如果列表中的第一个剪辑应用作所有其他剪辑的“背景”,则设置为True。第一个剪辑的大小必须与最后合成剪辑的大小相同。如果没有透明度,则最终剪辑将没有遮罩 ismask:最终合成剪辑是否为遮罩剪辑。
如果每个剪辑都设置了duration属性,合成剪辑的duration会自动计算,计算时取clips中所有剪辑的end属性值作为最终剪辑的end属性值和duration属性值 如果第一个剪辑为背景剪辑且该剪辑没有遮罩,则最终剪辑的透明度为False,否则需要看是否设置了背景色bg_color,如果未设置,则最终剪辑透明度为True,否则为False 最终剪辑的fps为clips中所有剪辑的最大者 最终剪辑的音频是所有clips剪辑音频的合成 最终剪辑的遮罩是所有clips剪辑的遮罩合成,如果所有剪辑无遮罩则创建一个完全不透明的遮罩 当所有剪辑都未指定pos属性时,默认所有剪辑在最终合成剪辑的位置为顶部居中,此时相关剪辑的显示内容会有很多重合,最上层的剪辑是clips中最后一个剪辑,最下层的剪辑是clips中第一个剪辑,除了最上层的剪辑,其他剪辑的内容只能超出其上层所有剪辑大小的部分才可见
ImageSequenceClip
构造方法:
__init__(self, sequence, fps=None, durations=None, with_mask=True,ismask=False, load_images=False)
sequence:参数sequence可以是如下三种之一 一个仅包含图片的文件夹路径目录名,目录下的文件将按字母顺序排列作为处理的系列图像文件 一个图像文件名的列表,在这种情况下开发者可以通过load_images参数控制选择将文件图像一次性加载到内存中 一个表示图像的numpy数组列表,注意这种情况不支持遮罩 fps:每秒读入的图像帧数,该参数可以通过设定durations来替代 durations:每个图像在剪辑中显示的时长列表,因此可以给每个图像不同的播放时间,如果设置了fps,该参数将不起作用 with_mask:是否将PNG图像的alpha层作为遮罩 ismask:是否将生成剪辑作为遮罩 load_images:是否在处理前集中将图像文件加载到内存,如果为True,则对于sequence对应图像文件的情况,一次性的将所有图像文件先加载到内存,否则每处理一个文件加载一个。该参数仅对sequence为文件名列表的情况生效。
concatenate_videoclips合成同屏播放的视频
语法:
concatenate_videoclips(clips, method="chain", transition=None, bg_color=None, ismask=False, padding = 0)
“chain”:生成一个简单输出多个剪辑连续帧的剪辑,不论这些剪辑是否相同大小(分辨率)都不进行修正。如果参数列表中的剪辑都没有遮罩,则最终拼接的剪辑也没有遮罩,否则最终剪辑的遮罩就是所有参数剪辑遮罩的拼接,如果对应参数指定剪辑没有遮罩则使用完全不透明的剪辑作为遮罩。如果参数对应的多个剪辑有不同大小又想将拼接剪辑直接输出到文件,需要使用“compose”方法 “compose”:如果参数对应的剪辑不具有相同分辨率,最终分辨率将是使所有剪辑都不必调整大小的分辨率。因此,最终剪辑具有参数列表中最高剪辑的高度和最宽剪辑的宽度。所有尺寸较小的剪辑将显示为居中。如果mask=True,则边界为透明,否则为由“bg-color”指定的颜色。所有输入剪辑的最高FPS为最终连接剪辑的FPS
clips_array视频的堆叠(同屏显示)
调用语法:
clips_array(array, rows_widths=None, cols_widths=None, bg_color = None)
array:用于存放剪辑的二维列表,每个列表的元素都是一个列表,每个元素的列表代表在屏幕上同行显示的多个剪辑,一维列表中有多少个元素就表示在屏幕上显示多少行,每行视频有多个视频并列。 rows_widths:不同行的像素宽度,如果设置为None则自动设置 cols_widths:不同列的像素宽度,如果设置为None则自动设置 bg_color:为蒙版和未蒙版区域填充颜色。这些设置为None,这些区域将透明,处理速度会慢一些
官网示例:
from moviepy.editor import VideoFileClip, clips_array, vfxclip1 = VideoFileClip("myvideo.mp4").margin(10) # add 10px contourclip2 = 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")
img
常见的vfx变换函数
与颜色和透明度相关的变换
blackwhite函数
clip:要处理的剪辑,通过fx或subfx调用时,会将调用者的实例对象self传入 RGB:设置RGB三种颜色的权重,默认为1:1:1,如果设置为’CRT_phosphor’,则RGB权重= [0.2125, 0.7154, 0.0721] preserve_luminosity:用于控制是否保持亮度,如果为True则RGB权重换算到和为1,否则不变。 三个值相加为1。在这里的亮度luminosity不是lightness,实际上是对明度的度量,也称为灰阶值,是不同权重的R、G、B的组合值。
fadein、fadeout函数
fadeout(clip, duration, final_color=None)
两个函数内部的fl核心实现为:
# 作用于开始阶段fading = (1.0*t/duration)return fading*gf(t) + (1-fading)*initial_color# 作用于结束阶段fading = 1.0 * (clip.duration - t) / durationreturn fading*gf(t) + (1-fading)*final_color
invert_colors函数
invert_colors将像素对应颜色进行反转,核心实现:
maxi = (1.0 if clip.ismask else 255)return clip.fl_image(lambda f : maxi - f)
mask_color函数
与时间线相关的变换函数
freeze函数
t 和 padding_end:t为剪辑冻结位置的时间位置,单位为秒,但如果t的值为字符串’end’,则t=剪辑时长-padding_end freeze_duration:该帧持续显示的时间,浮点数,单位秒 total_duration:表示剪辑的最终生成的总时长,当freeze_duration为None时有效。
freeze_region函数
t:要固定显示内容在剪辑中的时刻 region:取t时刻region对应矩形的屏幕内容作为固定显示内容,矩形是一个四元组 (x1, y1, x2, y2),分别指定矩形的左上角和右下角的坐标 outside_region:取t时刻outside_region对应矩形外的屏幕内容作为固定显示内容 mask:将t时刻对应内容构建一个固定画面的剪辑并设置遮罩为参数mask后,将该剪辑与原剪辑叠加合成播放
设置region,矩形区域内的内容固定不变:
#构建矩形区域固定显示为剪辑第5秒的内容clipVideo1 = clipVideo.fx(vfx.freeze_region ,t=5,region=(200,300,500,700))
设置outside_region,矩形区域外的内容固定不变:
# 构建矩形区域外固定显示为剪辑第10秒的内容clipVideo2 = clipVideo.fx(vfx.freeze_region, t=10, outside_region=(200,300,500,700))
设置一个透明度0.5的mask,此时15秒时刻的指定大小的画面融合到整个时间的所有帧(时间时长低于30秒):
# 取剪辑15秒时刻的屏幕作为一个新剪辑,新剪辑的遮罩设置为半透明c2 = ColorClip((360, 400), ismask=True, color=0.5, duration=30)clipVideo3 = clipVideo.fx(vfx.freeze_region, t=15, mask=c2)
loop函数
speedx函数
函数的核心实现为:
newclip = clip.fl_time(lambda t: factor * t, apply_to=['mask', 'audio'])newclip = newclip.set_duration(clip.duration / factor)
time_mirror函数
time_mirror函数用于实现倒放效果,实现为:
self.fl_time(lambda t: self.duration - t, keep_duration=True)
time_symmetrize函数
与大小相关的视频变换函数详解
crop函数
x1、y1:矩形区域左上角坐标 x2、y2:矩形区域右下角坐标 width、height:宽度和高度 x_center、y_center:表示x1的坐标为x_center-width/2,x2的坐标为x_center+width/2,y_center类似处理
源码核心计算逻辑:
if width and x1 is not None:x2 = x1 + widthelif width and x2 is not None:x1 = x2 - widthif height and y1 is not None:y2 = y1 + heightelif height and y2 is not None:y1 = y2 - heightif x_center:x1, x2 = x_center - width / 2, x_center + width / 2if y_center:y1, y2 = y_center - height / 2, y_center + height / 2
even_size函数
margin函数
mar:外边框的宽度,以像素为单位,如果mar指定了有效值,则忽略 left、right、top、bottom的设定 left、right、top、bottom:边框左、右、顶和底的宽度 color:边框颜色 opacity :边框的不透明度,如果为0表示完全透明,1则完全不透明。与其他视频堆叠合并时有效。
resize函数
newsize还可以指定一个函数,例如:
def getsize(t):if t<2:return (600,800)else:return (0.8-1/t)
与内容相关的变换函数
mask_and和mask_or函数
mirror_x、mirror_y函数
mirror_y(clip, apply_to="mask")
如果apply_to=“mask”,则遮罩也进行同样处理。
rotate函数
angle:根据时间返回旋转角度的函数,也可以指定角度常数 unit:默认为deg角度,若指定为"rad",则angle可以填写弧度会被自动转换为角度 resample:图像的重采样算法默认值为’bicubic’ expand:默认为True会扩展每帧剪辑的大小以容纳旋转后的所有图像内容,确保所有图像信息不丢失。设置会False,则每帧大小保持和原剪辑一致,旋转超出部分会被裁切
scroll函数
w,h:滚动内容显示区域的大小,也是变换完后剪辑的大小 x_speed,y_speed:滚动速度,单位为:像素/秒 x_start,y_start:从剪辑的哪个位置开始滚动 apply_to:是否对遮罩等进行同样处理
supersample函数
将[t-d,t+d]时间段平均分成nframes个等间距时刻tt 然后取这个nframes个对应时刻的帧,最终颜色叠加取平均值作为当前帧的像素值
headblur函数
该函数依赖OpenCV,要求必须安装OpenCV后才能使用。安装命令:
pip install opencv-python
fx和fy用于获取t时刻,需要模糊处理的坐标(x,y)。 r_zone表示被模糊化处理的半径。 r_blur值越大模糊效果越明显,默认值为2*r_zone/3。
修改点在于:
if r_blur is None: r_blur = 2*r_zone//3# 和im = gf(t).copy()
音频剪辑基类AudioClip
背景知识介绍
音调:人耳对声音高低的感觉称为音调(也叫音频)。音调主要与声波的频率有关。声波的频率高,则音调也高。 音量:人耳对声音强弱的主观感觉称为响度。一般说来,声波振动幅度越大则响度也越大。 音色:音色与声波的振动波形有关,或者说与声音的频谱结构有关。也就是音品。音色是人们区别具有同样响度、同样音调的两个声音之所以不同的特性,或者说是人耳对各种频率、各种强度的声波的综合反应。
数字音频常用概念
采样率(Sample Rate):每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。一般音乐CD的采样率是44.1kHz,通常视频转换器也将这个采样率作为默认设置。常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,采样频率越高音质越好,但资源消耗越高。22.05kHz的采样频率是常用的, 44.1kHz已是CD音质,超过48kHz的采样对人耳已经没有意义 采样位数(Sample Bits):也称采样精度,指使用数字表示声音信号的数字的二进制位数,位数越多表示声音的精度越高,存储消耗越大。1 字节(8bit) 只能表示 256 种声音值,2 字节(16bit) 可以表示 65536 个声音值,越高播放的声音与源音的差距越小 通道数(channel):也称为声道数,在录制声音时在前后左右几个不同的方位同时获取声音,每个方位的声音就是一个声道。声道数是声音录制时的音源数量或回放时相应的扬声器数量,有单声道、双声道、多声道。moviepy1.0.3的版本支持单声道和双声道。 帧(frame):帧记录了一个声音单元,其长度为样本长度(采样位数)和通道数的乘积 码率(Bit Rate):也称为位速或比特率,指视频或音频文件在单位时间内使用的数据流量,针对编码格式,表示压缩编码后每秒的音频数据量大小。计算公式:比特率 = 采样率 x 采样位数 x 通道数,单位kbps,这里的k为1000
AudioClip简介
make_frame:根据时间构建帧的方法,被get_frame调用 duration:音频剪辑的时长 fps:采样率
iter_chunks方法
chunksize:块的大小 chunk_duration:块包含的音频时长,其值不为None时,则设置chunksize=int(chunk_duration*fps) fps:块输出的采样频率,如果为None则等于剪辑的采样频率 quantize:是否量化处理,如果为True,则将音频帧对应的音频数据每个元素的值限制在[-0.99,0.99]范围内,然后乘以2的(8*nbytes-1)次方 nbytes:音频采用位数,缺省值为2字节即16位 logger:是否开启日志,字符串类型,"bar"表示进度条、None 表示不设置、或任何程序日志记录器的名字
to_soundarray方法
tt:为时间浮点数或时间浮点数的列表,用于获取对应时间的音频数据 fps:采用频率,如果为None则等于剪辑的fps属性 quantize:是否量化处理 nbytes:音频采用位数,缺省值为2字节即16位 buffersize:缓冲区大小,从剪辑中转换时,该大小即为处理块的大小
max_volume方法
stereo:是否立体声,该参数为True且剪辑的声道数为2才会在处理时作为立体声处理,否则作为单声道处理
write_audiofile方法
filename:文件名,类型包括文件如mp3、wav、ogg、m4a等都可以 fps:帧率,与音频采样率含义相同,每秒编码的帧数,如果为None且音频剪辑设置了fps则以剪辑额的fps属性值作为输出,否则以缺省值44100输出 nbytes:音频的采用的位数 buffersize:输出缓冲区大小,以该大小作为输出时数据读取块的大小 bitrate:码率,音频比特率,字符串形式,如“50k”、“500k”、“3000k”,用于将确定输出文件中音频的大小/质量。请注意,这主要是一个指示性目标,输出文件的比特率不一定会按此设置 codec:用于音频编码的编解码器,如果没有指定则系统根据输出文件名类型来确认。默认值为“libmp3lame”,除非视频扩展名为“ogv”或“webm”,在这2种情况下,默认值为“libvorbis”。如果是16位wav音频设置为 ‘pcm_s16le’、32位wav音频则设置为 ‘pcm_s32le’,对应音频类型和使用的编解码器如下: ogg:libvorbis mp3:libmp3lame, wav:pcm_s16le,、pcm_s24le,或pcm_s32le,根据采样位数确认 m4a:libfdk_aac write_logfile:如果为True,将为音频输出记录日志文件。日志文件将以“.log”结尾,包含输出文件的名称 verbose:已经废弃使用,留下来是为了兼容性,以前用于打开/关闭消息。现在使用logger=None。 ffmpeg_params:需额外传递的其他ffmpeg参数,用列表传递,形如:[’-option1’,‘value1’,’-option2’,‘value2’] logger:字符串类型,"bar"表示进度条、None 表示不设置、或任何程序日志记录器的名字
音频文件类AudioFileClip
filename:声音文件(可以是所有ffmpeg支持的音频文件类型,如mp3、wav、ogg、m4a等)或ffmpeg视频文件的的名字或者表示声音的数组。如果声音文件不是wav文件,moviepy首先使用fps、nbytes、bitrate将其转换成wav文件 buffersize:装入内存部分的大小,对应大小为音频帧的数量 nbytes:声音位数 fps:音频采样率,默认为44.1kHz
nchannels:原始音频帧的通道数 fps:加载后的音频采样率 buffersize:保存的构造方法的buffersize参数 filename:原始音频文件名 reader:当前AudioFileClip使用FFMPEG读取音频数据的对象,读取音频数据可以来源于是FFMPEG音频文件或视频文件,读取完的数据会被转换成原始数据。
音量调整函数
volumex(clip, factor)可以分别调整多个声道的音量,例如将右声道静音,左声道音量调整为原来的一半:
audio.volumex([0.5,0])
👇👇👇👇👇
赠书福利来袭啦 清华大学出版社为大家送福利 《Python算法小讲堂》
内容简介
《Python算法小讲堂(视频精讲版)》通过由浅入深的39个Python语言实际案例,不仅帮助初学者学习Python语言的基本使用,还可以使读者从数据、算法等多个角度体验编程的魅力。
本书从“如何解决问题”出发,讲述了常用的人工智能编程语言——Python语言的基本使用,帮助读者学习如何进行简单的数据处理,了解什么是算法,领略算法的魅力。当然,最终都是让初学者一行行地亲手写出代码,在计算机上运行自己写出的程序。
点击下方链接,立即购买
截止时间: 2024 年 1 月 22 日 12:00 整
#关注有礼# 以上书单喜欢吗?可以分享一下你喜欢这本书的理由!或者你对本文的见解,活动截止时虎哥会在读者中随机选出5位,送以上书籍一本~