Python Gstreamer总线日志消息在哪里?
我正在尝试使用python中的Gstreamer将.mp4流式传输到RTSP服务器Python Gstreamer总线日志消息在哪里?,python,gstreamer,rtsp,gstreamer-1.0,python-gstreamer,Python,Gstreamer,Rtsp,Gstreamer 1.0,Python Gstreamer,我正在尝试使用python中的Gstreamer将.mp4流式传输到RTSP服务器 import sys import gi gi.require_version('Gst', '1.0') gi.require_version('GstRtspServer', '1.0') gi.require_version('GstRtsp', '1.0') from gi.repository import Gst, GstRtspServer, GObject, GLib, GstRtsp loo
import sys
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
gi.require_version('GstRtsp', '1.0')
from gi.repository import Gst, GstRtspServer, GObject, GLib, GstRtsp
loop = GLib.MainLoop()
Gst.init(None)
file_path = "test.mp4"
class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):
def __init__(self):
GstRtspServer.RTSPMediaFactory.__init__(self)
def do_create_element(self, url):
src_demux = f"filesrc location={file_path} ! qtdemux name=demux"
h264_transcode = "demux.video_0"
pipeline = "{0} {1} ! queue ! rtph264pay name=pay0 config-interval=1 pt=96".format(src_demux, h264_transcode)
print ("Element created: " + pipeline)
self._pipeline = Gst.parse_launch(pipeline)
def bus_handler(bus, message):
print(message)
self.bus = self._pipeline.get_bus()
self.bus.connect('message', bus_handler)
self.bus.add_signal_watch_full(1)
return self._pipeline
class GstreamerRtspServer():
def __init__(self):
self.rtspServer = GstRtspServer.RTSPServer()
factory = TestRtspMediaFactory()
factory.set_shared(True)
mountPoints = self.rtspServer.get_mount_points()
self.address = '127.0.0.1' #my RPi's local IP
self.port = '8553'
self.rtspServer.set_address(self.address)
self.rtspServer.set_service(self.port)
urlstr = "/user=&password=.sdp"
url = GstRtsp.RTSPUrl.parse(urlstr)
mountPoints.add_factory(urlstr, factory)
self.rtspServer.attach(None)
if __name__ == '__main__':
s = GstreamerRtspServer()
loop.run()
然而,我试图了解如何使用Gstreamer总线记录诸如eos或错误和警告之类的消息,但我没有看到任何错误和警告,即使在我发送eos事件并且流媒体有效停止时也是如此
s.rtspServer._pipeline._end_stream_event.set()
s.rtspServer._pipeline.send_event(Gst.Event.new_eos())
我用得对吗?如果没有,我可以修复什么来正确记录总线消息?以下解决方案基于已接受但不完全的答案 我找到了一种不需要“手动”创建管道元素的方法,但它(在本场景中)保持了方便的
Gst.parse_launch(pipelineCmd)
方法,并扩展了Gst.Bin以启用消息调试
下面是完整的示例源代码(查看注释行以了解一些解释):
请注意,实际上inherists/extends(和Gst.Element)可以(无论听起来多么奇怪)将管道添加到bin
这个小“把戏”为我们这些“懒惰”的程序员节省了时间,使他们能够继续使用命令行语法的解析来创建管道元素
在一些更复杂的场景中,命令行语法的解析不适用,解决方案如下:
- 创建ExtendedBin
- 使用方法“手动”创建元素(并设置必要的属性)
- 将创建的元素添加到
ExtendedBean
- 链接元素
- 创建新管道并向其添加bin
- 在需要的地方使用管道
- 以下解决方案基于公认但不完全的答案
我找到了一种不需要“手动”创建管道元素的方法,但它(在本场景中)保持了方便的
Gst.parse_launch(pipelineCmd)
方法,并扩展了Gst.Bin以启用消息调试
下面是完整的示例源代码(查看注释行以了解一些解释):
请注意,实际上inherists/extends(和Gst.Element)可以(无论听起来多么奇怪)将管道添加到bin
这个小“把戏”为我们这些“懒惰”的程序员节省了时间,使他们能够继续使用命令行语法的解析来创建管道元素
在一些更复杂的场景中,命令行语法的解析不适用,解决方案如下:
- 创建ExtendedBin
- 使用方法“手动”创建元素(并设置必要的属性)
- 将创建的元素添加到
ExtendedBean
- 链接元素
- 创建新管道并向其添加bin
- 在需要的地方使用管道
#!/usr/bin/env python
import sys
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import Gst, GstRtspServer, GObject, GLib
Gst.init(None)
loop = GLib.MainLoop()
# extended Gst.Bin that overrides do_handle_message and adds debugging
class ExtendedBin(Gst.Bin):
def do_handle_message(self,message):
if message.type == Gst.MessageType.ERROR:
error, debug = message.parse_error()
print("ERROR:", message.src.get_name(), ":", error.message)
if debug:
print ("Debug info: " + debug)
elif message.type == Gst.MessageType.EOS:
print ("End of stream")
elif message.type == Gst.MessageType.STATE_CHANGED:
oldState, newState, pendingState = message.parse_state_changed()
print ("State changed -> old:{}, new:{}, pending:{}".format(oldState,newState,pendingState))
else :
print("Some other message type: " + str(message.type))
#call base handler to enable message propagation
Gst.Bin.do_handle_message(self,message)
class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):
def __init__(self):
GstRtspServer.RTSPMediaFactory.__init__(self)
def do_create_element(self, url):
#set mp4 file path to filesrc's location property
src_demux = "filesrc location=/path/to/dir/test.mp4 ! qtdemux name=demux"
h264_transcode = "demux.video_0"
#uncomment following line if video transcoding is necessary
#h264_transcode = "demux.video_0 ! decodebin ! queue ! x264enc"
pipelineCmd = "{0} {1} ! queue ! rtph264pay name=pay0 config-interval=1 pt=96".format(src_demux, h264_transcode)
self.pipeline = Gst.parse_launch(pipelineCmd)
print ("Pipeline created: " + pipelineCmd)
# creates extended Gst.Bin with message debugging enabled
extendedBin = ExtendedBin("extendedBin")
# Gst.pipeline inherits Gst.Bin and Gst.Element so following is possible
extendedBin.add(self.pipeline)
# creates new Pipeline and adds extended Bin to it
self.extendedPipeline = Gst.Pipeline.new("extendedPipeline")
self.extendedPipeline.add(extendedBin)
return self.extendedPipeline
class GstreamerRtspServer(GstRtspServer.RTSPServer):
def __init__(self):
self.rtspServer = GstRtspServer.RTSPServer()
self.factory = TestRtspMediaFactory()
self.factory.set_shared(True)
mountPoints = self.rtspServer.get_mount_points()
mountPoints.add_factory("/stream", self.factory)
self.rtspServer.attach(None)
print ("RTSP server is ready")
if __name__ == '__main__':
s = GstreamerRtspServer()
loop.run()