隨著自媒體時代,現(xiàn)在對視頻的處理變得越來越常見。我們可以使用 Adobe 的一些專業(yè)工具,但是效率不高;如果只是對視頻進行一些簡單的處理,或者視頻的數(shù)量非常多的話,那么使用專業(yè)軟件顯然就不太適合了。 而 Python 有一個專門用于處理視頻的第三方庫:moviepy,可以非常方便地對視頻進行一些簡單處理,下面我們就來看一看。 首先是安裝: pip install moviepy -i https://pypi.tuna./simple
個人推薦安裝的時候使用清華源,因為moviepy需要依賴另一個庫:imageio_ffmpeg,這個庫里面包含了一個 50 多 MB 的 ffmpeg 二進制文件,如果網(wǎng)絡(luò)不行的話,直接從pypi上拉取會花很長時間。當(dāng)然安裝moviepy的時候,imageio_ffmpeg 就順帶安裝了。 從這里我們也可以看到,moviepy 底層依賴 ffmpeg,而ffmpeg是跨平臺的,所以 moviepy 也可以在任意平臺上使用。 我們來看 moviepy 都提供了哪些功能,不過在使用之前我們需要一個視頻,就使用 you-get 工具從 bilibili 下載一個吧。 下面就使用這個下載的視頻進行演示。 如果一個視頻比較長,我們可以截取感興趣的片段。 from moviepy import editor
# 調(diào)用 `VideoFileClip(文件名)` 即可將視頻加載進來 # 并且支持不同的視頻格式,比如 flv、mp4 等等 video_clip = editor.VideoFileClip( "空城計,但是7Ki7Ki醬醬.mp4")
# 調(diào)用subclip方法,傳入起始時間和結(jié)束時間 # 即可截取視頻中的指定部分 """ video_clip.subclip(): 截取視頻全部,相當(dāng)于沒做處理 video_clip.subclip(10): 從視頻的 `第10秒` 截取到 `結(jié)尾` video_clip.subclip(10, -2): 從視頻的 `第10秒` 截取到結(jié)尾的 `前兩秒` 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 對象 # 所以它支持鏈?zhǔn)讲僮?/span> video_clip = video_clip.subclip(30)
一個視頻,我們也可以調(diào)整它的音量。 from moviepy import editor
video_clip = editor.VideoFileClip( "空城計,但是7Ki7Ki醬醬.mp4")
# 調(diào)整音量,變?yōu)樵瓉淼?.5 # 同樣會返回一個新的對象 video_clip = video_clip.volumex(0.5)
如果你想在視頻里面寫上一些內(nèi)容,moviepy 也是支持的。 from moviepy import editor
video_clip = editor.VideoFileClip( "空城計,但是7Ki7Ki醬醬.mp4")
# 做一個文本剪貼板,自定義樣式、顏色。 text_clip = editor.TextClip("7ki7ki 棒棒", fontsize=40, color="blue") # 讓文本在屏幕的正中間顯示 # 持續(xù)10秒,設(shè)置透明度為 0.6 """ 屏幕左上角的坐標(biāo)為 (0, 0),右下角的坐標(biāo)為 (屏幕寬度, 屏幕高度) set_position((800, 500)): 顯示在800, 500的位置上 set_position(("center", "center")): 顯示在屏幕的正中央 set_position((0.4, 0.6), True): 顯示在距離左邊百分之40、距離上邊百分之60的位置上
set_duration(10): 持續(xù)10秒 set_opacity(0.6): 設(shè)置透明度為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 系統(tǒng),不出意外的話,當(dāng)你在執(zhí)行 editor.TextClip() 的時候,會報出如下錯誤: 這個錯誤是由于你的電腦上缺少 ImageMagick 造成的,我們需要去官網(wǎng)下載對應(yīng)操作系統(tǒng)的 ImageMagick。 官網(wǎng):http://www./script/download.php
下載完之后,安裝在指定的目錄,然后修改site-packages\moviepy\config_defaults.py,在文件的尾部有如下內(nèi)容: import os
FFMPEG_BINARY = os.getenv('FFMPEG_BINARY', 'ffmpeg-imageio') IMAGEMAGICK_BINARY = os.getenv('IMAGEMAGICK_BINARY', 'auto-detect')
# 把 `IMAGEMAGICK_BINARY = ` 后面的內(nèi)容 # 換成 ImageMagick 安裝路徑下 magick.exe 的絕對路徑: import os
FFMPEG_BINARY = os.getenv('FFMPEG_BINARY', 'ffmpeg-imageio') IMAGEMAGICK_BINARY = r'E:\ImageMagick-7.0.10-Q16\magick.exe'
替換完之后,再執(zhí)行就沒有問題了。 我們將上面的幾個部分,組合起來演示一下: from moviepy import editor
video_clip = editor.VideoFileClip( "空城計,但是7Ki7Ki醬醬.mp4")
video_clip = ( # 截取 5 到 20 秒 video_clip.subclip(5, 20). # 設(shè)置音量為原來的 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])
# 然后將視頻導(dǎo)出 video_clip.write_videofile("空城計,但是7Ki7Ki醬醬_2.mp4")
執(zhí)行代碼,會看到以下輸出:
表示正在調(diào)用 ffmpeg 處理視頻,而視頻處理完畢大概需要十幾秒鐘的時間。處理完畢之后,我們打開看一下。 我們看到此時文字就添加進去了,并且該視頻只有15秒,也就是我們截取的 5 到 20 秒的部分。 總結(jié)一下整個流程,首先使用 VideoFileClip 對視頻進行讀取,得到 VideoFileClip 對象,記作 video_clip。我們可以對這個 video_clip 進行任意的操作(剪切、合并、調(diào)整亮度、速度、和其它的 video_clip 拼接在一起等等)。 并且需要注意的是,這些操作是可以鏈?zhǔn)秸{(diào)用的,因為每一次操作都會得到一個新的 video_clip,不會影響原來的。我們上面演示了視頻的讀取、以及指定部分的截取、音量的調(diào)整、以及添加文字等等,下面還會介紹更多操作。 最后我們調(diào)用 video_clip 的 write_videofile 方法,可以將處理之后的視頻寫入本地。當(dāng)然也可以使用 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) # 截取結(jié)尾的前兩秒 video_clip2 = video_clip.subclip(-2) # 然后前后拼接起來 video_clip = editor.concatenate_videoclips([video_clip1, video_clip2]) # 使用jupyter進行展示,設(shè)置一個寬度 video_clip.ipython_display(width=360)
執(zhí)行完之后,視頻就展示在 jupyter 上了,而且是兩個視頻拼接在一起的,總共 12 秒鐘。此外 concatenate_videoclips 中還可以指定一個transition參數(shù)(也是一個VideoFileClip對象),作為銜接之間的過渡。 還是比較簡單的,假設(shè)我們有 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 之間有相同的尺寸、時長什么的,僅僅是將它們按照順序拼接起來而已。 另外,當(dāng)你用 jupyter 進行展示時,視頻不要過長,否則報錯。當(dāng)然你也可以給 ipython_display 函數(shù)傳遞一個 maxduration 參數(shù),讓它支持顯示更大時長的視頻文件。但是注意:如果文件過大,在 jupyter 上可能會耗光你的內(nèi)存。 然后是第二種拼接
有多個視頻,可以讓它們在同一個畫面上顯示。 from moviepy import editor
# margin: 設(shè)置外邊距 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 = ( # 調(diào)整尺寸,保持比例 video_clip.fx(editor.vfx.resize, width=460) # 倍數(shù)播放 .fx(editor.vfx.speedx, 2) # 畫面調(diào)暗 .fx(editor.vfx.colorx, 0.5) ) video_clip.ipython_display(width=600)
雖然截取了 10 秒鐘,但是 2 倍數(shù)播放,所以變成了 5 秒鐘。 假設(shè)有一個視頻 A 和一個視頻 B,現(xiàn)在要將視頻 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 """ # 如果已經(jīng)是音頻格式,那么也可以直接加載 audioB = editor.AudioFileClip("b.mp3") """
# 將 B 的音頻和 A 組合起來 video_clipA = video_clipA.set_audio(audioB)
以上就是 moviepy 的一些基本用法,通過 moviepy 可以對視頻做一些簡單的批處理。至于視頻(以及音頻)背后的原理就是一門復(fù)雜的學(xué)問了,有興趣的話可以深入研究一下,現(xiàn)在短視頻那么火,相關(guān)的技術(shù)人員也比較短缺,所以前景還是很不錯的。
|