社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

如何用 Python 做视频自动化剪辑?

Python猫 • 1 年前 • 224 次点击  

来源:古明地觉的编程教室

随着自媒体时代,现在对视频的处理变得越来越常见。我们可以使用 Adobe 的一些专业工具,但是效率不高;如果只是对视频进行一些简单的处理,或者视频的数量非常多的话,那么使用专业软件显然就不太适合了。

而 Python 有一个专门用于处理视频的第三方库:moviepy,可以非常方便地对视频进行一些简单处理,下面我们就来看一看。

首先是安装:

pip install moviepy -i https://pypi.tuna.tsinghua.edu.cn/simple

个人推荐安装的时候使用清华源,因为moviepy需要依赖另一个库:imageio_ffmpeg,这个库里面包含了一个 50 多 MB 的 ffmpeg 二进制文件,如果网络不行的话,直接从pypi上拉取会花很长时间。当然安装moviepy的时候,imageio_ffmpeg 就顺带安装了。

从这里我们也可以看到,moviepy 底层依赖 ffmpeg,而ffmpeg是跨平台的,所以 moviepy 也可以在任意平台上使用。



moviepy 的简单使用




我们来看 moviepy 都提供了哪些功能,不过在使用之前我们需要一个视频,就使用 you-get 工具从 bilibili 下载一个吧。

下面就使用这个下载的视频进行演示。

视频截取

如果一个视频比较长,我们可以截取感兴趣的片段。

from moviepy import editor

# 调用 `VideoFileClip(文件名)` 即可将视频加载进来
# 并且支持不同的视频格式,比如 flv、mp4 等等
video_clip = editor.VideoFileClip(
    "空城计,但是7Ki7Ki酱酱.mp4")

# 调用subclip方法,传入起始时间和结束时间
# 即可截取视频中的指定部分
"""
video_clip.subclip(): 
   截取视频全部,相当于没做处理
video_clip.subclip(10): 
   从视频的 `第10秒` 截取到 `结尾`
video_clip.subclip(10, -2): 
   从视频的 `第10秒` 截取到结尾的 `前两秒`
video_clip.subclip((1, 35), (3, 10)): 
   从视频的 `第1分35秒` 截取到 `第3分10秒` 
video_clip.subclip((1, 2, 18), (2, 1, 34)): 
   从视频的 `第1小时2分18秒` 截取到 `第2小时1分34秒`
"""


# subclip 会返回一个新的 VideoFileClip 对象
# 所以它支持链式操作
video_clip = video_clip.subclip(30)


音量调整

一个视频,我们也可以调整它的音量。

from moviepy import editor

video_clip = editor.VideoFileClip(
    "空城计,但是7Ki7Ki酱酱.mp4")

# 调整音量,变为原来的0.5
# 同样会返回一个新的对象
video_clip = video_clip.volumex(0.5)


在视频上添加文字

如果你想在视频里面写上一些内容,moviepy 也是支持的。

from moviepy import editor

video_clip = editor.VideoFileClip(
    "空城计,但是7Ki7Ki酱酱.mp4")

# 做一个文本剪贴板,自定义样式、颜色。
text_clip = editor.TextClip("7ki7ki 棒棒",
                            fontsize=40, color="blue")
# 让文本在屏幕的正中间显示
# 持续10秒,设置透明度为 0.6
"""
屏幕左上角的坐标为 (0, 0),右下角的坐标为 (屏幕宽度, 屏幕高度)
set_position((800, 500)): 
    显示在800, 500的位置上
set_position(("center", "center")): 
    显示在屏幕的正中央
set_position((0.4, 0.6), True): 
    显示在距离左边百分之40、距离上边百分之60的位置上

set_duration(10): 持续10秒
set_opacity(0.6): 设置透明度为0.6
"""


text_clip = text_clip.set_position(("center""center")).\
    set_duration(10).set_opacity(0.8)

# 然后把 `文本剪贴板` 贴在视频上
video_clip = editor.CompositeVideoClip([video_clip, text_clip])

如果你是 Windows 系统,不出意外的话,当你在执行 editor.TextClip() 的时候,会报出如下错误:


这个错误是由于你的电脑上缺少 ImageMagick 造成的,我们需要去官网下载对应操作系统的 ImageMagick。

官网:http://www.imagemagick.org/script/download.php

