使用 Python 將 MP4視頻 轉換為GIF影片
Python 可用于讀取常見的 MP4 視頻格式并將其轉換為 GIF影片,當然,如果你愿意,你可以使用預先構建的軟體,但是自己做很有趣(并且是一種很好的學習體驗),
在本教程中,你將學習以下內容:
- 如何從 MP4 視頻中提取幀
- 將幀轉換為 GIF
- 創建 MP4 到 GIF GUI
讓我們開始吧!
文章目錄
- 使用 Python 將 MP4視頻 轉換為GIF影片
- 運行環境
- 如何從 MP4 視頻中提取幀
- 將幀變成 GIF
- 創建 MP4 到 GIF GUI
運行環境
你需要安裝 OpenCV 系結以讀取 MP4 檔案并將視頻中的每一幀轉換為 JPG 檔案,安裝教程:
python3 -m pip install opencv-python
你還需要Pillow從你從視頻中提取的 JPG 創建影片 GIF,也可以用pip安裝:
python3 -m pip install Pillow
要創建 GUI,我這里會用到PySimpleGUI,要安裝該庫,請使用以下命令:
python3 -m pip install PySimpleGUI
如果你使用的是 Anaconda,則包含 opencv-python 和 Pillow,你只需要單獨安裝 PySimpleGUI,
如何從 MP4 視頻中提取幀
從 MP4 視頻中提取幀的第一步是找到要轉換為 GIF 的視頻,
要從上面的視頻中提取單個幀,你需要撰寫一些 Python,創建一個新檔案并將其命名為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()將其寫出,
當你運行這段代碼時,你會發現這個 7 秒的視頻產生了 235 幀!
現在準備好拍攝這些幀并將它們轉換為影片 GIF,
將幀變成 GIF
該程序的下一步是將使用 OpenCV 從 MP4 檔案中提取的幀轉換為影片 GIF,
這就是 Pillow 包的用武之地,你可以使用它來接收影像檔案夾并創建你的 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.
創建 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()
這是一段相當長的代碼,我們來一段一段分析,
要開始,請查看匯入部分:
# 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 (*.*)", "*.*")]
在這里,你匯入創建 GUI 應用程式所需的所有模塊和包,這包括 OpenCV (cv2)、Pillow 的 Image clas 和 PySimpleGUI,以及許多 Python 自己的模塊,
你還創建了一個變數來保存可以加載到 GUI 中的檔案型別,這是一個元組串列,
現在是時候將注意力轉向程式中的第一個函式:
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
這是你之前創建的 MP4 轉換器代碼的修改版本,在這個版本中,你仍然使用VideoCapture()來讀取 MP4 檔案并將其轉換為單獨的幀,
但是,你還添加了一些額外的代碼來洗掉“輸出”檔案夾(如果存在),這可以防止你意外地將兩個 MP4 檔案合并到一個輸出檔案中,這會導致 GIF 混亂,
你還添加了一些代碼來嘗試在洗掉后創建“輸出”檔案夾,如果創建檔案夾時出現錯誤,則會顯示錯誤對話框,
其余代碼與之前相同,
現在你已準備好查看下一個函式:
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()將幀檔案夾轉換為 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 中,當你想在用戶界面中“布局”元素時,你可以將專案添加到 Python 串列中,對于此示例,你添加以下元素:
- sg.Text - 此元素有兩個實體,它們用作輸入(文本框)的標簽
- sg.Input - 這個元素有兩個實體,它是一個文本框型別的元素,一個保存 MP4 檔案的位置,一個保存你要保存 GIF 的位置
- sg.FileBrowse - 打開檔案瀏覽對話框的按鈕
- sg.SaveAs - 打開檔案另存為對話框的按鈕
- sg.Button - 一個可以做任何你想做的事情的按鈕
接下來,你獲取元素串列并將其傳遞給sg.Window,它表示包含所有其他元素的視窗,你的視窗還有一個退出按鈕、一個最小化按鈕和一個標題欄,
要啟動 GUI 的事件回圈,你需要創建一個 while 回圈并從 Window 物件中讀取資料,這允許你提取兩個sg.Input()物件的值,其中包含 MP4 和 GIF 檔案的路徑,
當用戶按下標記為“轉換為 GIF”的按鈕時,你會捕獲該事件并呼叫convert_mp4_to_jpgs()和make_gif(),如果一切順利,視頻將被轉換,你將看到一個彈出對話框,說明新創建的 GIF 的保存位置,
嘗試運行此代碼,你應該會看到如下內容:

現在你擁有了將 MP4 視頻檔案轉換為 GIF 所需的所有內容,你可以采取多種不同的措施來改進你的代碼,例如,你可以向代碼中添加更多錯誤處理,以免意外覆寫 GIF,
你還可以添加一些新的 UI 元素來告訴你的代碼調整各個幀的大小以幫助縮小 GIF,你可以在如何使用 Python 調整照片大小中閱讀相關內容,另一種選擇是更改每個單獨的 JPG 的壓縮,這也將減小 GIF 的大小,
還有很多其他有趣的方法可以使這段代碼變得更好,考慮一下,你一定會自己想出一些新功能!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/388035.html
標籤:其他
