通過Python將MP4視頻轉(zhuǎn)換為GIF動畫
Python 可用于讀取常見的 MP4 視頻格式并將其轉(zhuǎn)換為 GIF動畫。當(dāng)然,如果你愿意,你可以使用預(yù)先構(gòu)建的軟件,但是自己做很有趣(并且是一種很好的學(xué)習(xí)體驗)。
在本教程中,你將學(xué)習(xí)以下內(nèi)容:
- 如何從 MP4 視頻中提取幀
- 將幀轉(zhuǎn)換為 GIF
- 創(chuàng)建 MP4 到 GIF GUI
讓我們開始吧!
運行環(huán)境
你需要安裝 OpenCV 綁定以讀取 MP4 文件并將視頻中的每一幀轉(zhuǎn)換為 JPG 文件。安裝教程:
python3 -m pip install opencv-python
你還需要Pillow從你從視頻中提取的 JPG 創(chuàng)建動畫 GIF。也可以用pip安裝:
python3 -m pip install Pillow
要創(chuàng)建 GUI,我這里會用到PySimpleGUI。要安裝該庫,請使用以下命令:
python3 -m pip install PySimpleGUI
如果你使用的是 Anaconda,則包含 opencv-python 和 Pillow。你只需要單獨安裝 PySimpleGUI。
如何從 MP4 視頻中提取幀
從 MP4 視頻中提取幀的第一步是找到要轉(zhuǎn)換為 GIF 的視頻。
要從上面的視頻中提取單個幀,你需要編寫一些 Python。創(chuàng)建一個新文件并將其命名為mp4_converter.py。然后輸入以下代碼:
import cv2
def convert_mp4_to_jpgs(path):
video_capture = cv2.VideoCapture(path)
still_reading, image = video_capture.read()
frame_count = 0
while still_reading:
cv2.imwrite(f"output/frame_{frame_count:03d}.jpg", image)
# read next image
still_reading, image = video_capture.read()
frame_count += 1
if __name__ == "__main__":
convert_mp4_to_jpgs("flask_demo.mp4")
此代碼采用 MP4 視頻文件的路徑。然后使用cv2.VideoCapture(path)打開視頻。你可以使用此方法通讀整個視頻并提取每一幀。提取幀時,可以使用cv2.imwrite()將其寫出。
當(dāng)你運行這段代碼時,你會發(fā)現(xiàn)這個 7 秒的視頻產(chǎn)生了 235 幀!
現(xiàn)在準(zhǔn)備好拍攝這些幀并將它們轉(zhuǎn)換為動畫 GIF。
將幀變成 GIF
該過程的下一步是將使用 OpenCV 從 MP4 文件中提取的幀轉(zhuǎn)換為動畫 GIF。
這就是 Pillow 包的用武之地。你可以使用它來接收圖像文件夾并創(chuàng)建你的 GIF。打開一個新文件并將其命名為gif_maker.py。然后輸入以下代碼:
import glob
from PIL import Image
def make_gif(frame_folder):
images = glob.glob(f"{frame_folder}/*.jpg")
images.sort()
frames = [Image.open(image) for image in images]
frame_one = frames[0]
frame_one.save("flask_demo.gif", format="GIF", append_images=frames,
save_all=True, duration=50, loop=0)
if __name__ == "__main__":
make_gif("output")
在這里,你使用 Python 的glob模塊在輸出文件夾中搜索 JPG 文件。然后對幀進行排序,使它們按正確的順序排列。最后,你將它們保存為 GIF.
創(chuàng)建 MP4 到 GIF GUI
PySimpleGUI 是一個跨平臺的 GUI 框架,可在 Linux、Mac 和 Windows 上運行。它封裝了 Tkinter、wxPython、PyQt 和其他幾個 GUI 工具包,為它們提供了一個通用接口。
在本文前面安裝 PySimpleGUI 時,你安裝了包裝 Tkinter 的默認版本。
打開一個新的 Python 文件并將其命名為mp4_converter_gui.py。然后將此代碼添加到你的文件中:
# mp4_converter_gui.py
import cv2
import glob
import os
import shutil
import PySimpleGUI as sg
from PIL import Image
file_types = [("MP4 (*.mp4)", "*.mp4"), ("All files (*.*)", "*.*")]
def convert_mp4_to_jpgs(path):
video_capture = cv2.VideoCapture(path)
still_reading, image = video_capture.read()
frame_count = 0
if os.path.exists("output"):
# remove previous GIF frame files
shutil.rmtree("output")
try:
os.mkdir("output")
except IOError:
sg.popup("Error occurred creating output folder")
return
while still_reading:
cv2.imwrite(f"output/frame_{frame_count:05d}.jpg", image)
# read next image
still_reading, image = video_capture.read()
frame_count += 1
def make_gif(gif_path, frame_folder="output"):
images = glob.glob(f"{frame_folder}/*.jpg")
images.sort()
frames = [Image.open(image) for image in images]
frame_one = frames[0]
frame_one.save(gif_path, format="GIF", append_images=frames,
save_all=True, duration=50, loop=0)
def main():
layout = [
[
sg.Text("MP4 File"),
sg.Input(size=(25, 1), key="-FILENAME-", disabled=True),
sg.FileBrowse(file_types=file_types),
],
[
sg.Text("GIF File Save Location"),
sg.Input(size=(25, 1), key="-OUTPUTFILE-", disabled=True),
sg.SaveAs(file_types=file_types),
],
[sg.Button("Convert to GIF")],
]
window = sg.Window("MP4 to GIF Converter", layout)
while True:
event, values = window.read()
mp4_path = values["-FILENAME-"]
gif_path = values["-OUTPUTFILE-"]
if event == "Exit" or event == sg.WIN_CLOSED:
break
if event in ["Convert to GIF"]:
if mp4_path and gif_path:
convert_mp4_to_jpgs(mp4_path)
make_gif(gif_path)
sg.popup(f"GIF created: {gif_path}")
window.close()
if __name__ == "__main__":
main()
這是一段相當(dāng)長的代碼。我們來一段一段分析。
要開始,請查看導(dǎo)入部分:
# mp4_converter_gui.py
import cv2
import glob
import os
import shutil
import PySimpleGUI as sg
from PIL import Image
file_types = [("MP4 (*.mp4)", "*.mp4"), ("All files (*.*)", "*.*")]
在這里,你導(dǎo)入創(chuàng)建 GUI 應(yīng)用程序所需的所有模塊和包。這包括 OpenCV (cv2)、Pillow 的 Image clas 和 PySimpleGUI,以及許多 Python 自己的模塊。
你還創(chuàng)建了一個變量來保存可以加載到 GUI 中的文件類型。這是一個元組列表。
現(xiàn)在是時候?qū)⒆⒁饬D(zhuǎn)向程序中的第一個函數(shù):
def convert_mp4_to_jpgs(path):
video_capture = cv2.VideoCapture(path)
still_reading, image = video_capture.read()
frame_count = 0
if os.path.exists("output"):
# remove previous GIF frame files
shutil.rmtree("output")
try:
os.mkdir("output")
except IOError:
sg.popup("Error occurred creating output folder")
return
while still_reading:
cv2.imwrite(f"output/frame_{frame_count:05d}.jpg", image)
# read next image
still_reading, image = video_capture.read()
frame_count += 1
這是你之前創(chuàng)建的 MP4 轉(zhuǎn)換器代碼的修改版本。在這個版本中,你仍然使用VideoCapture()來讀取 MP4 文件并將其轉(zhuǎn)換為單獨的幀。
但是,你還添加了一些額外的代碼來刪除“輸出”文件夾(如果存在)。這可以防止你意外地將兩個 MP4 文件合并到一個輸出文件中,這會導(dǎo)致 GIF 混亂。
你還添加了一些代碼來嘗試在刪除后創(chuàng)建“輸出”文件夾。如果創(chuàng)建文件夾時出現(xiàn)錯誤,則會顯示錯誤對話框。
其余代碼與之前相同。
現(xiàn)在你已準(zhǔn)備好查看下一個函數(shù):
def make_gif(gif_path, frame_folder="output"):
images = glob.glob(f"{frame_folder}/*.jpg")
images.sort()
frames = [Image.open(image) for image in images]
frame_one = frames[0]
frame_one.save(gif_path, format="GIF", append_images=frames,
save_all=True, duration=50, loop=0)
你可以使用make_gif()將幀文件夾轉(zhuǎn)換為 GIF 文件。此代碼與原始代碼幾乎相同,只是你傳入 GIF 文件的路徑以使其唯一。
最后一段代碼是你的 GUI 代碼:
def main():
layout = [
[
sg.Text("MP4 File"),
sg.Input(size=(25, 1), key="-FILENAME-", disabled=True),
sg.FileBrowse(file_types=file_types),
],
[
sg.Text("GIF File Save Location"),
sg.Input(size=(25, 1), key="-OUTPUTFILE-", disabled=True),
sg.SaveAs(file_types=file_types),
],
[sg.Button("Convert to GIF")],
]
window = sg.Window("MP4 to GIF Converter", layout)
while True:
event, values = window.read()
mp4_path = values["-FILENAME-"]
gif_path = values["-OUTPUTFILE-"]
if event == "Exit" or event == sg.WIN_CLOSED:
break
if event in ["Convert to GIF"]:
if mp4_path and gif_path:
convert_mp4_to_jpgs(mp4_path)
make_gif(gif_path)
sg.popup(f"GIF created: {gif_path}")
window.close()
if __name__ == "__main__":
main()
在 PySimpleGUI 中,當(dāng)你想在用戶界面中“布局”元素時,你可以將項目添加到 Python 列表中。對于此示例,你添加以下元素:
- sg.Text - 此元素有兩個實例。它們用作輸入(文本框)的標(biāo)簽
- sg.Input - 這個元素有兩個實例,它是一個文本框類型的元素。一個保存 MP4 文件的位置,一個保存你要保存 GIF 的位置
- sg.FileBrowse - 打開文件瀏覽對話框的按鈕
- sg.SaveAs - 打開文件另存為對話框的按鈕
- sg.Button - 一個可以做任何你想做的事情的按鈕
接下來,你獲取元素列表并將其傳遞給sg.Window,它表示包含所有其他元素的窗口。你的窗口還有一個退出按鈕、一個最小化按鈕和一個標(biāo)題欄。
要啟動 GUI 的事件循環(huán),你需要創(chuàng)建一個 while 循環(huán)并從 Window 對象中讀取數(shù)據(jù)。這允許你提取兩個sg.Input()對象的值,其中包含 MP4 和 GIF 文件的路徑。
當(dāng)用戶按下標(biāo)記為“轉(zhuǎn)換為 GIF”的按鈕時,你會捕獲該事件并調(diào)用convert_mp4_to_jpgs()和make_gif()。如果一切順利,視頻將被轉(zhuǎn)換,你將看到一個彈出對話框,說明新創(chuàng)建的 GIF 的保存位置。
嘗試運行此代碼。你應(yīng)該會看到如下內(nèi)容:

