Raspberry Pi 5 Video Capture: Camera Module V3 Video Stream Latencies. Comparing UDP, TCP, RTSP, and WebRTC
by gektor650 in Circuits > Raspberry Pi
2037 Views, 0 Favorites, 0 Comments
Raspberry Pi 5 Video Capture: Camera Module V3 Video Stream Latencies. Comparing UDP, TCP, RTSP, and WebRTC
Testing the best live-streaming options for the Raspberry Pi 5. I will compare a video live-stream latency and pick the best from the list.
We will use raspi-vid and MediaMTX to capture a video from Camera Module V3.
A video version of this instruction:
Supplies
Rasbperry PI and Camera Setup and Connect
As an operating system, I have the latest official port of Debian Bookworm. I have zero custom setup; everything can be found in the official Raspberry Stores and Raspberry PI Imager.
Let’s start with the official Raspberry Camera Documentation and try some network stream recommendations.
https://www.raspberrypi.com/documentation/computers/camera_software.html
The left menu has an rpicam-vid item. Press it, and the page will scroll down to the necessary information. We can scroll a bit down to Network Streaming, and let’s try UDP stream.
I have two terminals. One will be connected to the Raspberry PI via SSH, and the other will run commands on a local machine.
Capture TCP Video Stream With a Default Codec
https://www.raspberrypi.com/documentation/computers/camera_software.html#tcp
The command to stream on Raspberry PI:
rpicam-vid -t 0 --width 1280 --height 720 --framerate 30 --inline --listen -o tcp://0.0.0.0:5556
The Raspberry PI will make a stream to its own port (I set 5556); any client can connect to it and receive a stream
As you can see, it sends some frames, and it stops and waits for a listener to receive the stream.
To show a stream on a laptop, we can use:
ffplay tcp://RASPBERRY_PI_IP_HERE:5556 -vf "setpts=N/30" -fflags nobuffer -flags low_delay -framedrop
The delay for TCP with a native codec is 0.5 seconds. (500 milliseconds)
Capture UDP Video StreamWith a Default Codec
https://www.raspberrypi.com/documentation/computers/camera_software.html#udp
The command to start a stream on a Raspberry PI is:
rpicam-vid -t 0 --width 1280 --height 720 --framerate 30 --inline -o udp://LAPTOP_IP_HERE:5555
We must replace LAPTOP_IP_HERE with a laptop IP address (not the Raspberry PI).
A port could be arbitrary. I used 5555.
As we can see, the Raspberry PI sends some frames to the laptop.
To play the video, we can run the ffplay command on the laptop:
ffplay udp://RASPBERRY_PI_IP_HERE:5555 -fflags nobuffer -flags low_delay -framedrop
Now, it’s time to see the performance.
I have a real-time camera that records the timer and sends a stream through the local network.
The UDP video delivery method has a 3.4-second delay. (3400 milliseconds)
Capture TCP Video Steam With a Libav Codec (mpegts)
It’s a different video codec, and it could affect delays.
The command to run on a Raspberry PI:
rpicam-vid -t 0 --width 1280 --height 720 --framerate 30 --codec libav --libav-format mpegts --libav-audio -o "tcp://0.0.0.0:1234?listen=1"
The command to play it on a laptop:
ffplay tcp://RASPBERRY_PI_IP_HERE:1234 -vf "setpts=N/30" -fflags nobuffer -flags low_delay -framedrop
Surprisingly, LibAv has a huge delay—approximately 10.5 seconds. (10500 milliseconds)
We had half a second with a default codec and TCP, but now it is ten and a half.
Capture UDP Video Steam With a Libav Codec (Mpegts)
The command to run on a Raspberry PI:
rpicam-vid -t 0 --width 1280 --height 720 --framerate 30 --codec libav --libav-format mpegts --libav-audio -o "udp://REPLACE_WITH_LAPTOP_IP:5555"
And player for a laptop:
ffplay tcp://RASPBERRY_PI_IP_HERE:1234 -vf "setpts=N/30" -fflags nobuffer -flags low_delay -framedrop
And now we have only half a second delay for UDP. (500 milliseconds)
These results are pretty strange. With the native codec, we had a huge delay in UDP and a small delay in TCP; with LibAV, we have the opposite.
Raspberry PI MediaMTX Setup
Finally, we are getting closer to our Raspberry PI winner of the stream latency: MediaMTX. This software can send a stream through all the protocols mentioned previously in the video and a few more. Let’s start with the set-up.
To install it, I need to do really simple steps:
- First, open the release page on the GitHub.
- Second, copy a link to an ARM64 archive. It’s essential to choose a proper version here.
- Third, create a folder for it on the Raspberry PI.
mkdir mediamtx && cd mediamtx
- Fourth, download it using the WGET command (find the latest link on GitHub).
wget https://github.com/bluenviron/mediamtx/releases/download/v1.7.0/mediamtx_v1.7.0_linux_arm64v8.tar.gz
- Fifth, unarchive it to the same folder.
tar -xvzf mediamtx_v1.7.0_linux_arm64v8.tar.gz
- Sixth, open the YML configuration file for editing.
nano mediamtx.yml
- Seventh, scroll down and paste these configurations.
cam1:
runOnInit: bash -c 'rpicam-vid -t 0 --camera 0 --nopreview --codec yuv420 --width 1280 --height 720 --inline --listen -o - | ffmpeg -f rawvideo -pix_fmt yuv420p -s:v 1280x720 -i /dev/stdin -c:v libx264 -preset ultrafast -tune zerolatency -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH'
runOnInitRestart: yes
In a nutshell, the MediaMTX software will run this command in a bash.
Next, it asks the RPICAM-VID command (the same as we dealt with before) to send a stream to the FFMPEG.
And FFMPEG will send it to the MediaMTX via RTSP protocol, but locally.
We can save the configuration and run MediaMTX.
./mediamtx
The very first prints of it will have helpful information about protocol and ports that we can use.
Capture RTSP Stream Using MediaMTX
Run MediaMTX from the previous step:
./mediamtx
Open a video player:
vlc rtsp://RASPBERRY_PI_IP_ADDRESS_HERE:8554/cam1
We have a delay of 1.3-1.4 seconds with this video stream. (~1300 milliseconds)
Capture WebRTC Stream Using MediaMTX
Finally, we are closer to our winner. Let’s go back to the console and grab a port for WebRTC. In my case, it’s 8889.
To play it, I'll open this stream in the browser:
http://RASPBERRY_PI_IP_HERE:8889/cam1
In a moment, we have a stream.
Zoom out, and let’s review the delay.
It has an awesome 0.2 delay, which is a winner across all tests. (~200 milliseconds)