如何用 Python 做視頻自動化剪輯?
來源:古明地覺的編程教室
隨着自媒體時代,現在對視頻的處理變得越來越常見。我們可以使用 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(5, 20).
# 設置音量爲原來的 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.70713996887207
"""
視頻合成
視頻合成有兩種方式:
1)多個視頻按照先後順序拼接起來,比如一個一分鐘和一個兩分鐘的視頻組合起來,變成三分鐘。
2)多個視頻在同一個畫面上顯示。
先來看看第一種:
from moviepy import editor
video_clip = editor.VideoFileClip(r"D:\satori\空城計,但是7Ki7Ki醬醬.mp4")
# 截取10到20秒
video_clip1 = video_clip.subclip(10, 20)
# 截取結尾的前兩秒
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(10, 20)
# 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(10, 20)
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 可以對視頻做一些簡單的批處理。至於視頻(以及音頻)背後的原理就是一門複雜的學問了,有興趣的話可以深入研究一下,現在短視頻那麼火,相關的技術人員也比較短缺,所以前景還是很不錯的。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/CDumuJU7H0rdpKdcPSQVbg