moviepy音視頻剪輯:與time時間線相關的變換函數freeze_region、make_loopable、speedx、time_mirror、time_symmetrize介紹

☞ ░ 前往老猿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方法進行調用,具體調用語法請參考上面介紹的博文內容。

由於變換函數比較多,老猿將其以自己的標準分爲了大小變換、時間變換、顏色變換、內容變換四個部分分別介紹,這種分法不一定非常對,比如有些部分的變換可能既和時間相關又和內容相關,兩個歸類都可以,大家就不必深究了。

本文主要介紹和剪輯時間線相關的變換函數。

二、freeze函數

freeze函數用於將指定時刻位置的幀延時顯示freeze_duration秒,剪輯的整體時長也增加了freeze_duration秒。

調用語法:

freeze(clip, t=0, freeze_duration=None, total_duration=None, padding_end=0)

參數說明:
  • t、padding_end:t爲剪輯凍結位置的時間位置,一般爲浮點數,單位爲秒,但如果t的值爲字符串‘end’,則t=剪輯的時長-padding_end-1
  • freeze_duration:該幀持續顯示的時間,浮點數,單位秒
  • total_duration:爲新剪輯的duration,實際凍結時間freeze_duration=total_duration-原剪輯的duration

三、freeze_region函數

功能說明:

freeze_region函數主要用於將剪輯中指定屏幕範圍內容固定爲參數指定的某個時刻的內容,它包括三種形式的設定:

  • 將剪輯中參數矩形指定的範圍固定爲指定時刻該剪輯的幀在該矩形內的範圍
  • 將剪輯中除了參數矩形指定的範圍是正常播放外,其他部分固定爲指定時刻的內容
  • 將剪輯中參數指定時刻的幀加遮罩後與正常剪輯剪輯疊加
調用語法:freeze_region(clip, t=0, region=None, outside_region=None, mask=None)
參數說明:
  • t:t爲在剪輯中要固定顯示內容對應在剪輯中的時刻,即freeze_region函數是將剪輯中t時刻對應的屏幕顯示中參數指定區域的內容固定顯示在剪輯所有時刻的對應屏幕位置
  • region:取t時刻region對應矩形的屏幕內容作爲固定顯示內容,矩形是一個四元組 (x1, y1, x2, y2),分別指定矩形的左上角和右下角
  • outside_region:取t時刻outside_region對應矩形外的屏幕內容作爲固定顯示內容,矩形是一個四元組 (x1, y1, x2, y2),分別指定矩形的左上角和右下角,即正常播放內容是outside_region指定區域的內容,其他區域固定爲t時刻的內容
  • mask:將t時刻對應屏幕的內容構建一個固定畫面的剪輯後,將該剪輯的mask設置爲參數mask指定的遮罩後,將該剪輯與原剪輯合成疊加播放
  • 參數region、outside_region、mask是有優先級的,三者中前面的如果出現了後面的不起作用

四、loop函數

loop函數將當前剪輯重複n次或無限循環。

調用語法:loop(self, n=None, duration=None)
說明:
  • 如果n有值則重複n次
  • 如果n和duration都有值,則剪輯重複n次後的時長被設置爲duration
  • 如果n爲None,duration有值,則剪輯的時長被強制值爲duration,如果duration比原剪輯duration大,則會重複原剪輯的內容
  • 如果n和duration都爲None,則剪輯無限制循環。

五、make_loopable函數

make_loopable使剪輯在它自己的末端逐漸淡入,這樣它就可以使用loop進行循環處理時過渡比較好。

調用語法:make_loopable(clip, cross)

參數cross是淡入的持續時間(秒)。

處理邏輯說明:

具體處理時,將剪輯clip的拷貝從duration-cross時開始進行淡入處理得到的新剪輯與原剪輯在duration-cross時疊加,最後剪輯的時長保留爲原剪輯的時長。

上述處理後,原剪輯從duration-cross開始會淡入到剪輯的開頭。

示例代碼:
if __name__=='__main__':
    threads = 8
    clip = VideoFileClip(r"F:\video\WinBasedWorkHard_src.mp4").subclip(0, 10)

    newclip = clip.fx(vfx.make_loopable, 3).set_fps(clip.fps)
    newclip.write_videofile(r"F:\video\WinBasedWorkHard_loopable.mp4", threads=threads)

