You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将GStreamer RTSP视频管道嵌入Qt GUI以显示IP摄像头视频流

如何将GStreamer RTSP视频管道嵌入Qt GUI以显示IP摄像头视频流

嘿,我来帮你搞定把GStreamer RTSP流嵌入Qt GUI的问题~你当前用gtksink虽然能正常显示视频,但它是GTK专属的组件,和Qt的GUI框架不兼容,没法直接嵌入到你用Qt Designer做的widget里。这里给你几个适配Qt的方案,一步步来:

一、首选方案:用qt5videosink(完美适配Qt)

GStreamer官方提供了专门给Qt5用的sink组件——qt5videosink,它可以直接把视频渲染到Qt的widget中,完全契合你的PyQt5应用场景。

调整后的GStreamer管道

把原来的gtksink直接替换成qt5videosink就行,管道如下:

rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=100 ! queue ! decodebin ! videoconvert ! qt5videosink name=sink sync=false

代码中绑定Qt Widget的步骤

假设你在Qt Designer里的视频显示控件叫video_widget,按下面的步骤把sink和它绑定:

  1. 先确保你的系统装了GStreamer的Qt5插件——比如Ubuntu上可以跑sudo apt install gstreamer1.0-qt5,其他系统对应安装即可
  2. 在PyQt的业务代码里,获取qt5videosink元素,然后调用它的set_widget方法绑定你的视频控件:
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject
from PyQt5 import QtWidgets

# 先初始化GStreamer
Gst.init(None)

# 创建GStreamer管道
pipeline = Gst.parse_launch("rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=100 ! queue ! decodebin ! videoconvert ! qt5videosink name=sink sync=false")

# 获取qt5videosink元素
sink = pipeline.get_by_name("sink")
# 把它绑定到你Qt界面里的video_widget(这里假设self.ui是你加载的UI对象)
sink.set_widget(self.ui.video_widget)

# 启动管道开始播放
pipeline.set_state(Gst.State.PLAYING)

二、备选方案:用xvimagesink嵌入窗口

如果因为环境限制没法用qt5videosink,可以试试xvimagesink,然后把它的渲染窗口嵌入到Qt widget中:

修改后的管道

rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=100 ! queue ! decodebin ! videoconvert ! xvimagesink name=sink sync=false

代码中嵌入窗口的操作

通过获取xvimagesink的窗口ID,再用Qt的API把它嵌入到你的控件里:

# 获取xvimagesink元素
sink = pipeline.get_by_name("sink")
# 获取它的窗口ID
xid = sink.get_property("window-id")
# 创建Qt窗口并嵌入到你的video_widget中
video_window = QtCore.QWindow.fromWinId(xid)
video_container = QtWidgets.QWidget.createWindowContainer(video_window, self.ui.video_widget)
video_container.setGeometry(self.ui.video_widget.rect())

三、播放/暂停按钮的实现

你可以通过控制GStreamer管道的状态来实现按钮功能,代码示例如下:

# 播放按钮点击事件处理
def on_play_btn_clicked(self):
    self.pipeline.set_state(Gst.State.PLAYING)

# 暂停按钮点击事件处理
def on_pause_btn_clicked(self):
    self.pipeline.set_state(Gst.State.PAUSED)

一些额外的注意事项

  • 要确保你的PyQt5版本和GStreamer的Qt插件版本匹配,避免出现兼容性问题
  • 记得处理GStreamer的错误信号,比如监听管道的消息总线,捕获断开或者错误情况,方便调试和恢复:
# 绑定消息总线的监听
bus = self.pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message", self._on_gst_message)

def _on_gst_message(self, bus, message):
    msg_type = message.type
    if msg_type == Gst.MessageType.ERROR:
        err, debug = message.parse_error()
        print(f"GStreamer出错啦:{err.message},调试信息:{debug}")
        self.pipeline.set_state(Gst.State.NULL)
    elif msg_type == Gst.MessageType.EOS:
        print("视频流结束")
        self.pipeline.set_state(Gst.State.NULL)

备注:内容来源于stack exchange,提问作者Christopher Lajoie

火山引擎 最新活动