如何使用gst和python创建视频聊天,并在单个gtk窗口中显示发起者和接受者的视频

3 投票
1 回答
1832 浏览
提问于 2025-04-16 22:38

我正在用gst和python开发视频聊天功能。在这个功能中,我想在一个gtk窗口里同时看到用户的摄像头画面和我自己的摄像头画面(就像empathy视频聊天那样)。

为此,我使用了gst.Tee对象,并创建了两个队列,一个连接到本地的gtk窗口,另一个则把同样的视频流连接到会话对象。

gst.Tee完成了这个任务,但也导致视频聊天的速度变慢,视频的播放比音频晚了。(我为音频会话使用了不同的流)

这里是代码片段:

self.pipeline = gst.Pipeline()

bus = self.pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', self._on_gst_message)

self.src_bin = gst.element_factory_make("autovideosrc", "src")
autovideosinkLocal = gst.element_factory_make("autovideosink", "autovideosinkLocal")
tee = gst.element_factory_make('tee', "tee")
queueLocal = gst.element_factory_make("queue", "queueLocal")
queueSend = gst.element_factory_make("queue", "queueSend")
self.pipeline.add(self.src_bin, tee, queueLocal, autovideosinkLocal, queueSend)
gst.element_link_many(self.src_bin, tee)
tee.link(queueLocal)
queueLocal.link(autovideosinkLocal)
tee.link(queueSend)
queueSend.get_pad('src').link(self.p2psession.get_property('sink-pad'))
self.pipeline.set_state(gst.STATE_PLAYING)

我该如何加快视频聊天的速度呢?(比如,如果我只使用一个接收端,只显示接受者的视频,那效果很好)

有没有其他方法可以做到这一点?

谢谢!

1 个回答

0

我本来不想回答这个问题,但因为没有其他人发言,我就试试看。

我不太确定这是否和摄像头有关(不过可能有关系),但你可以在PyGTK中为你的两个屏幕创建两个绘图区域(gtk.DrawingArea)。然后,你可以把视频连接到这些区域上。

我在我的代码中做的事情和这个类似,用来播放视频。这可能需要你创建两个独立的接收器,但老实说,我不太确定。(如果有人能进一步解释这个想法,请在评论中分享。)

这是我现在使用的代码片段(取自def __ init __)。我在Ubuntu上遇到了一点小问题(我觉得和JACK有关),但我相信这可能是特定于我的电脑的。请注意,我有一个预定义的路径。

def __init__(self):

        def on_message(bus, message): 
            if message.type == gst.MESSAGE_EOS: 
                # End of Stream 
                player.set_state(gst.STATE_NULL) 
            elif message.type == gst.MESSAGE_ERROR: 
                player.set_state(gst.STATE_NULL) 
                (err, debug) = message.parse_error() 
                print "Error: %s" % err, debug

        def on_sync_message(bus, message):
            if message.structure is None: 
                return False 
            if message.structure.get_name() == "prepare-xwindow-id":
                if sys.platform == "win32":
                    win_id = videowidget.window.handle
                else:
                    win_id = videowidget.window.xid
                assert win_id
                imagesink = message.src 
                imagesink.set_property("force-aspect-ratio", True)
                imagesink.set_xwindow_id(win_id) 

        win = gtk.Window()
        win.set_resizable(False)
        win.set_has_frame(False)
        win.set_position(gtk.WIN_POS_CENTER)

        fixed = gtk.Fixed()
        win.add(fixed)
        fixed.show()

        videowidget = gtk.DrawingArea()
        fixed.put(videowidget, 0, 0)
        videowidget.set_size_request(640, 480)
        videowidget.show()

        # Setup GStreamer 
        player = gst.element_factory_make("playbin", "MultimediaPlayer")
        bus = player.get_bus() 
        bus.add_signal_watch() 
        bus.enable_sync_message_emission() 
        #used to get messages that GStreamer emits 
        bus.connect("message", on_message) 
        #used for connecting video to your application 
        bus.connect("sync-message::element", on_sync_message)
        player.set_property("uri", "file://" + os.getcwd() + "/VID/SEQ-GAME-OPEN.ogv") 
        player.set_state(gst.STATE_PLAYING)

        win.show()

希望这对你有帮助。

撰写回答