下载完之后,安装在指定的目录,然后修改site-packages\moviepy\config_defaults.py,在文件的尾部有如下内容:

import os

FFMPEG_BINARY = os.getenv('FFMPEG_BINARY''ffmpeg-imageio')
IMAGEMAGICK_BINARY = os.getenv('IMAGEMAGICK_BINARY''auto-detect')

# 把 `IMAGEMAGICK_BINARY = ` 后面的内容
# 换成 ImageMagick 安装路径下 magick.exe 的绝对路径:
import os

FFMPEG_BINARY = os.getenv('FFMPEG_BINARY''ffmpeg-imageio')
IMAGEMAGICK_BINARY = r'E:\ImageMagick-7.0.10-Q16\magick.exe'

替换完之后,再执行就没有问题了。

我们将上面的几个部分,组合起来演示一下:

from moviepy import editor

video_clip = editor.VideoFileClip(
    "空城计,但是7Ki7Ki酱酱.mp4")

video_clip = (
    # 截取 5 到 20 秒
    video_clip.subclip(520).
    # 设置音量为原来的 0.8
    volumex(0.8)
)

text_clip = (
    editor.TextClip("7ki7ki",
                   fontsize=40, color="blue").
    set_position(("center""center")).
    set_duration(10).
    set_opacity(0.8)
)

# 把 `文本剪贴板` 贴在视频上
video_clip = editor.CompositeVideoClip([video_clip, text_clip])

# 然后将视频导出
video_clip.write_videofile("空城计,但是7Ki7Ki酱酱_2.mp4")

执行代码,会看到以下输出:


表示正在调用 ffmpeg 处理视频,而视频处理完毕大概需要十几秒钟的时间。处理完毕之后,我们打开看一下。


我们看到此时文字就添加进去了,并且该视频只有15秒,也就是我们截取的 5 到 20 秒的部分。

总结一下整个流程,首先使用 VideoFileClip 对视频进行读取,得到 VideoFileClip 对象,记作 video_clip。我们可以对这个 video_clip 进行任意的操作(剪切、合并、调整亮度、速度、和其它的 video_clip 拼接在一起等等)。

并且需要注意的是,这些操作是可以链式调用的,因为每一次操作都会得到一个新的 video_clip,不会影响原来的。我们上面演示了视频的读取、以及指定部分的截取、音量的调整、以及添加文字等等,下面还会介绍更多操作。

最后我们调用 video_clip 的 write_videofile 方法,可以将处理之后的视频写入本地。当然也可以使用 pygame,或者 jupyter notebook 进行展示。为了方便,我们后面就使用 jupyter notebook。

但是要清楚,moviepy 处理视频使用的是 ffmpeg,生成文字使用的是 ImageMagick。



获取视频属性




一个视频,肯定有大小、宽高、fps、时长等属性,那么 moviepy 要如何获取这些属性呢。

from moviepy import editor

video_clip = editor.VideoFileClip(r"空城计,但是7Ki7Ki酱酱.mp4")
# 获取宽度和高度
print(video_clip.size)
print(video_clip.w, video_clip.h)
"""
[2160, 1080]
2160 1080
"""


# 获取 fps
print(video_clip.fps)
"""
30.0
"""


# 获取时长,单位是秒
print(video_clip.duration)
"""
110.92
"""


# 获取大小,可以直接使用 os 模块
import os
# 大概 13MB
size = os.stat(r"空城计,但是7Ki7Ki酱酱.mp4").st_size
print(size)
print(size / 1024 ** 2)
"""
13324402
12.70713996887
207
"""



视频合成




视频合成有两种方式:

1)多个视频按照先后顺序拼接起来,比如一个一分钟和一个两分钟的视频组合起来,变成三分钟。

2)多个视频在同一个画面上显示。

先来看看第一种:

from moviepy import editor
video_clip = editor.VideoFileClip(r"D:\satori\空城计,但是7Ki7Ki酱酱.mp4")

# 截取10到20秒
video_clip1 = video_clip.subclip(1020)
# 截取结尾的前两秒
video_clip2 = video_clip.subclip(-2)
# 然后前后拼接起来
video_clip = editor.concatenate_videoclips([video_clip1, video_clip2])
# 使用jupyter进行展示,设置一个宽度
video_clip.ipython_display(width=360)

