💻【python】MoviePy从入门到入土(2)入门
2024-5-4
| 2024-5-4
字数 8307阅读时长 21 分钟
type
Post
status
Published
slug
moviepy02
date
May 4, 2024
summary
以下部分展示了开始使用 MoviePy 进行编辑所需的一切
tags
教学
python
category
技术分享
icon

快速演示

你是否需要 MoviePy?

以下是您可能需要使用 Python 编辑视频的几个原因:
  • 您有很多视频需要以复杂的方式处理或合成。
  • 您想要在 Web 服务器(Django、Flask 等)上自动创建视频或 GIF。
  • 您想要自动执行繁琐的任务,例如标题插入、跟踪对象、剪辑场景、制作片尾字幕、字幕等。
  • 您想要编写自己的视频效果来完成现有视频编辑器无法完成的任务。
  • 您想要从另一个 python 库(Matplotlib、Mayavi、Gizeh、scikit-images...)生成的图像创建动画。
以下是 MoviePy 不是最佳解决方案的一些用途:
  • 您只需要进行逐帧视频分析(使用面部检测或其他奇特的东西)。这可以通过 MoviePy 与其他库结合来完成,但实际上,只需使用 imageio、OpenCV 或 SimpleCV,这些是专门从事这些任务的库。
  • 您只想转换视频文件,或将一系列图像文件转换为电影。在这种情况下,最好直接调用 ffmpeg (或 avconv 或 mencoder ...),它会比通过 MoviePy 更快、更节省内存。

优点和局限性

MoviePy 的开发考虑了以下目标:
  • 简单直观。基本操作可以在一行中完成。代码简单易学,对于新手来说也很容易理解。
  • 灵活的。您可以完全控制视频和音频的帧,并且创建自己的效果就像 Py 一样简单。
  • 便携的。该代码使用非常常见的软件(Numpy 和 FFMPEG),并且可以在(几乎)任何具有(几乎)任何版本的 Python 的机器上运行。