六、speedx函數

speedx函數返回的剪輯的播放速度是原剪輯的n倍,n爲相關參數指定或計算得出。

調用語法:speedx(clip, factor=None, final_duration=None)

speedx函數很簡單,就三個參數,clip爲原剪輯,factor爲需要達到的倍數,final_duration爲新剪輯的最終播放時長。factor和final_duration只要有一個存在有效值就可以,如果二者都存在或者僅final_duration存在有效值,則factor值被置爲原剪輯的時長除以final_duration的值。如果原剪輯的duration存在有效值,新剪輯的時長設置爲clip.duration/factor。

案例:
if __name__=='__main__':
    clip = VideoFileClip(r"F:\video\WinBasedWorkHard_src.mp4", audio=False).crop(0, 300, 540, 840).subclip(0, 10)
    newclip = clip.speedx(2)
    newclip.write_videofile(r"F:\video\WinBasedWorkHard_speedx.mp4", threads=8)

以上代碼輸出的視頻的播放速度是原剪輯的2倍。

七、time_mirror函數

time_mirror函數返回原剪輯的一個倒序播放剪輯,該函數只帶一個clip參數。

案例:
if __name__=='__main__':
    clip = VideoFileClip(r"F:\video\WinBasedWorkHard_src.mp4", audio=False).fx(vfx.crop,0, 300, 540, 840).subclip(0, 10)
    newclip = clip.fx(vfx.time_mirror)
    newclip.write_videofile(r"F:\video\WinBasedWorkHard_time_mirror.mp4", threads=8)
注意:
  1. 該函數會同時對剪輯的遮罩和音頻生效;
  2. 經老猿驗證測試,moviepy 1.03版本中該函數處理效率大大低於moviepy 2.0.0Dev1版本,但moviepy 2.0.0Dev1版本在處理到最後時存在BUG,老猿已經在GitHub的moviepy項目中上報,應該會很快解決。

八、time_symmetrize函數

time_symmetrize函數將當前調用剪輯進行處理後,返回一個調用剪輯和調用剪輯倒序播放的剪輯的拼接剪輯,該剪輯前半部分爲調用剪輯的內容,後半部分爲調用剪輯的倒序播放的剪輯。這種處理方法能使得剪輯能構成循環播放,在製作動畫時非常有用。該函數同步作用於剪輯的遮罩和音頻。該函數只帶一個clip參數。

案例:
if __name__=='__main__':
    clip = VideoFileClip(r"F:\video\WinBasedWorkHard_src.mp4", audio=False).fx(vfx.crop,0, 300, 540, 840).subclip(0,10)
    newclip = clip.fx(vfx.time_symmetrize)
    newclip.write_videofile(r"F:\video\WinBasedWorkHard_time_symmetrize.mp4", threads=8)

九、小結

本節詳細介紹了moviepy提供的與時間線相關的變換函數,這些函數本質上是調用fl_time函數完成變換的,只是提供了一些更典型場景的時間線變換處理函數,有了這些經典時間線變換場景支持的函數,開發者可以更快的實現諸如倍速、倒序、循環播放等基本的時間特效。

更多moviepy的介紹請參考《PyQt+moviepy音視頻剪輯實戰文章目錄》或《專欄:使用PyQt開發圖形界面Python應用》。

廣告

老猿關於PyQt的付費專欄《使用PyQt開發圖形界面Python應用》只需要9.9元(老猿正在考慮是否調整專欄價格,如果調整價格至少是19.9元),本專欄《PyQt+moviepy音視頻剪輯實戰》文檔的同樣內容在付費專欄上也有相應內容,總體來說付費專欄介紹更詳細或案例更多。

本節內容對應付費專欄的《moviepy音視頻剪輯:與time時間線相關的變換函數freeze_region、make_loopable、speedx、time_mirror、time_symmetrize詳解及使用案例》。如果有興趣也願意支持老猿的讀者,歡迎購買付費專欄。

跟老猿學Python、學5G!

☞ ░ 前往老猿Python博文目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章