RidgeRun PTZ Microservice
PTZ Microservice is a microservice developed by RidgeRun. It allows you to navigate a 360-degree video through pan, tilt, and zoom (PTZ).
This microservice leverages the RidgeRun Spherical Video PTZ to make possible the selection of your region of interest within the sphere.
Briefly, this service works in this way:
- Gets an RTSP stream as an input
- Performs the PTZ depending on user instructions
- Returns the transformed video as a separate RTSP stream
Running the service
PTZ Microservice can run as a standalone application or as a docker image. The docker approach has some benefits, for example: since the application is encapsulated along with its dependencies, fewer conflicts arise in the deployment.
As a docker image
Before starting with docker support make sure you have Nvidia runtime in your system. Follow these instructions to have docker up and running in your Jetson Board.
Use prebuild image
For convenience, a docker image is available in dockerhub which as of today is available for Jetpack 6.0. Use the following command to pull it.
docker pull ridgerun/ptz-service
Build your image (Dockerfile)
If you instead want to build your image, a convenient Dockerfile is included as part of the service.
First, we need to prepare the context and include all the projects that are needed by the service.
mkdir ptz-context cd ptz-context git clone https://gitlab.ridgerun.com/open/ridgerun-microservices/ptz.git git clone https://gitlab.ridgerun.com/open/ridgerun-microservices/rrms-utils.git # Include gst-cuda, gst-rr-panoramaptz, gst-rtsp-sink, and libpanorama
The context directory should look like this:
ptz-context/ . ├── gst-cuda ├── gst-rr-panoramaptz ├── gst-rtsp-sink ├── libpanorama ├── ptz └── rrms-utils
Then, build the container image running the following command from the folder containing the Dockerfile and context directory:
sudo docker build \ --network=host \ -f ptz-context/ptz/docker/Dockerfile \ -t ridgerun/ptz-service:latest ptz-context/
Change ptz-context to your context's path and the tag (-t) to the name you want to give to your image.
Launch the container
Either you pulled the prebuilt image or you built your own, a docker container can be launched by running the following command:
docker run --runtime nvidia -it --privileged --net=host --ipc=host --name ptz-service ridgerun/ptz-service:latest
You can modify the name you want to give to your container with the option --name.
Here we are creating a container called ptz-service that will start the ptz-service application in the default address and port and use the default output resolution. If a different address, port, or output resolution has to be used, you can do it by running:
docker run --runtime nvidia -it --privileged --net=host --ipc=host --name ptz-service ridgerun/ptz-service:latest --host=HOST --port=PORT --ptz-window-size=PTZ_WINDOW_SIZE
As a standalone application
The service can also be run directly into your jetson device.
Before running the service, you should make sure you have all the dependencies installed. The instructions to do it can be found here: Spherical Video PTZ Building and Installation and: GstRtspSink plugin
Then you have to clone into your device the repository project:
git clone https://github.com/RidgeRun/ptz-service.git
The project is configured (via setup.py) to install the service with the name ptz. So to install it run:
cd ptz pip install .
Then you will have the service with the following options:
usage: ptz [-h] [--port PORT] [--host HOST] [--ptz-window-size PTZ_WINDOW_SIZE] options: -h, --help show this help message and exit --port PORT Port for server --host HOST Server ip address --ptz-window-size PTZ_WINDOW_SIZE Size of the PTZ output window in pixels. The final resolution will be (Size x Size)
After this, the service will be available under the name ptz.
Examples
As we mentioned at the beginning of the wiki. If you see PTZ Microservice as a black box, with an input and an output. It works in this way:
- Get an RTSP stream as the input.
- Performs the PTZ in the stream, depending on the user's instructions.
- Returns the stream transformed using the same protocol, RTSP, as the output.
RidgeRun developed a convenient package called rrms_utils that makes the interaction with our microservices easier.
An example of a typical application using rrms_utils to control the PTZ microservice follows.
In the example above we assume the following:
- A 360-degree RTSP Stream is being played in the URI: rtsp://192.168.100.20:4000/sream_in,
- The PTZ microservice is running in: (IP) host=192.168.100.15, port=7000
from rrms_utils.ptz import PTZ from rrms_utils.models.ptz.stream import Stream from rrms_utils.models.ptz.position import Position from rrms_utils.models.ptz.position import Zoom # Create client (by default will talk to address 127.0.0.1 and port 5020) # Change the host and port for the IP address and port of the service. client = PTZ(host=192.168.100.15, port=7000) # Configure Stream stream = Stream(in_uri="rtsp://192.168.100.20:4000/sream_in", out_port=8000, out_mapping="stream_out") set_stream_result = client.set_stream(stream) if not set_stream_result: print("Something went wrong") # Perform PTZ #Change pan and tilt position = Position(pan=50, tilt=20) set_position_result = client.set_position(position) if not set_position_result: print("Something went wrong") # Change zoom zoom = Zoom(zoom=0.5) set_zoom_result = client.set_zoom(zoom) if not set_zoom_result: print("Something went wrong")
The previous example will create an output stream at port 8000 with mapping stream_out. To display it you can use a player like VLC:
vlc rtsp://BOARD_IP_ADDRESS:8000/stream_out
Just replace BOARD_IP_ADDRESS with the IP address of the board running the service.
Code WalkTrough
Once installed, we can use the rrms_utils module to create a client that "talks" to the server created into the ptz microservices.
First, we have to import the required models and modules:
from rrms_utils.ptz import PTZ from rrms_utils.models.ptz.stream import Stream from rrms_utils.models.ptz.position import Position from rrms_utils.models.ptz.position import Zoom
Then we create the "client" using this command:
# Create client client = PTZ(host=192.168.100.15, port=7000)
By default, it will talk to address 127.0.0.1 and port 5020. In this example, we are configuring it to talk to address 192.168.100.15 and port 7000
Here we prepare the "stream" model we want to configure into the PTZ Microservice:
# Configure Stream stream = Stream(in_uri="rtsp://192.168.100.20:4000/sream_in", out_port=8000, out_mapping="stream_out")
- in_uri is the URI where the PTZ Microservice will be "listening" to get the incoming RTSP stream.
- out_port is the port where the PTZ Microservice is going to locate its output (RTSP stream transformed with the PTZ specified), in this case, port 8000
- out_mapping is the mapping where the PTZ Microservice is going to locate its output (RTSP stream transformed with the PTZ specified), in this case, /stream_out
Once the "stream" model is ready, we send the request to the PTZ Microservice, using this command:
#Send request to set stream in PTZ Microservice set_stream_result = client.set_stream(stream) if not set_stream_result: print("Something went wrong")
Using the same logic as in the stream. We can send requests to update pan, tilt, and zoom, using these commands:
# Perform PTZ #Set the Position model to send position = Position(pan=50, tilt=20) #Send the request to change pan and tilt set_position_result = client.set_position(position) if not set_position_result: print("Something went wrong") #Set the Zoom model to send zoom = Zoom(zoom=0.5) #Send the request to change the zoom set_zoom_result = client.set_zoom(zoom) if not set_zoom_result: print("Something went wrong")
Finally, we can see the output result with VLC using the commands:
#Receive the PTZ output - RTSP Stream: vlc rtsp://192.168.100.15:8000/stream_out