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

发布于 2024-11-27 09:55:53 字数 1124 浏览 3 评论 0原文

我正在使用 gst 和 python 开发视频聊天。 我想在其中查看最终用户的网络摄像头,并且还想在一个 gtk 窗口中查看我自己的网络摄像头(类似于同理心视频聊天)。

为此,我使用了 gst.Tee 对象并创建了 2 个队列,一个队列将结果链接到本地​​ 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)

我将如何加速视频聊天(例如,如果我使用单个接收器并仅显示接受者的视频,效果很好)?

还有其他方法可以做到同样的事情吗?

谢谢!

I am developing video chat using gst and python.
where, I would like to view end user's webcam and also want to view my own webcam in one gtk window (similar to empathy video chat).

for that, I have used gst.Tee object and created 2 queues, one would link result to local gtk window and second queue would link same video stream to session object.

gst.Tee have done the task but also decrease the speed of video chat and Video comes later than Audio. (I have used different stream for Audio session)

here, the code snippet :

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)

How would I speedup the video chat (like, If I would use single sink and display only accepter's video it works great)?

Is there any other way to do the same?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愛上了 2024-12-04 09:55:53

我一直没有回答,但由于没有其他人参与其中,所以我会尝试一下。

我不确定这是否会与网络摄像头配合(尽管可能会),但是您可以创建两个绘图区域(gtk.DrawingArea) 在 PyGTK 中为您的两个屏幕。然后,您可以将您的视频连接到这些内容。

我在播放视频的代码中做了类似的事情。这可能需要您创建两个单独的接收器,但坦率地说,我不确定。 (如果有人可以进一步扩展这个想法,请随时在评论中这样做。)

这是我现在正在使用的代码片段(取自 def __ init __ 。我正在 Ubuntu 中处理一个小故障(我认为这与杰克有关),但我很确定这是特定于计算机的。注意,我有一个预定义的路径,

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()

希望对您有所帮助。

I was holding off on answering, but as no one else has weighed in, I'll take a shot at it.

I'm not sure if this would tie in with webcam (though it probably would), but you could create two drawing areas (gtk.DrawingArea) in PyGTK for your two screens. Then, you can hook your video up to those.

I'm doing something similar in my code for playing video. This may require you to create two separate sinks, but frankly, I'm not sure. (If anyone can further expand on this idea, please feel free to do so in comments.)

Here's the piece of code I'm using right now (taken from def __ init __. I am dealing with a small glitch with it in Ubuntu (it has to do with JACK I think), but I'm pretty sure that's computer specific. Note, I have a predefined path.

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()

Here's hoping that helps you out, some.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文