☞ ░ 前往老猿Python博文目錄 ░
一、引言
在《moviepy音視頻剪輯:moviepy中的剪輯基類Clip詳解》介紹了剪輯基類的fl、fl_time、fx方法,在《moviepy音視頻剪輯:視頻剪輯基類VideoClip的屬性及方法詳解》介紹了fl_image和subfx方法,
在《Python+moviepy音視頻剪輯:視頻幀數據的本質、Clip的fl方法進行變換處理的原理以及滾屏案例》及《moviepy音視頻剪輯:使用fl_time進行諸如快播、慢播、倒序播放等時間特效處理的原理和可能遇到的坑》分別介紹了fl和fl_time進行視頻剪輯變換的原理及使用方法。
實際上moviepy所有視頻變換的方法都是以Clip的fl方法為基礎衍生出來的,最后都會調用到fl方法實施真正的變換,只是變換處理的邏輯由上次方法提供,如fl_time就是針對剪輯的時間線進行變換、fl_image就是針對剪輯的內容進行變換,開發者也可以根據自己的需要實現自己的變換方法。
為了支持一些常規的變換處理,moviepy提供了一系列常用的變換函數,開發者可以直接使用這些方法進行變換,這些函數都在moviepy.video.fx包下,基本上一個函數就是一個文件,在moviepy.editor通過import moviepy.video.fx.all as vfx
中將這些函數都加載到了vfx模塊下,可以直接通過vfx.函數名方式調用,也可以通過VideoClip類+函數名直接調用,這是因為在moviepy.editor執行錄入如下語句:
for method in [
"afx.audio_fadein",
"afx.audio_fadeout",
"afx.audio_normalize",
"afx.volumex",
"transfx.crossfadein",
"transfx.crossfadeout",
"vfx.crop",
"vfx.fadein",
"vfx.fadeout",
"vfx.invert_colors",
"vfx.loop",
"vfx.margin",
"vfx.mask_and",
"vfx.mask_or",
"vfx.resize",
"vfx.rotate",
"vfx.speedx",
]:
exec("VideoClip.%s = %s" % (method.split(".")[1], method))
將這些函數動態賦值給了VideoClip的同名實例變量,但這些實例變量是在moviepy.editor中定義的,因此在VideoClip的派生子類中不能這樣使用。
這些函數的調用可以通過Clip的fx方法和VideoClip的subfx方法進行調用,具體調用語法請參考上面介紹的博文內容。
由於變換函數比較多,老猿將其以自己的標准分為了大小變換、時間變換、顏色變換、內容變換四個部分分別介紹,這種分法不一定非常對,比如有些部分的變換可能既和時間相關又和內容相關,兩個歸類都可以,大家就不必深究了。
本文主要介紹和剪輯大小相關的變換函數,包括crop、even_size、margin和resize。
二、crop函數
crop函數從剪輯中獲取一個矩形區域的剪輯內容作為新的剪輯。
調用語法:
crop( clip, x1=None, y1=None, x2=None, y2=None, width=None, height=None, x_center=None, y_center=None)
參數:
- x1、y1:代表矩形區域左上角坐標
- x2、y2:代表矩形區域右下角坐標
- width、height:是寬度和高度
- x_center、y_center:表示x1的坐標為x_center-width/2,x2的坐標為x_center+width/2,y_center類似處理
數據計算邏輯
下面以橫坐標系數據為例來說明矩形位置坐標(單位:像素)的計算邏輯:
- 橫坐標系數據 x1、x2、width只要出現任意2個就能算出另外1個
- x_center如果出現,則可以計算出x1和x2
- 如果 x1、x2、width只出現1個或者都未出現,則x1、x2其中未出現的則取原剪輯的左上角或右下角的橫坐標,因此單獨出現width沒有意義
以上計算過程是有順序的,只有前面的不滿足才會執行后面的。縱坐標系數據同樣如此。
案例:
if __name__=='__main__':
threads = 8
clipVideo = VideoFileClip(r"F:\video\WinBasedWorkHard_src.mp4").fx(vfx.crop,0,260)
clipVideo.write_videofile(r"F:\video\crop.mp4", threads=threads)
clipVideo.close()
原剪輯和執行代碼后存儲剪輯對應幀圖像對比:
上圖中左邊為原視頻的幀圖像,右邊為上述代碼執行后視頻幀的圖像。
三、even_size函數
even_size函數是將剪輯的寬和高變成偶數,如果這兩個值有為奇數的,則剪輯的幀在丟棄一行或一列像素。這是因為ffmpeg編碼規則要求寬和高必須是偶數,相當於一個糾錯處理的函數,並沒有實際處理的意義。其調用參數就是一個clip。
四、margin函數
margin函數在剪輯的四周增加一個外邊框。
調用語法如下:
margin(clip, mar=None, left=0, right=0, top=0, bottom=0, color=(0, 0, 0), opacity = 1.0)
說明:
- mar:外邊框的寬度,以像素為單位,如果mar指定了有效值,則 left、right、top、bottom設定值不起作用
- left、right、top、bottom:邊框左、右、頂和底的寬度
- color:邊框顏色
- opacity :邊框的不透明度,如果為0表示完全透明,1則完全不透明
增加邊框的剪輯,其寬度和高度都會相應增加,因此剪輯大小會變大。
案例:
if __name__== '__main__':
threads = 8
clip = VideoFileClip(r"F:\video\WinBasedWorkHard_src.mp4").crop(0, 300, 540, 660)
newclip = clip.fx(vfx.margin, 3, color=(0, 0, 255), opacity=0.5)
newclip.write_videofile(r"F:\video\WinBasedWorkHard_margin.mp4", threads=threads)
視頻效果:
五、resize函數
resize函數用於調整剪輯的大小,包括縮小或放大。
調用語法:resize(clip, newsize=None, height=None, width=None, apply_to_mask=True)
說明:
- 使用resize必須先安裝了OpenCV、Scipy或PIL圖像處理模塊中的一個,否則不能使用
- newsize可以是返回新剪輯的寬和高二元組,也可以是大小變化的比例如0.5或2,還可以是一個和剪輯幀時間t相關的函數來返回前面2種值中的一個
- width、height:剪輯的寬或高,二者指定一個,另一個會自動計算
六、小結
本文主要介紹和剪輯大小相關的變換函數,包括crop、even_size、margin和resize,相關的函數會在原剪輯大小的基礎上進行大小變化,包括裁取其中一部分、給剪輯增加邊框和調整剪輯大小等,返回新剪輯。
更多moviepy的介紹請參考《PyQt+moviepy音視頻剪輯實戰文章目錄》或《moviepy音視頻開發專欄》。
關於收費專欄
老猿的付費專欄《使用PyQt開發圖形界面Python應用》專門介紹基於Python的PyQt圖形界面開發基礎教程,付費專欄《moviepy音視頻開發專欄》詳細介紹moviepy音視頻剪輯合成處理的類相關方法及使用相關方法進行相關剪輯合成場景的處理,兩個專欄加起來只需要19.9元,都適合有一定Python基礎但無相關專利知識的小白讀者學習。這2個收費專欄都有對應免費專欄,只是收費專欄的文章介紹更具體、內容更深入、案例更多。
收費專欄文章目錄:《moviepy音視頻開發專欄文章目錄》、《使用PyQt開發圖形界面Python應用專欄目錄》,本文收費專欄對應文章為《moviepy音視頻剪輯:與大小相關的視頻變換函數詳解》。
對於缺乏Python基礎的同仁,可以通過老猿的免費專欄《專欄:Python基礎教程目錄》從零開始學習Python。
如果有興趣也願意支持老猿的讀者,歡迎購買付費專欄。