先用 Python 寫支程式到 YouTube 下載李飛飛 TED 演講的影片(How we teach computers to understand pictures)。將下載的影片命名為 Video.mp4 (影片解析度為 1280x720,長度為 18:02),並儲存於工作目錄。
安裝 ffmpeg 套件 (此時版本為 4.1)
conda install ffmpeg -c conda-forge
安裝 moviepy 套件 (此時版本為 0.2.3.5)
pip install moviepy
第一版程式-使用 ffmpeg_extract_subclip 剪輯
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
t1 = 50
t2 = 100
ffmpeg_extract_subclip('C:\Temp\Video.mp4', t1, t2, targetname='C:\Temp\Video Clip 1.mp4')
t1 = 100
t2 = 150
ffmpeg_extract_subclip('C:\Temp\Video.mp4', t1, t2, targetname='C:\Temp\Video Clip 2.mp4')
程式執行後會將下載的 Video.mp4 剪輯出 Video Clip 1.mp4 (50s-100s) 與 Video Clip 2.mp4 (100s-150s) 兩段影片。
Video Clip 1.mp4 (50s-100s)
**********************************************************************************************************************
第二版程式-使用 VideoFileClip 剪輯
from moviepy.video.io.VideoFileClip import VideoFileClip
t1 = 50
t2 = 100
input_video = 'C:\Temp\Video.mp4'
output_video = 'C:\Temp\Video Clip 1.mp4'
with VideoFileClip(input_video) as video:
video_clip = video.subclip(t1, t2)
video_clip.write_videofile(output_video, audio_codec='aac')
t1 = 100
t2 = 150
input_video = 'C:\Temp\Video.mp4'
output_video = 'C:\Temp\Video Clip 2.mp4'
with VideoFileClip(input_video) as video:
video_clip = video.subclip(t1, t2)
video_clip.write_videofile(output_video, audio_codec='aac')
程式執行後一樣會將下載的 Video.mp4 剪輯出 Video Clip 1.mp4 (50s-100s) 與 Video Clip 2.mp4 (100s-150s) 兩段影片。
Video Clip 1.mp4 (50s-100s)
從畫面截圖可以看出兩個版本的程式會有些微的時間差。仔細比對,第二版的程式時間比較準;可是第一版的執行速度非常快。
**********************************************************************************************************************
有時候只是想聽演講內容,而不需要畫面,這時用 mp3 會方便很多。
第三版程式-使用 ffmpeg_extract_audio 擷取聲音
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_audio
ffmpeg_extract_audio('C:\Temp\Video.mp4', 'C:\Temp\Audio.mp3', bitrate=3000, fps=44100)
**********************************************************************************************************************
第四版程式-使用 AudioFileClip 擷取聲音
from moviepy.audio.io.AudioFileClip import AudioFileClip
audio_clip = AudioFileClip('C:\Temp\Video.mp4')
audio_clip.write_audiofile('C:\Temp\Audio.mp3')
# 預設 fps=44100,bitrate='3000k'
原始長度為 18:02 的影片,在相同的 bit rate 與 fps 下,第三版的程式擷取出來的聲音檔長度為 18:02,與影片長度一致;但第四版的程式擷取出來的聲音檔長度卻為 18:30,還好聲音聽起來感覺不出延遲。
**********************************************************************************************************************
第五版程式-使用 concatenate_videoclips 串接影片
from moviepy.editor import VideoFileClip, concatenate_videoclips
clip1 = VideoFileClip('C:\Temp\Video.mp4').subclip(50, 100)
clip2 = VideoFileClip('C:\Temp\Video.mp4').subclip(100, 150)
final_clip = concatenate_videoclips([clip1, clip2])
final_clip.write_videofile('C:\Temp\Video Clip.mp4')
# 如未指定 write_videofile 的 audio_codec 參數,預設是 mp3
程式執行後會將 Video.mp4 (50s-100s) 與 Video.mp4 (100s-150s) 兩段影片串接成 Video Clip.mp4 (0s-100s)。
Video Clip.mp4 (0s)
**********************************************************************************************************************
第六版程式-使用 clips_array 與 vfx 堆疊特效影片
from moviepy.editor import VideoFileClip, clips_array, vfx
clip1 = VideoFileClip('C:\Temp\Video.mp4').subclip(50, 100).margin(10)
clip2 = clip1.fx(vfx.mirror_x)
clip3 = clip1.fx(vfx.mirror_y)
clip4 = clip1.resize(0.60)
final_clip = clips_array([[clip1, clip2], [clip3, clip4]])
final_clip.resize(width=1280).write_videofile('C:\Temp\Video vfx Clip.mp4')
# clip1 增加 10 個像素的黑邊,clip2 對 x 軸鏡射,clip3 對 y 軸鏡射,clip4 縮小 60%
# 調整輸出影片解析度寬為 1280
程式執行後會將 Video.mp4 (50s-100s) 影片經過四次 vfx 特效處理後,堆疊成 Video vfx Clip.mp4 (0s-50s)。
Video vfx Clip.mp4 (0s-50s)
**********************************************************************************************************************
第七版程式-製作 GIF 影片
from moviepy.editor import VideoFileClip
clip = VideoFileClip('C:\Temp\Video.mp4').subclip(50, 52)
final_clip = clip.resize(0.50)
final_clip.write_gif('C:\Temp\Video Clip.gif')
**********************************************************************************************************************
在各個程式版本之間,我故意使用不同的語法與應用方式,做測試也留下筆記,尤其是在第二版中使用了 with-as statement。為了處理檔案讀取過程中發生的例外,並且確定最後檔案一定會關閉,一般會使用 try-except-finally statement,而在 Python 3 (或 2.6) 中,可以使用 wit-as statement 來簡化程式的撰寫。
使用 try-except-finally statement
from moviepy.video.io.VideoFileClip import VideoFileClip
t1 = 50
t2 = 100
input_video = 'C:\Temp\Video.mp4'
output_video = 'C:\Temp\Video Clip 1.mp4'
video = VideoFileClip(input_video)
try:
video_clip = video.subclip(t1, t2)
video_clip.write_videofile(output_video, audio_codec='aac')
except:
print('讀取檔案發生錯誤')
finally:
video.close()
使用 wit-as statement
from moviepy.video.io.VideoFileClip import VideoFileClip
t1 = 50
t2 = 100
input_video = 'C:\Temp\Video.mp4'
output_video = 'C:\Temp\Video Clip 1.mp4'
with VideoFileClip(input_video) as video:
video_clip = video.subclip(t1, t2)
video_clip.write_videofile(output_video, audio_codec='aac')
with 之後的運算式傳回的物件,可以使用 as 指定給變數來參考,在上面的例子中,video 所參考到的物件,最後會被自動關閉,即使在 with-as 的區塊中發生了例外,最後還是一定會關閉 video 所參考的物件。
您好,我在執行VideoFileClip的resize時候,他說VideoFileClip has no "resize" member, 不知道您是用哪一版的moviepy呢? 感謝
回覆刪除不好意思,我看到您的版本了,我更新一下我的moviepy
刪除