Skip to main content

[Python] Gstreamer with Python on Windows

info

參考影片: Video Streaming Made Awesome with GStreamer and Python - sunhacks 2020 Talk

參考文章: sunhacks_2020_gstreamer_talk.md 可以直接依照參考文章去進行操作

Dependencies

首先要去下載MSYS2,參考圖片

下載完之後,按照指示直到最後一步,取消Run MSYS2 now.

透過win鍵搜尋MSYS2 MINGW64打開,會是一個很像 cmd 的 terminal

在 terminal 進行以下操作,

  1. 更新 MSYS2 pacman -Syu

  2. 下載 gstreamer、gstreamer with Python 需要的套件

pacman -S mingw-w64-x86_64-gstreamer mingw-w64-x86_64-gst-devtools mingw-w64-x86_64-gst-plugins-{base,good,bad,ugly} mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-gobject

PyGObject

PyGObject API Reference

Python GStreamer Tutorial

Python code

gi module

保留著 MSYS2 的視窗,我們開啟 visual studio code 編輯器,在C:\msys64\home\username的位置建立main.py撰寫程式碼。

GStreamer library 本身是使用 C 語言撰寫,透過binding的 library: PyGObject,我們可以使用 Python 來撰寫,首先要先匯入gi

main.py
import gi

告訴 PyGObject 我們要使用的是 GStreamer 1.0("Gst"為其縮寫),匯入要使用的模組,並透過Gst.init()啟動 GStreamer

import gi

gi.require_version("Gst", "1.0")
gi.require_version("GstApp", "1.0")

from gi.repository import Gst, GstApp, GLib

_= GstApp # 需要匯入GstApp後面才可以運作,而實際上這個模組並沒有出現在程式碼中,所以我們將其定義為_變數,為的是不要出現模組未使用的警告

Gst.init()

MainLoop

接著,我們開始主要的迴圈,他負責處理各種事件並在背景中運行,因此,我們透過thread來達到多工處理

from threading import Thread

main_loop = GLib.MainLoop()
main_loop_thread = Thread(target=main_loop.run)
# 啟動main_loop
main_loop_thread.start()

pipeline

我們要建立影像處理的 pipeline,這裡的元素有四個,使用!進行串接,一開始都要指定 source,最後匯出的地方為 sink。

  1. ksvideosrc 指定我們的影像來源為視訊前鏡頭,autovideosrc for macOS,v412src for Linux。
  2. decodebin 處理各種不同的 video 壓縮的方式(compression format)、檔案格式(container format),幫助我們解碼成一張張的原生圖片
  3. videoconvert處理與下個串接元素不同的格式,轉成下個元素預期接受的格式
  4. autovideosink會在我們的主螢幕顯示
pipeline = Gst.parse_launch("ksvideosrc ! decodebin ! videoconvert ! autovideosink")

透過set_state的方法,開始這條 pipeline,背景main_lop會接受到開始的事件,在背景執行

pipeline.set_state(Gst.State.PLAYING)

Interrupt

主程式現在執行sleep(0.1),等待視訊鏡頭的畫面呈現在主螢幕上,透過KeyboardInterrupt可以跳出 while loop,並將 pipeline 清空,關掉main_loop

try:
while True:
sleep(0.1)
except KeyboardInterrupt:
pass

pipeline.set_state(Gst.State.NULL)
main_loop.quit()
# 關掉main_loop_thread
main_loop_thread.join()

Github code