对于限制:MoviePy(还)无法流式传输视频(从网络摄像头读取,或在远程机器上实时渲染视频),并且并不是真正为涉及电影的许多连续帧的视频处理而设计的(例如视频稳定,您'为此需要另一个软件)。如果您同时使用许多视频、音频和图像源(>100),您也可能会遇到内存问题,但这将在未来的版本中得到修复。

示例代码

在典型的 MoviePy 脚本中,您加载视频或音频文件,修改它们,将它们放在一起,然后将最终结果写入新的视频文件。举个例子,让我们加载我上次假期的视频,降低音量,在前十秒的视频中央添加标题,并将结果写入文件中:

MoviePy 的工作原理

MoviePy 使用软件 ffmpeg 来读取和导出视频和音频文件。它还(可选)使用 ImageMagick 生成文本并写入 GIF 文件。Python 的快速数值库 Numpy 确保了不同媒体的处理。高级效果和增强功能使用 Python 的众多图像处理库(PIL、Scikit-image、scipy 等)中的一些。
notion image

基本概念

MoviePy 的中心对象是剪辑,可以是 AudioClip 或 VideoClip。它们可以被修改(剪切、减速、加暗……),也可以与其他剪辑混合以形成新的剪辑。您可以预览这些剪辑(使用 PyGame 或 IPython Notebook),并将它们渲染到文件中(如 MP4、GIF、MP3 等格式)。例如,VideoClip 可以由视频文件、图像、文本或自定义动画创建。它们可以具有音轨(即 AudioClip)和遮罩(一种特殊的 VideoClip,指示混合其他剪辑时应该隐藏的剪辑部分)。有关更多详细信息,请参阅创建和导出视频剪辑以及混合剪辑。
剪辑可以使用 MoviePy 的众多效果之一进行修改(例如 clip.resize(width="360")、clip.subclip(t1,t2) 或 clip.fx(vfx.black_white)),也可以使用用户实现的效果。MoviePy 实现了许多函数(例如 clip.fl、clip.fx 等),这使得编写自己的效果变得非常简单。有关更多信息,请参阅剪辑变换和效果。
此外,您还可以在 moviepy.video.tools 中找到一些高级功能,用于在视频中跟踪对象、绘制简单形状和颜色渐变(对于遮罩非常有用)、生成字幕和片尾字幕等。有关这些功能的描述,请参阅高级工具。
最后,虽然 MoviePy 没有图形用户界面,但有许多预览剪辑的方法,使您能够在以高质量渲染视频之前微调脚本并确保一切完美。请参阅如何高效使用 MoviePy。

混合剪辑

视频合成,也称为非线性编辑,是将多个剪辑组合在一起形成新的剪辑的过程。以下视频是使用 MoviePy 进行合成的一个很好的示例:
Video preview
在开始之前,请注意,视频剪辑通常包含音轨和遮罩,它们也是剪辑。当您将这些剪辑组合在一起时,最终剪辑的音轨和遮罩会自动根据各个剪辑的音轨和遮罩生成。因此,大多数情况下,您无需担心混合音频和遮罩的问题。

堆叠和连接剪辑

将剪辑放在一起的两种简单方法是连接它们(在一个长剪辑中一个接一个地播放它们)或堆叠它们(在一个较大的剪辑中将它们并排播放)。
连接是通过函数 concatenate_videoclips 完成的:
final_clip 是一个剪辑,依次播放剪辑 1、2 和 3。请注意,剪辑不需要具有相同的尺寸。如果它们尺寸不同,它们将全部居中显示在一个足够大的剪辑中,以包含其中最大的一个,还可以选择填充边框的颜色。您还有许多其他选项(请参阅该函数的文档)。例如,您可以使用选项 transition=my_clip 在剪辑之间播放过渡剪辑。
堆叠是通过 clips_array 完成的:
您将获得一个类似以下的剪辑:
notion image

复合视频剪辑

复合视频剪辑提供了一种非常灵活的方式来组合剪辑,但比 concatenate_videoclips 和 clips_array 更复杂。
现在 video 播放 clip1,然后在 clip1 上播放 clip2,在 clip1 和 clip2 上播放 clip3。例如,如果 clip2 和 clip3 与 clip1 具有相同的大小,则视频中只有位于顶部的 clip3 可见……除非 clip3 和 clip2 具有隐藏它们部分的遮罩。请注意,默认情况下,合成的大小与其第一个剪辑的大小相同(因为它通常是背景)。但是有时您可能希望在更大的合成中浮动剪辑,因此您可以指定最终合成的大小如下:

开始和停止时间

在 CompositionClip 中,所有剪辑都在 clip.start 属性指定的时间开始播放。您可以按如下方式设置此开始时间:
因此,例如您的合成将如下所示:
在上面的示例中,也许 clip2 将在 clip1 结束之前开始。在这种情况下,您可以使 clip2 以一秒的淡入效果出现:

设置剪辑位置

如果 clip2 和 clip3 小于 clip1,您可以通过设置它们的位置来决定它们在合成中的显示位置。这里我们指定剪辑左上角像素的坐标:
有许多指定位置的方法:
在指定位置时,请记住 y 坐标的零点位于图片的顶部。
notion image

合成音频剪辑

当您将视频剪辑混合在一起时,MoviePy 会自动合成它们各自的音轨以形成最终剪辑的音轨,因此您无需担心自己合成这些音轨。
如果您想从多个音频源制作自定义音轨:音频剪辑可以使用 CompositeAudioClip 和 concatenate_audioclips 混合在一起:
这样可以根据需要自定义合成音频剪辑,以便满足特定的需求。

剪辑变换和效果

MoviePy 中的剪辑修改有几类:
  1. 常见方法:用于更改剪辑属性的常见方法,如 clip.with_durationclip.with_audioclip.with_maskclip.with_start 等。
  1. 已经实现的效果:核心效果(如 clip.subclip(t1, t2),保留 t1 和 t2 之间的剪辑)作为类方法实现。更高级和不太常见的效果(如 loop,使剪辑循环播放,或 time_mirror,使剪辑向后播放)放置在特殊模块 moviepy.video.fxmoviepy.audio.fx 中,并通过 clip.fx 方法应用。例如 clip.fx(time_mirror)(使剪辑向后播放)、clip.fx(black_white)(将剪辑转换为黑白),等等。
  1. 您可以自己创造的效果:您可以创建自定义效果,使用 fx 方法。
所有这些效果都具有一个共同点,即它们不是就地修改:它们不会修改原始剪辑,而是创建一个新剪辑,该剪辑是对前一个剪辑应用了更改的版本。例如:
另外,当您编写 clip.resize(width=640) 时,它不会立即将效果应用于剪辑的所有帧,而是仅应用于第一帧:所有其他帧只会在需要时(即当您将整个剪辑写入文件或预览时)进行调整大小。换句话说,创建新剪辑既不耗费时间也不耗费内存,所有计算都在最终渲染期间发生。

MoviePy 中的时间表示

在 MoviePy 中,许多方法都接受时间作为参数。例如 clip.subclip(t_start, t_end) 方法可以在两个时间点之间剪切剪辑。对于这些方法,时间可以用秒表示(例如 t_start=230.54),也可以用一对(分钟、秒)表示(例如 t_start=(3,50.54)),或者用三元组(小时、分钟、秒)表示(例如 t_start=(0,3,50.54)),还可以用字符串表示(例如 t_start='00:03:50.54')。
大多数情况下,如果未提供时间,MoviePy 会自动猜测。例如在 clip.subclip(t_start=50) 中,暗示着 t_end 对应于剪辑的结尾;在 clip.subclip(t_end=20) 中,暗示着 t_start 为 0。如果时间为负数,它被视为相对于剪辑结束的时间。例如,clip.subclip(-20, -10) 剪切的是距离剪辑结束前 20 秒到剪辑结束前 10 秒之间的部分。

更改剪辑属性的方法

假设您有一些函数实现了对剪辑的效果,即给定一个剪辑和一些参数,返回一个新剪辑:
其中 args 代表参数和/或关键字参数。要按顺序将这些函数应用于一个剪辑,您可能会编写类似于以下代码:
但这种方式不易阅读。为了更清晰的语法,您可以使用 clip.fx
好多了!在 moviepy.video.fx 和 moviepy.audio.fx 模块中已经实现了许多效果。如果相关,这些模块中的 fx 方法将自动应用于剪辑的声音和遮罩,这样您就不必担心修改它们。为了方便起见,这两个模块被加载为 vfx 和 afx,因此您可以这样写:
为了方便使用,诸如 resize 之类的 fx 方法可以以更简单的方式调用:clip.resize(...) 而不是 clip.fx(vfx.resize, ...)

创建自定义效果的方法

您可以使用自定义过滤器通过 clip.time_transform、clip.image_transform 等方式修改剪辑。
使用 clip.time_transform,您可以修改剪辑的时间线,例如:
现在,修改后的剪辑 modifiedClip1 的播放速度是原始剪辑的三倍,而 modifiedClip2 将在时间 t=0s 和 t=2s 之间振荡播放。需要注意的是,在最后一种情况下,您创建了一个持续时间无限的剪辑(目前这不是问题)。
使用 clip.image_transform,您可以修改剪辑的显示方式,例如:
最后,您可能希望同时考虑时间和帧图片来处理剪辑。这可以通过 clip.transform(filter) 方法实现。filter 必须是一个接受两个参数并返回图片的函数。第一个参数是 get_frame 方法(即给定时间的函数 gf(t) 返回该时间的剪辑帧),第二个参数是时间。例如:
这将使剪辑向下滚动,高度恒定为 360 像素。
在编写新效果时,尽可能使用 time_transform 和 image_transform 而不是 transform。这样做的原因是,当这些效果应用于 ImageClip 时,MoviePy 将意识到这些方法不需要应用于每一帧,这将导致更快的渲染。

如何高效使用 MoviePy

使用 MoviePy 的最佳方式是与 IPython Notebook 结合使用:它使得预览剪辑更加容易(正如我们将在本节中看到的),具有自动补全功能,并且可以显示库的不同方法的文档。

应该使用 moviepy.editor 吗?

在 MoviePy 的旧版本中,通常建议从 moviepy.editor 中导入。但在 v2.0 及以上版本中,不再建议这样做,您应该通常直接从 moviepy 中导入(例如,from moviepy import VideoFileClip)。现在,只有在您使用 MoviePy 手动编辑视频时才应加载 moviepy.editor 模块。导入它将:
  • 如果安装了 pygame,则启动 pygame 会话以启用 clip.show() 和 clip.preview()
  • 如果在 IPython Notebook 中,则启用 clip.ipython_display()
  • 如果安装了 Matplotlib,则启用 sliders()

何时关闭()剪辑

当您创建某些类型的剪辑实例 - 例如 VideoFileClip 或 AudioFileClip - MoviePy 会创建一个子进程并锁定文件。为了在使用完后释放这些资源,您应该调用 close() 方法。
这对于更复杂的应用程序更为重要,特别是在 Windows 上运行时。虽然 Python 的垃圾收集器最终应该为您清理资源,但关闭它们可以让它们更早地可用。
然而,如果您过早关闭剪辑,剪辑上的方法(以及从它派生的任何剪辑)将变得不安全。
因此,经验法则是:
  • 一旦您使用完您构建的任何剪辑以及使用从该剪辑派生的任何剪辑,就可以调用 close() 。
  • 即使您关闭 CompositeVideoClip 实例,您仍然需要关闭创建它的剪辑。
  • 否则,如果您有一个通过从另一个剪辑派生而创建的剪辑(例如通过调用 with_mask() ),那么通常您不应该关闭它。关闭原始剪辑也会关闭副本。
剪辑充当上下文管理器。这意味着您可以将它们与 with 语句一起使用,并且即使存在异常,它们也会在块末尾自动关闭。

预览剪辑的多种方式

当您编辑视频或尝试通过 MoviePy 实现效果时,通过反复试验生成视频可能会非常耗时。本节介绍了一些加快速度的技巧。

剪辑保存

大多数情况下,只需要视频的一帧就足以告诉您是否正确操作。您可以将剪辑的一帧保存到文件中,方法如下:

剪辑显示和预览

方法 clip.show()clip.preview() 可以在 Pygame 窗口中预览剪辑。它们是最快的预览方式,因为剪辑是同时生成和显示的,并且对于获取像素的坐标或颜色非常有用。这些方法需要安装 PyGame 并使用 moviepy.editor 模块。

IPython 显示

在 IPython Notebook 中显示剪辑非常方便,尤其是如果您不想使用 clip.show()clip.preview()。您可以嵌入视频、图像和声音,可以来自文件或直接来自剪辑。
您还可以提供任何有效的 HTML5 选项作为关键字参数,例如指定宽度、自动播放或循环。
重要的是,ipython_display 实际上将剪辑物理嵌入到您的笔记本中。优点是您可以移动或在线发布笔记本,视频仍然可以正常播放。缺点是笔记本的文件大小可能会变得非常大,但重新启动浏览器可以解决这个问题。

使用 matplotlib

定义自定义动画

MoviePy 允许您通过定义一个函数来生成自定义动画,该函数以 numpy 数组的形式返回动画给定时间的帧。
下面是此工作流程的示例:
然后可以通过通常的 MoviePy 方式导出该动画:

简单的 matplotlib 示例

以下是使用 matplotlib 创建动画的示例:

在 Jupyter Notebook 中工作

如果您在 Jupyter Notebook 中工作,则可以利用以下事实:VideoClips 可以通过 ipython_display 方法嵌入到 Notebook 的输出单元中。
以下是上述示例在 Jupyter Notebook 中的应用:

MoviePy 中的音频

本节介绍如何使用 MoviePy 创建和编辑音频剪辑。

音频剪辑的构成

音频剪辑与 MoviePy 中的视频剪辑非常相似:它们具有长度,可以进行剪切和合成等操作。一个显著的区别是音频剪辑只包含音频部分,而视频剪辑则包含音频和视频。

创建新的音频剪辑

音频剪辑可以从音频文件或视频文件的音轨中创建。

合成音频剪辑

您可以将多个音频剪辑合成为一个剪辑,方法是使用 CompositeAudioClip

导出和预览音频剪辑

您可以将音频剪辑导出为音频文件,并在 MoviePy 中预览音频剪辑。

创建和导出视频剪辑

视频和音频剪辑是 MoviePy 的核心对象。本节将介绍不同类型的剪辑、创建它们的方法及其写入文件的方式。关于修改剪辑(剪切、效果等)的信息,请参阅“剪辑变换和效果”。要了解如何组合剪辑,请参阅“混合剪辑”;要了解如何在写入文件之前预览剪辑,请参阅“如何高效使用 MoviePy”。
以下代码总结了您可以使用 moviepy 创建的基本剪辑:

视频剪辑

音频剪辑

了解这些剪辑的最佳方式是阅读参考手册中每个剪辑的详细文档。在本节中,我们会探索如何创建剪辑(例如从视频或音频文件中获取),如何将它们混合以及如何将它们写入文件。

视频剪辑的类别

视频剪辑是较长视频的基石。从技术上讲,它们是具有 clip.get_frame(t) 方法的剪辑,该方法输出表示时间 t 的剪辑帧的 HxWx3 numpy 数组。主要有两类:动画剪辑(由 VideoFileClip 和 VideoClip 制作)和非动画剪辑,这些剪辑显示相同的图片,理论上持续时间无限长(如 ImageClip、TextClip、ColorClip)。还有特殊的视频剪辑称为遮罩剪辑,属于上述类别,但输出灰度帧,显示另一个剪辑的哪些部分可见或不可见。视频剪辑可以携带音频剪辑(其音轨)和遮罩剪辑。

VideoClip录像片段

VideoClip 是 MoviePy 中所有其他视频剪辑的基类。如果您的目的仅是编辑视频文件,则不需要使用这个类。当您希望从另一个库生成的帧制作动画时,这个类非常有用。您需要定义一个函数 make_frame(t),它返回一个 HxWx3 的 numpy 数组(8 位整数),代表时间 t 的帧。下面是使用图形库 Gizeh 的一个示例:
notion image
请注意,使用 make_frame 创建的剪辑没有明确的帧速率,因此在使用 write_gifwrite_videofile 以及任何需要遍历帧的方法时,您必须提供帧速率(fps,每秒帧数)。

VideoFileClip视频文件剪辑

VideoFileClip 是从视频文件(支持大多数格式)或 GIF 文件读取的剪辑。加载视频的方式如下:
请注意,这些剪辑将具有 fps(每秒帧数)属性,如果您对剪辑进行小的修改,该属性将被传递,并且默认会在 write_videofilewrite_gif 等方法中使用。例如:
有关更多信息,请参阅 VideoFileClip

ImageSequenceClip 图像序列剪辑

ImageSequenceClip 是由一系列图像组成的剪辑,您可以通过以下方式创建它:
其中 images_list 可以是按顺序播放的图像名称列表、文件夹名称(在这种情况下,文件夹中的所有图像文件将按字母数字顺序播放)或帧列表(Numpy 数组),例如从其他剪辑获取。
当您提供文件夹名称或文件名列表时,可以选择 load_images=True 参数来指定应将所有图像加载到 RAM 中。这种方法适用于您有少量图像且每个图像都会多次使用的情况(例如,图像形成循环动画)。

ImageClip 图像剪辑

ImageClip 是一种始终显示相同图像的视频剪辑。您可以通过以下几种方式创建:
有关更多信息,请参阅 ImageClip
下面展示的两个 ImageClip 示例是 TextClip 和 ColorClip。

TextClip 文本剪辑

生成 TextClip 需要安装 ImageMagick,并(对于 Windows 用户)需要将其链接到 MoviePy。具体安装说明请参阅官方文档。
创建文本剪辑的方法如下(您可能不需要使用所有这些选项):
字体可以是计算机上安装的任何字体,但 ImageMagick 会有特定的命名。例如,Amiri 字体通常称为 Amiri-Regular,而 Impact 字体称为 Impact-Normal。要获取可能的字体列表,可以使用 TextClip.list('font')。要查找与特定字体相关的所有字体名称,可以使用:
请注意,使用笔画(或轮廓)在小字母上效果不佳,因此如果您需要带轮廓的小文本,最好是生成大号文本后再缩小:
TextClips 提供许多选项,如对齐、字间距(字母之间的距离)、笔画大小、背景、自动换行等。更多详细信息,请参阅 TextClip

Mask clips 蒙版剪辑

蒙版是一种特殊的视频剪辑,用于指示在将带有此蒙版的视频剪辑与其他视频剪辑合成时哪些像素可见(参见混合剪辑)。当您将剪辑导出为 GIF 文件或 PNG 文件时,蒙版也用于定义透明度。
与标准剪辑不同,标准剪辑的每个像素输出包含三个分量(R-G-B),范围在 0 到 255 之间,而蒙版的每个像素只有一个分量,范围在 0 到 1 之间(1 表示像素完全可见,0 表示像素透明)。换句话说,蒙版始终是灰度的。
创建或加载将用作蒙版的剪辑时,需要如下声明:
对于视频和图像文件,如果它们原本不是黑白的,系统将自动将它们转换为黑白。
然后,您可以使用 myclip.with_mask(maskclip) 将此蒙版附加到与之尺寸相同的另一个剪辑上。
一些图像格式,如 PNG,支持带有 alpha 层的透明度,MoviePy 将使用这个 alpha 层作为蒙版:
任何视频剪辑都可以通过 clip.to_mask() 转换为蒙版,蒙版也可以通过 my_mask_clip.to_RGB() 转换为标准的 RGB 视频剪辑。
蒙版由于其帧的不同,很多方法对它们的处理也不同,但您可以对蒙版进行几乎所有标准剪辑能做的操作,如剪切、编辑、预览、写入视频文件、制作快照等。

导出视频剪辑

视频文件(.mp4、.webm、.ogv…)可以通过以下方法写入视频文件:
MoviePy 对最常见的文件扩展名有默认的编解码器名称。如果您想使用特殊格式或对默认设置不满意,可以指定编解码器,例如 codec='mpeg4'。写视频时有许多选项,如比特率、音频编写的参数、文件大小优化、使用的处理器数量等。更多详细信息,请参阅 write_videofile()
有时,MoviePy 无法猜测剪辑的持续时间属性(请记住,某些剪辑如显示图片的 ImageClip,默认具有无限持续时间)。这种情况下,必须手动设置持续时间:

GIF 动画

要将视频编写为动画 GIF,可以使用以下命令:
请注意,这需要安装 ImageMagick。如果没有安装,您也可以通过添加选项 program='ffmpeg' 使用 ffmpeg 来创建 GIF,这会更快,但效果可能不如 ImageMagick 优化得好。
编写 GIF 时,有多种选项可以优化 GIF 的质量和大小。更多详细信息,请参阅 write_gif()
编辑 GIF 的最佳方式是在笔记本中预览它们,具体方法请参考 ipython_display。您可以查看相关博客文章,了解如何从视频文件制作 GIF,以及如何制作带有矢量图形的 GIF 动画。

导出图像

您可以将帧写入图像文件,如下所示:
如果剪辑包含蒙版,蒙版将作为图像的 Alpha 层被导出,除非您指定 with_mask=False
  • 教学
  • python
  • 【error】pip error: externally-managed-environment【python】MoviePy从入门到入土(1)安装
    Loading...