Video streaming from Raspberry Pi with UV4L

Here I describe how to set up secure video streaming using Raspberry Pi and a dedicated camera with UV4L. This post is written in tutorial–like form and the set–up presented here will be used in my other projects.

Retrieving video from camera is not that hard. For this you can use UV4L. It is an open source initiative which aims to deliver user space for real or virtual video input or video output (after UV4L project website). In other words, it will create a device inside /dev/ which can be directly accessed to get video from it. So let’s jump straight to installing the required software.

The other possibility is to use update-rc.d to start UV4L server at boot using udpate-rc.d. This is how you would do this:

1

sudo update-rc.d-fuv4l_raspicam enable

Also do stop UV4L from starting at boot you would do something like this:

1

sudo update-rc.d-fuv4l_raspicam disable

Enabling camera interface

There is also a preliminary step which has to be done before working with the camera. The camera interface has to be turned on. Unless it is already turned on you have to use raspi-config command, like this:

1

sudo raspi-config

There you can navigate through the interface and set camera interface to Enabled. After that reboot RPi and you are good to go. I assume that the camera is already connected to the mini computer.

Accessing UV4L web server

Now, you can test if the UV4L is working properly. If you have installed uv4l-server then there is a small web server which will allow you to test UV4L installation. By default the server is working on port number 8080. To test the server you need to enter this URL address inside your browser:

RPI_LOCAL_IP:8080

if you are accessing RPi from local network at a different computer. The RPI_LOCAL_IP is IP address of Raspberry PI, probably but not limited to something like this 192.168.0.x.

or

localhost:8080

if you are running it on your Raspberry Pi. However, I recommend testing it on a different computer.

You should see something similar to:

what you are interested in are two tiles: “MJPEG/Stills stream” and “Control panel”. Let’s start with the later. If you click on the nice two gears you should see something like this:

You can set resolution of the video and some other parameters like brightness or rotation. In my case, I had to rotate the image because I have mounted the camera upside down. After saving the configuration go to MJPEG/Stills stream. There you will see a live stream from the camera. There is one thing worth noting, when you have live stream active, it is open on another tab in your browser, you will not be able to save the configuration. First you have to close the live stream, save configuration and then reopen the video tab.

The MJPEG/Stills stream is used to display live stream. What is nice about it is that you can use a direct URL for this http://localhost:8080/stream.

Securing UV4L

Since sharing live stream publicly is not necessarily a good idea we should do two things:

add some authorization, so people who do not know the password won’t be able to log into uv4l server and change something,

encrypt the connection itself, thus even if someone is sniffing your network, the traffic will be safe.

Let’s start with the first one. U4VL can have up to three predefined user types:

admin, this user can to everything, change parameters, start live stream, everything what UV4L is capable of,

config, he can change configuration file,

user, he can only start live stream without modifying the parameters.

The password is not stored in open form it is encrypted as md5 hash. To create a md5 hash you can use Python and those lines:

Python

1

2

3

4

5

importhashlib

importgetpass

password=getpass.getpass("Enter password: ");

hashlib.md5(str.encode(password)).hexdigest();

For example, hash for password ‘mysecretpassword’ will be ‘4cab2a2db6a3c31b01d804def28276e6’.

When you generate those three password you can edit the configuration file. It can be found under /etc/uv4l/uv4l-raspicam.conf. Inside this file you should find lines:

1

2

3

server-option=--user-password=AAAAA

server-option=--admin-password=BBBBB

server-option=--config-password=CCCCC

If there are commented out remove ‘#’ at the beginning of each line and substitute AAAAA, BBBBB, CCCCC with md5 hashes. Also alter this line

1

server-option=--md5-passwords=no

to

1

server-option=--md5-passwords=yes

After restarting uv4l service the server will be protected. The next thing is to use HTTPS instead of HTTP to encrypt the traffic. This can be done by altering three lines:

1

2

3

4

