moviepy音视频剪辑:多个视频合成一个视频

一、视频合成概述

视频合成,也称为非线性编辑,实际上是在一个新剪辑中播放几个剪辑。

请注意视频剪辑通常带有音频和遮罩(放到视频轨道上的图片视频音乐我们通常都称为素材,遮罩作用于素材上,用来遮挡或显示素材的部分内容。通常黑白相间的图片或者视频都可以作为遮罩使用,遮罩白色部分显示素材内容,遮罩黑色部分遮挡消除素材内容),它们也是剪辑。当您将这些剪辑组合在一起时,通过将剪辑的原声和遮罩组合在一起,将自动生成最终剪辑的原声和遮罩。所以大多数时候你不需要担心混音和面具。

两种简单的剪辑合成方法是将它们拼接起来(在一个长剪辑中一个接一个地播放它们)或将它们堆叠起来(在一个大剪辑中并排播放)。

二、视频的拼接

2.1、拼接方法和语法

视频的拼接使用方法concatenate_videoclips,调用语法:

concatenate_videoclips(clips, method="chain", transition=None, bg_color=None, ismask=False, padding = 0)
语法释义:
  • clips:多个视频剪辑的列表,列表中的每个元素都是VideoFileClip类型的对象
  • method:拼接方法,有2种取值
  1. “chain”:生成一个简单输出多个剪辑连续帧的剪辑,不论这些剪辑是否相同大小(分辨率)都不进行修正。如果参数列表中的剪辑都没有遮罩,则最终拼接的剪辑也没有遮罩,否则最终剪辑的遮罩就是所有参数剪辑遮罩的拼接,如果对应参数指定剪辑没有遮罩则使用完全不透明的剪辑作为遮罩。如果参数对应的多个剪辑有不同大小又想将拼接剪辑直接输出到文件,需要使用“compose”方法
  2. “compose”:如果参数对应的剪辑不具有相同分辨率,最终分辨率将是使所有剪辑都不必调整大小的分辨率。因此,最终剪辑具有参数列表中最高剪辑的高度和最宽剪辑的宽度。所有尺寸较小的剪辑将显示为居中。如果mask=True,则边界为透明,否则为由“bg-color”指定的颜色。所有输入剪辑的最高FPS为最终连接剪辑的FPS
  • transition: transition指定一个将在列表的每两个剪辑之间播放的剪辑 ,即结果剪辑不但会将参数对应剪辑拼接,而且会在两个剪辑拼接中间插入一个由transition指定的过场剪辑
  • bg_color:仅在method="compose"时使用,设置背景色,如果要一个透明剪辑,则设置为None,否则为一个代表RGB颜色的三元组,如(0,0,0)代表黑色,也即透明色
  • padding:仅在method=“compose"时使用,两个连续剪辑间的间隔时间,注意如果该参数为赋值,后面的剪辑和前一剪辑的播放有一段时间重叠,这种负数的padding参数,会制造出后一个剪辑逐渐变暗退出的效果。一个非0的padding值会自动将method置为"compose”
  • 返回值:最终拼接的剪辑

2.2、案例

fileList = ['F:\\video\\1.mp4', 'F:\\video\\2.mp4','F:\\video\\3.mp4']
tmpClip = []
for fileName in fileList:
    print(f"准备加载视频文件:{fileName} ")
    clip = mpe.VideoFileClip(fileName)
    print(f"加载视频文件:{fileName} 完成,时长为{clip.duration}秒 ")
    tmpClip.append(clip)
    print(f"视频文件:{fileName} 已经加载并缓存")

print("进行内存视频拼接...")
destClip = mpe.concatenate_videoclips(tmpClip)
print("内存视频拼接完成,准备输出到文件.")
destClip.write_videofile("F:\\video\\dest.mp4")
print("输出到文成功!")

2.3、两种拼接方法的使用

经实际验证,“chain”方法确实可以将不同分辨率的视频拼接起来,但在播放时,很可能除了与第一个视频分辨率相同的视频能正常播放外,其他视频播放可能出现花屏或扭曲,无法正常观看。对这种情况有两种处理方式:

  1. 对于不同视频分辨率的视频进行拼接时使用“compose”方法,compose方法会自动调整视频的分辨率(取所有视频的最大宽度和最高高度作为新分辨率)以确保所有视频都能正常播放,只是播放时,原视频的实际分辨率小于调整后的分辨率的,屏幕上会有留白空间,这些留白空间可以通过bg_color来设定显示的颜色;
  2. 通过代码调整源视频的分辨率,使得所有源视频加载后变成相同的分辨率,这样拼接时就是相同分辨率了。源视频加载后调整成相同分辨率的方法包括两种,一种是加载后,针对视频剪辑调用VideoFileClip的resize方法,另外一种是使用VideoFileClip的构造方法时,使用参数target_resolution指定加载视频同时需要调整到的分辨率(请参考《moviepy音视频剪辑:使用VideoFileClip、AudioFileClip和write_videofile、write_audiofile进行音视频的加载和输出》)。注意这两个方法的参数可以都是视频需要设置的分辨率,但两者的分辨率的宽和高的位置在列表中是相反的。

三、视频的堆叠(同屏显示)

3.1、语法

视频的堆叠使用了的clips_array函数,调用语法如下:

clips_array(array, rows_widths=None, cols_widths=None, bg_color = None)
参数说明:
  • array:用于存放剪辑的二维列表,每个列表的元素都是一个列表,每个元素的列表代表在屏幕上同行显示的多个剪辑,一维列表中有多少个元素就表示在屏幕上显示多少行,每行视频有多个视频并列。
  • rows_widths:不同行的像素宽度,如果设置为None则自动设置
  • cols_widths:不同列的像素宽度,如果设置为None则自动设置
  • bg_color:为蒙版和未蒙版区域填充颜色。这些设置为None,这些区域将透明,处理速度会慢一些
  • 返回值:合成后的剪辑

3.2、样例

print(f"视频将排列成{lines}行{columns}列")
clipArrays = []
tmpClipArray = []
column = 0
for clip in tmpClip:
    tmpClipArray.append(clip)
    column += 1
    if column == columns:
        clipArrays.append(tmpClipArray)
        column = 0
        tmpClipArray = []
destClip = mpe.clips_array(clipArrays)

跟老猿学Python、学5G!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章