I have a code which uses gstreamer RTSP server and I am trying to create some rtsp streams from images/frames. The implementation works fine and converts the images into an RTSP stream.
The process is I run the script and the server is now active and then I can use the RTSP stream on another machine with my current machine IP.
Questions:
This is my code so far:
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)
This is my config.json file:
{
"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"
}
]
}
For setting the port used by the server, you would use method set_service
of the RtspServer.
You don't need to specify different ports for different clients, the RTSP server will negociate with client and manage the actual ports and transport protocols. Clients can select the stream just with the URI using stream1, stream2.
So after modifying your json config file with:
{
"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"
}
]
}
and modified your code to:
#!/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)
it works fine with 2 clients (one for each stream) on localhost and 2 other clients from a remote host.