### HTTPS options:

server-option=--use-ssl=yes

server-option=--ssl-private-key-file=/etc/uv4l/privkey.key

server-option=--ssl-certificate-file=/etc/uv4l/cert.pem

First one says that HTTPS should be used and the last two are paths to SSL private key and certificate respectively. There are two ways of obtaining the certificate: you can generate a self-signed one but each web browser will warn about that saying that this kind of certificate is untrusty but it will work! You can generate it with following commands:

Generate and save CSR (Certificate Signing Authority), it will prompt you for passphrase to secure the private key which will be saved to privkey.pem.

1

sudo openssl req-new>new.ssl.csr

Generate key for signing:

1

sudo openssl rsa-inprivkey.pem-out new.cert.key

Generate certificate and key. The certificate will be valid for 100 days:

But it requires you to have registered domain EXAMPLE.COM. Also you should pass a valid email EMAIL@EXAMPLE.COM. Renewing a certificate is also very straightforward:

1

letsencrypt rewnew

The certificates can be found under /etc/letsencrypt/live/EXAMPLE.COM/. You should be interested in files cert.pem and privkey.pem (remember to change its name to privkey.key to match the configuration in configuration file).

Additional configuration

To set up different port change following line

1

server-option=--port=8080

Default encoding, resolution and frame rate can be changed with those lines:

1

2

3

4

encoding=mjpeg

width=640

height=480

framerate=30

Some image parameters like sharpness, contrast, brightness and saturation can be adjusted with:

1

2

3

4

sharpness=0

contrast=0

brightness=50

saturation=0

Also if you would like to rotate the image you can pass the number of degrees:

1

rotation=180

Or you can flip the image horizontally or vertically:

1

2

hflip=no

vflip=yes

There are many more options. Just remember those are default parameters and can by changed with web interface!

Thanks for the instructions for creating selfsigned SSL certificates. When using Chromium on a Pi 3B, I get the following errors when trying to call another Pi 3B (Both are running UV4L and I am using the WebRTC stream page with peer being 192.168.2.29):

I have to admit I am a beginner at this but any advice would be appreciated. The Common Name for each certificate on each machine is their respective local IP addresses. I am trying to get it to work within the LAN first and then perhaps across the Internet later. I haven’t had any luck with Jitsi. I got the WebRTC stream page to work internally. I know if it was to go over the Internet, I would have to port forward on each end. I would be able to do so. Anyway, comments, suggestions, direction would be helpful. Thanks. 🙂

You can use selfsigned certificate with Chrome or any other browser. It will say that it is insecure but it is. The reason behind it is that each browser is checking a chain of relationships between certificates. Since you are generating a certificate by yourself the Chrome is unable to verify the CA of the certificate because it simply doesn’t know it. Said that, the traffic is safe, still encrypted but it will produce an alert in any web browser. Could you please tell me if you are able to visit the site or it terminates the connection completely?
What I can recommend is using a Let’s Encrypt certificate. You have to portforward the service ports (like 80 or 443). There are scripts which will automate the process of renewing the certificate every 90 days. You have a set of instruction in my blog post where I describe how to do this. Hope it helps!
However, if you do this completely locally then you have to bear the error message.

I cannot connect to the site at all. When I try to connect, nothing happens. I can connect locally if the remote peer is the respective IP address of the Pi I am on.

Thanks for the info on the SSLs. (I can try the other option from Let’s Encrypt perhaps later.) I wasn’t sure if it was rejecting the connection because it did not approve of the certificates or not and this is why the connection would not happen. Below is the config file I have setup for uv4l-raspicam.conf (I placed the SSL key and pem files in a different folder than you stated in your instructions) See anything that might cause a problem?

