我有一个简单的Python程序使用gst-rtsp-server创建RTSP流。它工作,但原来没有错误处理。如果管道输入错误或连接到视频源有问题,我看不到堆栈跟踪或任何日志记录。我会在哪里挂钩代码来处理这样的问题?
我应该提一下,我是GObject世界的完全初学者。我怀疑这些库有一种标准的方式来报告错误,但我在文档中找不到任何关于如何完成的文档。
如果它有用,这是我现在的代码:
from threading import Thread
from time import sleep
import signal
import gi
gi.require_version("Gst", "1.0")
gi.require_version("GstRtsp", "1.0")
gi.require_version("GstRtspServer", "1.0")
from gi.repository import GLib, GObject, Gst, GstRtsp, GstRtspServer
PIPELINE = (
"( videotestsrc ! vp8enc ! rtpvp8pay name=pay0 pt=96 )")
def main():
GObject.threads_init()
Gst.init(None)
server = GstRtspServer.RTSPServer.new()
server.props.service = "3000"
server.attach(None)
loop = GLib.MainLoop.new(None, False)
def on_sigint(_sig, _frame):
print("Got a SIGINT, closing...")
loop.quit()
signal.signal(signal.SIGINT, on_sigint)
def run_main_loop():
loop.run()
main_loop_thread = Thread(target=run_main_loop)
main_loop_thread.start()
media_factory = GstRtspServer.RTSPMediaFactory.new()
media_factory.set_launch(PIPELINE)
media_factory.set_shared(True)
server.get_mount_points().add_factory("/test", media_factory)
print("Stream ready at rtsp://127.0.0.1:3000/test")
while loop.is_running():
sleep(0.1)
if __name__ == "__main__":
main()
在对GStreamer和RTSP服务器库进行一些实验之后,错误处理情况变得复杂。
在GStreamer管道上查看错误的规范方法是将一个观察者添加到管道的总线并监听错误消息。
def watcher(bus, message, *user_data);
if message.type == Gst.MessageType.ERROR:
error, message = message.parse_error()
# TODO: Do something with the error
my_pipeline.get_bus().add_watch(
GLib.PRIORITY_DEFAULT,
watcher,
None)
但是,您无法使用提供给GstRtspServer的管道执行此操作。这是因为GstRtspServer希望能够在管道总线上安装自己的观察器,并且一次只能有一个观察者连接到总线。这尤其令人遗憾,因为这会阻止我们监听管道上的任何事件,而不仅仅是错误。
我们可以将管道分成两部分:一部分负责连接源和解码帧的容易出错的过程,另一部分负责编码生成的帧并为GstRtspServer加载它们。然后我们可以使用intervideo插件在两者之间进行通信。
例如,假设您正在尝试从VP8格式的文件流式传输。我们的第一个负责读取和解码帧的管道如下所示:
filesrc location="{filepath}" ! decodebin ! intervideosink channel="file-channel"
...我们负责编码和加载框架的第二个管道如下所示:
intervideosrc channel="file-channel" ! videoconvert ! vp8enc deadline=1 ! rtpvp8pay name=pay0 pt=96
这里的关键是只有第二个管道必须由GstRtspServer管理,因为它是提供加载数据的管道。第一个由我们管理,我们可以附加我们自己的观察者,它可以智能地响应错误并做任何我们需要的事情。这当然不是一个完美的解决方案,因为我们无法响应与编码和有效加载相关的错误,但我们已经获得了接收与读取文件和解码相关的错误的能力。我们现在还能够执行其他与消息相关的任务,例如拦截流结束消息以循环视频文件。