現(xiàn)在你擁有了將 MP4 視頻文件轉(zhuǎn)換為 GIF 所需的所有內(nèi)容。你可以采取多種不同的措施來改進你的代碼。例如,你可以向代碼中添加更多錯誤處理,以免意外覆蓋 GIF。
你還可以添加一些新的 UI 元素來告訴你的代碼調(diào)整各個幀的大小以幫助縮小 GIF。另一種選擇是更改每個單獨的 JPG 的壓縮,這也將減小 GIF 的大小。
還有很多其他有趣的方法可以使這段代碼變得更好??紤]一下,你一定會自己想出一些新功能!?
到此這篇關(guān)于通過Python將MP4視頻轉(zhuǎn)換為GIF動畫的文章就介紹到這了,更多相關(guān)Python視頻轉(zhuǎn)為GIF動畫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python圖像處理之目標(biāo)物體輪廓提取的實現(xiàn)方法
目標(biāo)物體的輪廓實質(zhì)是指一系列像素點構(gòu)成,這些點構(gòu)成了一個有序的點集,這篇文章主要給大家介紹了關(guān)于Python圖像處理之目標(biāo)物體輪廓提取的實現(xiàn)方法,需要的朋友可以參考下2021-08-08
Python設(shè)置Word全局樣式和文本樣式的示例代碼
這篇文章主要介紹了如何利用Python對Word內(nèi)容進行各種樣式的設(shè)置,讓其能夠看起來更加的美觀。文中的示例代碼講解詳細,需要的可以參考一下2022-05-05
Python3實現(xiàn)計算兩個數(shù)組的交集算法示例
這篇文章主要介紹了Python3實現(xiàn)計算兩個數(shù)組的交集算法,結(jié)合2個實例形式總結(jié)分析了Python3針對數(shù)組的遍歷、位運算以及元素的添加、刪除等相關(guān)操作技巧,需要的朋友可以參考下2019-04-04
scrapy中如何設(shè)置應(yīng)用cookies的方法(3種)
這篇文章主要介紹了scrapy中如何設(shè)置應(yīng)用cookies的方法(3種),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Python從Excel讀取數(shù)據(jù)并使用Matplotlib繪制成二維圖像
本課程實現(xiàn)使用 Python 從 Excel 讀取數(shù)據(jù),并使用 Matplotlib 繪制成二維圖像。這一過程中,將通過一系列操作來美化圖像,最終得到一個可以出版級別的圖像。本課程對于需要書寫實驗報告,學(xué)位論文,發(fā)表文章,做報告的學(xué)員具有較大價值2023-02-02
django執(zhí)行原始查詢sql,并返回Dict字典例子
這篇文章主要介紹了django執(zhí)行原始查詢sql,并返回Dict字典例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04

