You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python GStreamer程序无法正常显示MacBook摄像头画面(绿屏花屏)

问题分析与修复方案

你的Python代码与命令行管道的核心差异在于缺少了capsfilter元素的链路整合:命令行中avfvideosrc之后明确通过capsfilter约束了输出格式,但Python代码里虽然创建了capsfilter实例,却没有将它添加到管道中,也没有把它纳入元素链路里。这导致摄像头输出的视频格式未被正确约束,与后续rawvideoparse期望的格式不匹配,最终出现绿屏花屏问题。

具体修复步骤

  1. 将capsfilter元素添加到管道中
  2. 调整元素链路顺序,让视频流依次经过source → capsfilter → rawvideoparse,与命令行管道结构完全对齐

修正后的完整代码

import os
import sys

import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
gi.require_version('GLib', '2.0')
gi.require_version('GObject', '2.0')
from gi.repository import GObject, Gst, GstVideo
GObject.threads_init()
Gst.init(None)

class GstCaps(object):
  def __init__(self, caps_string):
    self.caps_string = caps_string

  def __new__(cls, caps_string):
    cf = Gst.ElementFactory.make('capsfilter', None)
    caps = Gst.Caps.from_string(caps_string)
    cf.set_property('caps', caps)
    return cf


class Webcam(object):
  # macOS, open webcam and display on screen
  # ./gst-launch-1.0 -v -e
  #     avfvideosrc device-index=0 !
  #     "video/x-raw, width=1280, height=720, format=(string)YUY2, texture-target=rectangle" !
  #     rawvideoparse width=1280 height=720 format=yuy2 !
  #     queue !
  #     autovideoconvert !
  #     autovideosink

  def __init__(self, device_index: int = 0):
    self.mainloop = GObject.MainLoop()

    self.pipeline = Gst.ElementFactory.make('pipeline', 'pipeline')

    self.source = Gst.ElementFactory.make('avfvideosrc', 'source')
    self.source.set_property('device-index', device_index)

    self.caps = GstCaps('video/x-raw, width=1280, height=720, format=(string)YUY2, texture-target=rectangle')

    self.rawvideoparse = Gst.ElementFactory.make('rawvideoparse', 'rawvideoparse')
    self.rawvideoparse.set_property('width', 1280)
    self.rawvideoparse.set_property('height', 720)
    self.rawvideoparse.set_property('format', 'yuy2')

    self.queue = Gst.ElementFactory.make('queue', 'queue')
    self.autovideoconvert = Gst.ElementFactory.make('autovideoconvert', 'autovideoconvert')
    self.autovideosink = Gst.ElementFactory.make('autovideosink', 'autovideosink')

    if (not self.pipeline or
        not self.source or
        not self.caps or
        not self.rawvideoparse or
        not self.queue or
        not self.autovideoconvert or
        not self.autovideosink
    ):
      print('ERROR: Not all elements could be created.')
      sys.exit(1)

    # 将capsfilter添加到管道
    self.pipeline.add(self.source)
    self.pipeline.add(self.caps)
    self.pipeline.add(self.rawvideoparse)
    self.pipeline.add(self.queue)
    self.pipeline.add(self.autovideoconvert)
    self.pipeline.add(self.autovideosink)

    # 修正链路顺序
    linked = self.source.link(self.caps)
    linked = linked and self.caps.link(self.rawvideoparse)
    linked = linked and self.rawvideoparse.link(self.queue)
    linked = linked and self.queue.link(self.autovideoconvert)
    linked = linked and self.autovideoconvert.link(self.autovideosink)

    if not linked:
      print("ERROR: Elements could not be linked")
      sys.exit(1)

    self.bus = self.pipeline.get_bus()
    self.bus.add_signal_watch()
    self.bus.connect('message::eos', self.on_eos)
    self.bus.connect('message::error', self.on_error)

  def run(self):
    self.pipeline.set_state(Gst.State.PLAYING)
    self.mainloop.run()

  def quit(self):
    self.pipeline.set_state(Gst.State.NULL)
    self.mainloop.quit()

  def on_eos(self, bus, message):
    self.quit()

  def on_error(self, bus, message):
    print(f'ERROR: {message.parse_error()}' )
    self.quit()

# 注意:如果你的摄像头设备索引是1,这里传入1
webcam = Webcam(device_index=1)
webcam.run()

额外说明

  • 请根据你实际的摄像头设备索引调整Webcam初始化时的device_index参数(命令行中使用的是1)
  • capsfilter的作用是强制摄像头输出指定格式的视频流,确保后续rawvideoparse能正确解析数据,避免格式不匹配导致的画面异常

内容的提问来源于stack exchange,提问作者HanSooloo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 12:24:58