执行完之后,视频就展示在 jupyter 上了,而且是两个视频拼接在一起的,总共 12 秒钟。此外 concatenate_videoclips 中还可以指定一个transition参数(也是一个VideoFileClip对象),作为衔接之间的过渡。

还是比较简单的,假设我们有 5 个视频,如果只是简单的前后拼接就可以这么做。

from moviepy import editor

videos = ["1.mp4""2.mp4""3.flv",
          "4.mp4""5.flv"]
video_clips = []

for video in videos:
    video_clips.append(editor.VideoFileClip(video))

editor.concatenate_videoclips(
    video_clips).write_videofile("xxx.mp4")

这里值得一提的是,多个 video_clip 进行拼接,并不需要这些 video_clip 之间有相同的尺寸、时长什么的,仅仅是将它们按照顺序拼接起来而已。

另外,当你用 jupyter 进行展示时,视频不要过长,否则报错。当然你也可以给 ipython_display 函数传递一个 maxduration 参数,让它支持显示更大时长的视频文件。但是注意:如果文件过大,在 jupyter 上可能会耗光你的内存。

然后是第二种拼接

有多个视频,可以让它们在同一个画面上显示。

from moviepy import editor

# margin: 设置外边距
video_clip = editor.VideoFileClip(
    r"D:\satori\空城计,但是7Ki7Ki酱酱.mp4").margin(10)

# 截取 10 到 20 秒
video_clip1 = video_clip.subclip(1020)
# x 轴镜像
video_clip2 = video_clip1.fx(editor.vfx.mirror_x)
# y 轴镜像
video_clip3 = video_clip1.fx(editor.vfx.mirror_y)
# resize: 等比缩放
video_clip4 = video_clip1.resize(0.5)

# 列表里面有两个列表,所以会将屏幕上下等分
# 上半部分显示 video_clip1, video_clip2
# 下半部分显示video_clip3, video_clip4
video_clip = editor.clips_array([[video_clip1, video_clip2],
                            [video_clip3, video_clip4]])
video_clip.ipython_display(width=600)


所以 concatenate_videoclips 是将多个视频前后拼接,而 clips_array 则是将多个视频同时显示在一个画面里面。



修改视频属性




from moviepy import editor

video_clip = editor.VideoFileClip(
    r"D:\satori\空城计,但是7Ki7Ki酱酱.mp4" ).subclip(1020)

video_clip = (
    # 调整尺寸,保持比例
    video_clip.fx(editor.vfx.resize, width=460)
        # 倍数播放
        .fx(editor.vfx.speedx, 2)
        # 画面调暗
        .fx(editor.vfx.colorx, 0.5)
)
video_clip.ipython_display(width=600)

虽然截取了 10 秒钟,但是 2 倍数播放,所以变成了 5 秒钟。



视频音频合成




假设有一个视频 A 和一个视频 B,现在要将视频 B 的音频和视频 A 组合起来,怎么做呢?

from moviepy import editor

video_clipA = editor.VideoFileClip(r"A.mp4")
video_clipB = editor.VideoFileClip(r"B.mp4")

# 获取 B 的音频
audioB = video_clipB.audio
"""
# 如果已经是音频格式,那么也可以直接加载
audioB = editor.AudioFileClip("b.mp3")
"""


# 将 B 的音频和 A 组合起来
video_clipA = video_clipA.set_audio(audioB)




小结




以上就是 moviepy 的一些基本用法,通过 moviepy 可以对视频做一些简单的批处理。至于视频(以及音频)背后的原理就是一门复杂的学问了,有兴趣的话可以深入研究下,现在短视频那么火,相关的技术人员也比较短缺,所以前景还是很不错的。

Python猫技术交流群开放啦!群里既有国内一二线大厂在职员工,也有国内外高校在读学生,既有十多年码龄的编程老鸟,也有中小学刚刚入门的新人,学习氛围良好!想入群的同学,请在公号内回复『交流群』,获取猫哥的微信(谢绝广告党,非诚勿扰!)~


还不过瘾?试试它们




2022 年 Python “十级”试题(全国卷A)

最新开源:高效的 Python 通用对象池化库

Python猫 2021 文章小结,翻译竟比原创多!

Python 官方研讨会:彻底移除 GIL 真的可行么?

神器 pypandoc —— 实现电子书自由

Python进阶:探秘描述符的工作原理


如果你觉得本文有帮助
请慷慨分享点赞,感谢啦
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/146521
 
224 次点击