提问人:NevMthw 提问时间:11/17/2023 最后编辑:NevMthw 更新时间:11/20/2023 访问量:70
如何让 RTSP 流显示在多个设备上?
How can I get the RTSP stream to show up on multiple devices?
问:
我有一个使用 gstreamer RTSP 服务器的代码,我正在尝试从图像/帧创建一些 rtsp 流。该实现工作正常,并将图像转换为 RTSP 流。
这个过程是我运行脚本,服务器现在处于活动状态,然后我可以在另一台机器上使用我当前机器 IP 的 RTSP 流。
问题:
- 我想知道如何更改rtsp端口并从config.json文件中获取它。出于某种原因,即使我没有明确说明使用该端口,使用的默认端口也是 8554。
- 在不同端口的帮助下,我是否能够通过一个 RTSP 服务器使用多个 rtsp 流?例如,如果我通过 VLC 流式传输相同的 RTSP URL,我当前的实现无法在多台计算机上工作。
这是我到目前为止的代码:
class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):
def __init__(self, source):
GstRtspServer.RTSPMediaFactory.__init__(self)
self.source = source
def do_create_element(self, url):
image_folder = self.source.get("image_folder", None)
if image_folder:
# print('Image folder paths:', image_folder)
pipeline = f"multifilesrc location={image_folder}/%d.jpg index=1 caps=\"image/jpeg,framerate=30/1\" ! jpegdec ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast ! rtph264pay name=pay0 config-interval=1 pt=96"
else:
print("Invalid source. Specify 'image_folder' in the configuration.")
return None
print("Element created:", pipeline)
return Gst.parse_launch(pipeline)
class GstreamerRtspServer():
def __init__(self, sources):
self.rtspServer = GstRtspServer.RTSPServer()
self.mountPoints = self.rtspServer.get_mount_points()
self.create_rtsp_streams(sources)
def create_rtsp_streams(self, sources):
for source in sources:
rtsp_port = source["rtsp_port"]
rtsp_mount_point = source["rtsp_mount_point"]
print(rtsp_mount_point)
print(rtsp_port)
factory = TestRtspMediaFactory(source)
factory.set_shared(True)
self.mountPoints.add_factory(rtsp_mount_point, factory)
self.rtspServer.attach(None)
def main(config_file):
with open(config_file, 'r') as f:
config = json.load(f)
sources = config.get("sources", [])
s = GstreamerRtspServer(sources)
loop = GLib.MainLoop()
loop.run()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Run RTSP server for multiple video sources.")
parser.add_argument("--config", required=True, help="Path to the JSON configuration file.")
args = parser.parse_args()
main(args.config)
这是我的config.json文件:
{
"sources": [
{
"image_folder": "/path/to/another/image/folder",
"rtsp_port": 4000,
"rtsp_mount_point": "/stream1"
},
{
"image_folder": "/path/to/another/image/folder",
"rtsp_port": 8555,
"rtsp_mount_point": "/stream2"
}
]
}
答:
1赞
SeB
11/19/2023
#1
要设置服务器使用的端口,请使用 RtspServer 的方法。
set_service
您不需要为不同的客户端指定不同的端口,RTSP服务器将与客户端协商并管理实际的端口和传输协议。客户端可以使用 stream1、stream2 仅使用 URI 选择流。
因此,在修改您的 json 配置文件后:
{
"server": {
"port": "8556"
},
"sources": [
{
"image_folder": "/home/neville/Documents/convert_rtsp_video/frames",
"rtsp_mount_point": "/stream1"
},
{
"image_folder": "/path/to/another/image/folder",
"rtsp_mount_point": "/stream2"
}
]
}
并将代码修改为:
#!/usr/bin/env python3
import argparse
import json
import gi
gi.require_version('Gst','1.0')
gi.require_version('GstVideo','1.0')
gi.require_version('GstRtspServer','1.0')
from gi.repository import GObject, GLib, Gst, GstVideo, GstRtspServer
class TestRtspMediaFactory(GstRtspServer.RTSPMediaFactory):
def __init__(self, source):
GstRtspServer.RTSPMediaFactory.__init__(self)
self.source = source
def do_create_element(self, url):
image_folder = self.source.get("image_folder", None)
if image_folder:
# print('Image folder paths:', image_folder)
pipeline = f"multifilesrc location={image_folder}/%d.jpg index=1 loop=1 caps=\"image/jpeg,framerate=30/1\" ! jpegdec ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=30 ! rtph264pay name=pay0 config-interval=1 pt=96"
else:
print("Invalid source. Specify 'image_folder' in the configuration.")
return None
print("Element created:", pipeline)
return Gst.parse_launch(pipeline)
class GstreamerRtspServer():
def __init__(self, server_conf, sources):
self.rtspServer = GstRtspServer.RTSPServer()
self.rtspServer.set_service(server_conf["port"])
print("RTSP Server on port", server_conf["port"])
self.mountPoints = self.rtspServer.get_mount_points()
self.create_rtsp_streams(sources)
def create_rtsp_streams(self, sources):
for source in sources:
rtsp_mount_point = source["rtsp_mount_point"]
print(rtsp_mount_point)
factory = TestRtspMediaFactory(source)
factory.set_shared(True)
self.mountPoints.add_factory(rtsp_mount_point, factory)
self.rtspServer.attach(None)
def main(config_file):
with open(config_file, 'r') as f:
config = json.load(f)
server_conf = config.get("server", {})
sources = config.get("sources", [])
s = GstreamerRtspServer(server_conf,sources)
loop = GLib.MainLoop()
loop.run()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Run RTSP server for multiple video sources.")
parser.add_argument("--config", required=True, help="Path to the JSON configuration file.")
args = parser.parse_args()
Gst.init(None)
main(args.config)
它适用于 localhost 上的 2 个客户端(每个流一个)和远程主机上的其他 2 个客户端。
评论
0赞
NevMthw
11/20/2023
嗨,@SeB感谢您的回答,它现在似乎正在工作。但是,我对您添加的管道更改有一些疑问。该怎么办?另外,您对 gstreamer 文档或 rtsp 相关概念有什么建议吗?为了便于理解,普通的 gstreamer 文档没有太多内容。key-int-max=30
0赞
NevMthw
11/20/2023
另外,上次每次流开始时都会不断创建元素,但现在它只创建一次,那么您认为这会有什么变化?另外,我当时正在循环浏览 vlc,所以也许就是这样,.最后,这与什么有关?vlc rtsp://127.0.0.1:8556/stream1 --loop
Gst.init(None)
1赞
SeB
11/21/2023
关于我对原始管道所做的更改:我使用了带有循环选项的 multifilesrc,因为我刚刚生成了包含 3000 张图像的图像文件夹。我添加了 key-int-max=30,以便编码器每 30 帧发送一个关键帧,这有助于接收器更快地显示。Gst.init 用于初始化 gstreamer(也可以解析一些 gstreamer 参数)。对于文档,您会发现许多 from 命令,这些命令将列出主机中可用的插件和元素。使用给定元素作为参数,它将显示支持的输入/输出格式和属性:.gst-inspect-1.0
gst-inspect-1.0 x264enc
1赞
SeB
11/21/2023
您还可以在网上找到许多文档。请参见 : github.com/GStreamer/gstreamer#where-to-start
0赞
NevMthw
11/22/2023
哦,好的,非常感谢@SeB。感谢您的帮助!
评论