MoviePy - 使用 Python 编辑视频
MoviePy 是一个用于编辑视频的 Python 模块,可用于视频剪切、视频合并、标题插入、视频旋转变换等一些基本的视频操作。MoviePy 可以读写很多常见的视频格式,包含 GIF。
本文介绍如何使用 MoviePy。
欢迎点击链接跳转 Github Page 博客,享受更舒适的排版界面。
什么时候需要 MoviePy
在以下情况十分适合使用 MoviePy:
- 以一致的方式编辑和处理大批量视频;
- 想在如 Django、Flask 等服务上合成视频或动图;
- 希望将繁琐的任务自动化,例如标题插入、剪辑场景、制作片尾字幕等;
- 从另一个 Python 库(如 Matplotlib、Mayavi)生成的图像创建动画。
以下用途中 MoviePy 不是最佳解决方案:
- 需要对视频做帧级的分析,例如人脸检测等,此时只需要使用 imageio、OpenCV 或 SimpleCV 等专门处理这些任务的库;
- 仅需要转换视频格式,或将多张图片合成视频,可以直接使用 ffmpeg 更加快速。
MoviePy 的优缺点
MoviePy 在开发中考虑了以下目标:
- 简单易用。视频编辑操作基本能使用极少的代码实现,容易上手;
- 灵活性高。能够在视频或音频的每一帧上做处理;
- 多平台可用。MoviePy 使用 numpy、ffmpeg 实现,能在几乎所有平台和 Python 版本运行。
MoviePy 如何工作
MoviePy 使用软件 ffmpeg 读写视频和音频文件,借助 ImageMagick 合成文本和写入 GIF 文件。视频的处理过程使用到 Numpy、Scipy 等 Python 库。
样例代码
# 引入用于编辑视频的所有包
from moviepy.editor import *
# 加载视频并选择 00:00:50 - 00:00:60 的片段
clip = VideoFileClip("myHolidays.mp4").subclip(50,60)
# 降低音量 (volume x 0.8)
clip = clip.volumex(0.8)
# 生成字幕片段,可自定义字体和颜色等
txt_clip = TextClip("My Holidays 2013", fontsize=70, color='white')
# 设置在屏幕中央显示 10 秒
txt_clip = txt_clip.set_pos('center').set_duration(10)
# 在载入的原视频上层覆盖文本视频
video = CompositeVideoClip([clip, txt_clip])
# 将输出结果写入文件中
video.write_videofile("myHolidays_edited.webm")
VideoPy 编辑操作
MoviePy 处理对象的基本单元为 clips,包含 AudioClips 和 VideoClips,在代码中可以看到,基本每一编辑操作都是作用在一个或多个 clips 上的。
混合片段 Mixing clips
视频合成,也称为非线性编辑,是在一个新剪辑中以一定的效果播放多个片段的现象。下面通过几个简单的样例介绍 MoviePy 的合并功能。
连接视频 Concatenate clips
将视频片段放在一起,最简单的方法是连接它们,在新剪辑中一个接一个地播放。视频连接通过函数 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")
堆叠视频 Stack clips
除了一个接一个播放的合并方式,MoviePy 还能将多个片段在同一画面中同时播放,形成片段堆叠效果,使用 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")
实现效果类似于:
覆盖视频 Composite clips
CompositeVideoClip 提供了非常方便的覆盖视频的方法,但是比前面所讲述的方法略显复杂。
video = CompositeVideoClip([clip1,clip2,clip3])
上述代码实现的覆盖关系为,片段 clip2 覆盖在 clip1 上层,clip3 覆盖在 clip2 上层。也就是说,当这三个片段具有相同的尺寸时,我们只看得到位于最上层的片段 clip3,除非 clip2 和 clip3 在尺寸或时长上只显示一部分。
需要注意的是,合成视频的尺寸大小以第一个参数 (clip1) 为准,因为它通常作为背景。而有些时候需要使合成视频尺寸更大,或者让背景更大,可以通过下面代码指定最终合成的尺寸大小:
video = CompositeVideoClip([clip1,clip2,clip3], size=(720,460))
在合成视频中,我们还可以通过 clip.set_start
来设置某片段的开始时刻,例如:
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 还没结束的时候就开始,此时可以通过 crossfadein
设置淡入效果的时间:
video = CompositeVideoClip([clip1, # starts at t=0
clip2.set_start(5).crossfadein(1),
clip3.set_start(9).crossfadein(1.5)])
如果 clip2 和 clip3 都比 clip1 小,可以通过设置其位置来决定它们出现在哪里。需要注意的是,坐标原点位于视频左上角。
video = CompositeVideoClip([clip1,
clip2.set_position((45,150)),
clip3.set_position((90,100))])
有更多的方法指定坐标:
clip2.set_position((45,150)) # x=45, y=150 , in pixels
clip2.set_position("center") # automatically centered
# clip2 is horizontally centered, and at the top of the picture
clip2.set_position(("center","top"))
# clip2 is vertically centered, at the left of the picture
clip2.set_position(("left","center"))
# clip2 is at 40% of the width, 70% of the height of the screen:
clip2.set_position((0.4,0.7), relative=True)
# clip2's position is horizontally centered, and moving down !
clip2.set_position(lambda t: ('center', 50+t) )
当指定视频坐标时,注意其遵循下图所示的坐标布局,左上角顶点为视频坐标开始原点。
混合音频 Compositing audio clips
将视频混合剪辑在一起时,MoviePy 会自动组合它们各自的音轨,形成最终剪辑的音轨,因此无需考虑手动编辑视频的音轨。
如果想从多个音频源制作自定义音频,可以使用 CompositeAudioClip
和 concatenate_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)])
音频操作 Audio in MoviePy
创建音频 Creating a new audio clip
音频对象可以从音频文件中初始化:
from moviepy.editor import *
audioclip = AudioFileClip("some_audiofile.mp3")
audioclip = AudioFileClip("some_video.avi")
也可以从视频的音轨中创建:
videoclip = VideoFileClip("some_video.avi")
audioclip = videoclip.audio
合并音频 Compositing audio clips
见本篇『混合音频 Compositing audio clips』部分。
设置为视频音轨
将音频剪辑片段指定为视频的配乐:
videoclip2 = videoclip.set_audio(my_audioclip)