# You can use this file to override the built-in defaults of the options in
# the following modules:
# – UV4L core
# – raspicam driver
# – Streaming Server module.
#
# To get a full list of the available options with their defaults and
# descriptions, please refer to the ‘uv4l’, ‘uv4l-raspicam’ and ‘uv4l-server’
# manual pages, or alternatively type the following command:
#
# uv4l –driver raspicam –help –driver-help –server-help
#
# This file is parsed by uv4l through the ‘uv4l_raspicam’ system service script,
# if installed. If you are not using the service facility to load the raspicam
# driver, then to instruct uv4l to parse this file you must explicitly pass its
# path to the ‘–driver-config-file’ driver option and/or to the ‘–config-file’
# options, for example (in one line):
#
# uv4l […] –driver raspicam –config-file=/path/to/uv4l-raspicam.conf \
# –driver-config-file=/path/to/uv4l-raspicam.conf
#
# NOTE: multi argument options must be specified with one argument per line,
# e.g the command line option ‘–min-object-size 80 120’, in this file becomes:
# min-object-size = 80
# min-object-size = 120
# another example:
# server-option = –webrtc-stun-urls=stun:stun.l.google.com:19302
# server-option = –webrtc-stun-urls=stun1.l.google.com:19302
#
# NOTE: to comment out an option override put a # at the beginning of the
# corresponding line. Remember that any commented out option that may appear
# on a standard installation of this file is *not* necessarily specified with
# its default built-in value.

### path to a separate config file that will be parsed by the streaming server
### module directly when it’s loaded,
### in which you are allowed to specify all the streaming server options
### listed below in the short form “option=value” instead of the longer
### “–server-option = –option=value” form that you must use
### in this configuration file.
#server-config-file = #path

Wow. Please do not past such long config files. Thanks!
I have one other idea. Could you show me the file permissions and ownership of your cert files? I think that it might be the issue. Also what says uv4l log file?

“Now it’s the time to install all the required certificates in your browser’s trusted certificate store. There are formal ways to do this from within the browser, but perhaps the most practical way is the following. Open the browser and visit the following three URL‘s one at a time, in this exact order: https://:8889 (blank page), https://:8080 and https://. For each of the three contacted HTTPS servers above the browser will ask you to add a security exception to the self-signed SSL server’s certificate, so that it can whitelist them once for any future use. You must accept the certificates before doing anything else.”

Going to each Pi’s /stream/webrtc website from the other Pi and then accepting the “dangerous” site seemed to get it to work somewhat though the local broadcast is not showing and only one channel of audio is working (dangerous site setting in Chromium is turned on). May be tied to the SSL certificates somehow on each again? Don’t know. Any thoughts?

“Now it’s the time to install all the required certificates in your browser’s trusted certificate store. There are formal ways to do this from within the browser, but perhaps the most practical way is the following. Open the browser and visit the following three URL‘s one at a time, in this exact order: https://:8889 (blank page), https://:8080 and https://. For each of the three contacted HTTPS servers above the browser will ask you to add a security exception to the self-signed SSL server’s certificate, so that it can whitelist them once for any future use. You must accept the certificates before doing anything else.”

Going to each Pi’s /stream/webrtc website from the other Pi and then accepting the “dangerous” site seemed to get it to work somewhat though the local broadcast is not showing and only one channel of audio is working. May be tied to the SSL certificates somehow on each again? Don’t know. Any thoughts?

Could you do a quick test for me? Please run just the stream via HTTPS and tell me if you can see anything.
Giving all permissions to certificate files is not necessary the best idea. But maybe it is not the case here. If you run the test get back here with results and we will figure out what to do next.

Thanks! To just eliminate one thing please run only the video stream not the Web RTC. To be honest I never played with Web RTC on Raspberry Pi. This way we will be sure that video streaming is source of the problem or not.

Thanks, I managed to sign the keys and I didn’t have any error messages, but now when i tried to connect with https i got a secure connection failed stating that: “SSL_ERROR_RX_RECORD_TOO_LONG”. At least the keys did something but I still am unable to connect to UV4L via https connection. Any advice?

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.