Secure Webcam streaming with MJPG-Streamer on a Raspberry Pi
Installing the MJPG-Streamer Video Streamer->

There are a number of blogs purporting to explain how to stream the video output of a web camera connected to a Raspberry Pi. As is often the case, quite a few are out of date. That is the fate of all instructions, things change. So I cannot say how long this post, showing how I added MJPG-Streamer to my home automation server, will be useful.

In the last few weeks, I have revisited the use of the video streamer. I hope to update this post which, as I feared, is definitely long in the tooth. In the meantime, I would suggest reading the section named Installing the MJPG-Streamer Video Streamer in my October 17, 2021 post Additional Servers on a Raspberry Pi Based Home Automation System. Basically, that section updates many parts of this old post, namely sections 3 - Security, 5 - A New Script and 6 - Remote Start and Stop.
October 27, 2021

Table of Contents

  1. Hardware
  2. Software
  3. Security
  4. Other Clients: VLC, Kodi, and Domoticz
  5. A New Script
  6. Remote Start and Stop
  7. Slow Camera

Hardware toc

A Raspberry Pi Model B+ v1.2 is hosting my home automation system based on Domoticz. This is the fourth iteration (July 2014) of the initial single board computer from the Raspberry Pi Foundation. It uses a Broadcom BCM2835 system on a chip (SoC) along with 512 MB of on board RAM shared between the CPU (ARM1176jZF-S: 32 bit, single core, 700 MHZ, ARM v6) and the GPU (Broadcom BCM2837). Since the Raspberry Pi is operating as a headless server, the minimum 16 MB of RAM is allocated to the GPU. This was the first board to have four USB 2.0 ports and to use a microSD card for storage. While there is a 10/100 Mbit/s Ethernet port on the board, a WiFi dongle is used for connection to the local area network.

The operating system is Raspbian Jessie a version of Debian 8 tweaked for the Raspberry Pi. There is a newer version available but there were problems associated with the libssl1 and libssl-dev libraries when trying to install Domoticz with Stretch (Debian 9). I could not surmount them. It does seem that this known to the developers of Domoticz, see SSL protocol issue #2062. So I had to use last version of Jessie Lite which is still available from the Raspberry Pi Foundation.

The latest version of Domoticz (version 4.9700) does work with the latest version of Raspbian Stretch Lite (Version: June 2018, Kernel version: 4.14).
However, I ran into problems with the secure connection of the video stream as described below. For some reason, I can get snapshots through the secure lighttpd proxy server but not the video stream. If I ever solve this mystery, I will update this post.
August 4, 2018.

Image of Logitech C270 Webcam The camera is a Logitech HD Webcam C270 bought a number of years ago for use with a portable computer. It is capable of streaming video at a resolution of 720p (1280x720 pixels which is a 16:9 aspect ratio). The producer does not provide Linux drivers for the camera, but it does work with a humble Raspberry Pi because of V4L2 (Video4Linux version 2).

After plugging the camera in a USB port, and waiting a short while, it shows up as a USB device.

pi@domo:~ $ lsusb Bus 001 Device 005: ID 0bda:8179 Realtek Semiconductor Corp. RTL8188EUS 802.11n Wireless Network Adapter Bus 001 Device 004: ID 046d:0825 Logitech, Inc. Webcam C270 Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Video4Linux is included in Raspbian so we can use it to ascertain which video formats the webcam supports.

pi@domo:~ $ v4l2-ctl --list-formats ioctl: VIDIOC_ENUM_FMT Index : 0 Type : Video Capture Pixel Format: 'YUYV' Name : YUYV 4:2:2 Index : 1 Type : Video Capture Pixel Format: 'MJPG' (compressed) Name : Motion-JPEG

The fact that the C270 supports MJPG format is very good. It means that the camera itself compresses each JPG image (frame) before passing it on to the computer over the USB link. Not all webcams support the MJPG format. In that case, the Raspberry Pi will have to perform compression of the images before streaming them over HTTP. This task overwhelms the single core Raspberry Pi Model B+. More on that later.

Software toc

The obvious source for instructions on installing MJPG-Streamer is the repository for the package. The latter is no longer hosted on SourceForge. I installed a forked version by Liam Jackson (I hope I am not making a mistake with the name) on github. Mr Jackson has simplified installation considerably.

pi@domo:~ $ sudo apt-get install cmake libjpeg8-dev ... After this operation, 19.9 MB of additional disk space will be used. Do you want to continue? [Y/n] y ... pi@domo:~ $ wget https://github.com/jacksonliam/mjpg-streamer/archive/master.zip ... pi@domo:~ $ unzip master.zip ... pi@domo:~ $ cd mjp*g-* pi@domo:~/mjpg-streamer-master $ cd mjpg-* pi@domo:~/mjpg-streamer-master/mjpg-streamer-experimental $ make ... pi@domo:~/mpjg-streamer-master/mjpg-streamer-experimental $ sudo make install ... pi@domo:~/mjpg-streamer-master/mjpg-streamer-experimental $ cd $home

That completes the basic installation. The executable is placed in the /usr/local/bin/ directory which is included in the system path environment variable. The input and output plugins are in the /usr/local/lib/mjpg-streamer directory, the built-in web server pages are in the /usr/local/share/mjpg-streamer/www directory.

pi@domo:~ $ which mjpg_streamer /usr/local/bin/mjpg_streamer pi@domo:~ $ ls /usr/local/lib/mjpg-streamer input_file.so input_raspicam.so output_file.so output_rtsp.so input_http.so input_uvc.so output_http.so output_udp.so pi@domo:~ $ ls /usr/local/share/mjpg-streamer/www bodybg.gif javascript.html jquery.ui.widget.min.js cambozola.jar javascript_motiondetection.html LICENSE.txt control.htm javascript_simple.html rotateicons.png example.jpg java_simple.html sidebarbg.gif favicon.ico jquery.js spinbtn_updn.gif favicon.png jquery.rotate.js static.html fix.css JQuerySpinBtn.css static_simple.html functions.js JQuerySpinBtn.js stream.html index.html jquery.ui.core.min.js stream_simple.html java_control.html jquery.ui.custom.css style.css java.html jquery.ui.tabs.min.js videolan.html

I did not bother setting up the LD_LIBRARY_PATH environment variable as described in the README page. Starting mjpg_streamer require defining one or more input plugin and an output plugin. This is explained in the Usage paragraph. I used the input_uvc and the output_http plugings.

pi@domo:~ $ mjpg_streamer -i "input_uvc.so --help" MJPG Streamer Version.: 2.0 --------------------------------------------------------------- Help for input plugin..: UVC webcam grabber --------------------------------------------------------------- The following parameters can be passed to this plugin: [-d | --device ].......: video device to open (your camera) [-r | --resolution ]...: the resolution of the video device, can be one of the following strings: QQVGA QCIF CGA QVGA CIF PAL VGA SVGA XGA HD SXGA UXGA FHD or a custom value like the following example: 640x480 [-f | --fps ]..........: frames per second (activates YUYV format, disables MJPEG) [-q | --quality ] .....: set quality of JPEG encoding [-m | --minimum_size ].: drop frames smaller then this limit, useful if the webcam produces small-sized garbage frames may happen under low light conditions [-e | --every_frame ]..: drop all frames except numbered [-n | --no_dynctrl ]...: do not initalize dynctrls of Linux-UVC driver [-l | --led ]..........: switch the LED "on", "off", let it "blink" or leave it up to the driver using the value "auto" [-t | --tvnorm ] ......: set TV-Norm pal, ntsc or secam [-u | --uyvy ] ........: Use UYVY format, default: MJPEG (uses more cpu power) [-y | --yuv ] ........: Use YUV format, default: MJPEG (uses more cpu power) [-fourcc ] ............: Use FOURCC codec 'argopt', currently supported codecs are: RGBP ... pi@domo:~ $ mjpg_streamer -o "output_http.so --help" MJPG Streamer Version.: 2.0 --------------------------------------------------------------- Help for output plugin..: HTTP output plugin --------------------------------------------------------------- The following parameters can be passed to this plugin: [-w | --www ]...........: folder that contains webpages in flat hierarchy (no subfolders) [-p | --port ]..........: TCP port for this HTTP server [-l ] --listen ]........: Listen on Hostname / IP [-c | --credentials ]...: ask for "username:password" on connect [-n | --nocommands ]....: disable execution of commands ---------------------------------------------------------------

Putting those two together, I started the streamer with the following command. Streaming is to be done at the full resolution of the camera but at a relatively slow 10 frames per second. If the -n option is not specified, there will be quite a few error messages, but streaming will work. The TCP port 8085 was specified for output to make sure there was no interference with anything else.

pi@domo:~ $ /usr/local/bin/mjpg_streamer -i "/usr/local/lib/mjpg-streamer/input_uvc.so -n -f 10 -r 1280x720" \ > -o "/usr/local/lib/mjpg-streamer/output_http.so -p 8085 -w /usr/local/share/mjpg-streamer/www" MJPG Streamer Version.: 2.0 i: Using V4L2 device.: /dev/video0 i: Desired Resolution: 1280 x 720 i: Frames Per Second.: 10 i: Format............: JPEG i: TV-Norm...........: DEFAULT o: www-folder-path......: /usr/local/share/mjpg-streamer/www/ o: HTTP TCP port........: 8085 o: HTTP Listen Address..: (null) o: username:password....: disabled o: commands.............: enabled

Using top in another ssh session, I could see that mjpg_streamer was using less than 1% of CPU time and less than 2% of the available RAM when idle.

pi@domo:~ $ top --------------------------------------------------------------------------------- top - 12:38:34 up 13:53, 2 users, load average: 0.19, 0.20, 0.17 Tasks: 90 total, 1 running, 89 sleeping, 0 stopped, 0 zombie %Cpu(s): 1.0 us, 3.1 sy, 0.0 ni, 95.5 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st KiB Mem: 493252 total, 158916 used, 334336 free, 25176 buffers KiB Swap: 102396 total, 0 used, 102396 free. 86032 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 23822 pi 20 0 5100 2488 2148 R 1.3 0.5 1:50.51 top 694 root 20 0 162388 13256 10668 S 1.0 2.7 8:14.22 domoticz 24893 pi 20 0 49952 9040 8680 S 0.7 1.8 0:15.07 mjpg_streamer 364 avahi 20 0 3984 2704 2380 S 0.3 0.5 0:14.96 avahi-daemon

I then looked at the video stream from my desktop machine with a web browser at the following address: http://domo.local:8085/stream_simple.html. On my tablets I have to use the explicit IP address of the Raspberry Pi, because Android doesn't seem to use zero-configuration networking (avahi). As can be seen below, the streamer used a bit more than 8% of CPU time and no more memory while active.

top - 12:40:35 up 13:55, 2 users, load average: 0.37, 0.20, 0.16 Tasks: 93 total, 1 running, 92 sleeping, 0 stopped, 0 zombie %Cpu(s): 1.4 us, 7.1 sy, 0.0 ni, 85.7 id, 0.0 wa, 0.0 hi, 5.7 si, 0.0 st KiB Mem: 493252 total, 162780 used, 330472 free, 25140 buffers KiB Swap: 102396 total, 0 used, 102396 free. 86032 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 24893 pi 20 0 49952 9040 8680 S 8.2 1.8 0:05.06 mjpg_streamer 23822 pi 20 0 5100 2488 2148 R 1.6 0.5 1:48.06 top 694 root 20 0 162388 13256 10668 S 1.0 2.7 8:12.03 domoticz 373 mosquit+ 20 0 5504 3772 3356 S 0.7 0.8 1:57.21 mosquitto

These are very good results which means that it should certainly be possible to run the video streamer as a daemon even with the relatively under-powered Raspberry Pi B+.

I should point out that the first time I looked at the video with the browser, the view was greatly distorted but the camera was clearly connected. The streamer can be stopped with the CtrlC combination. I restarted the streamer (it took a couple of tries) and then the image displayed on the desktop was good.

There will be three HTTP servers running on the Raspberry Pi: There is clearly a potential for conflict here and ports have to be assigned with care. This is why the default 8080 port was not used to stream the webcam video.

Security toc

The main reason to stream the video from the Webcam connected to my home automation server is to monitor the inside of the house when away. When exposing a local network to the mean and cold outside world, it is important to think about security. I seem to remember reading somewhere that IP cameras were among the most common cause of security breaches on the Internet and that's precisely what's being done here, turning a webcam into an IP camera.

At the minimum, the video streamer password protection must be enabled. Look at the -c or --credentials options of the HTTP output plugin.

pi@domo:~ $ mjpg_streamer -i "/usr/local/lib/mjpg-streamer/input_uvc.so -n -f 10 -r 1280x720" \ > -o "/usr/local/lib/mjpg-streamer/output_http.so -p 8085 -w /usr/local/share/mjpg-streamer/www/ \ > -c stream:michel" MJPG Streamer Version.: 2.0 i: Using V4L2 device.: /dev/video0 i: Desired Resolution: 1280 x 720 i: Frames Per Second.: 10 i: Format............: JPEG i: TV-Norm...........: DEFAULT o: www-folder-path......: /usr/local/share/mjpg-streamer/www/ o: HTTP TCP port........: 8085 o: HTTP Listen Address..: (null) o: username:password....: stream:michel o: commands.............: enabled

When connecting to the MJPG_Streamer HTTP server there will now be a login window where the specified user name and password must be defined.

MJPG-Streamer login screen

Alternatively, the user name and password can be specified in the URL:
In this particular example it would be stream:michel@ (or stream:michel@domo.local)

This first line of defence is not very secure. The user name and password will be sent as plain text. It would be preferable to use TLS encryption. Unfortunately, this is not quite as simple as one would wish because the mjpg_streamer server does not handle the HTTPS protocol. I have found two potential workarounds but I have tested only one.

The untested solution is "stunnel [which] can be used to add TLS functionality to commonly used Inetd daemons like POP-2, POP-3, and IMAP servers, to standalone daemons like NNTP, SMTP and HTTP, and in tunneling PPP over network sockets without changes to the source code." Here a couple of references on the subject.

  1. Secure webcam streaming with mjpg-streamer and stunnel by Cristiano Urban (Cris' hacks).
  2. Securing mjpg streamer by Siva Dirisala.

The other solution, the one I am using, relies on the much greater capabilities of the lighttpd HTTP server also running on the Raspberry Pi. For those few unfortunate persons that have not read all my previous posts, it serves OTA firmware updates to the ESP8266 based switches used in my house. The idea is simple, access lighttpd with a secure HTTPS connection at a specified port and let that server pass on the request to the mjpg_streamer on its unsecured TCP port. I had often seen the terms "proxy" and "reverse proxy" but I had never touched those things. I got it to work and its deceptively easy, but do not ask me anything about it. This is the result of much searching on the web into the wee hours of the morning and much trial and error. I feel like one of those proverbial monkeys that manage to bang out a Shakespeare sonnet on a keyboard.

On December 3, 2018 I announced that I was no longer trying to set up a reverse proxy with LIGHTTPD to securily stream webcams (see lighttpd with Raspbian Stretch in Not Everything Works if you are curious about that). At that time I decided that such streaming would be done with a VPN.
Lately (October 2021), I have revisited the subject. It turns out an NGINX reverse proxy is easily set up. You can see the details in the section entitled Secured Streaming in Additional Servers on a Raspberry Pi Based Home Automation System. As said at the start of this old post, I would suggest reading the whole section named Installing the MJPG-Streamer Video Streamer which updates many parts of this post.

Not much needs to be done; just a couple of additions to the lighttpd configuration file. First add the proxy module in the server modules at the start of the file and then add a proxy server definition at the end of the file.

pi@domo:~ $ sudo nano /etc/lighttpd/lighttpd.conf
server.modules = ( "mod_access", "mod_alias", "mod_compress", "mod_proxy", <-- add this module "mod_redirect", # "mod_rewrite", ) ... add this server socket definition at the end: # reverse proxy to provide https wrapper around mjpg_streamer # that is listening on TCP port 8085 at IP # $SERVER["socket"] == ":4433" { ssl.engine = "enable" ssl.pemfile = "/home/pi/domoticz/server_cert.pem" proxy.server = ( "" => ( ("host" => "", "port" => 8085) ) ) }

Being the lazy sort, I used the self signed certificate that was installed with the domoticz server, but any signed SSL certificate can be used. If lighttpd were on another computer on the local network, then the host address should be changed to the IP of the Raspberry Pi on which MJPG-Streamer is running. Since both servers are on the same machine, I used the localhost IP number. It will not be necessary to modify this configuration file should the IP of Rapsberry Pi change.

Check that the configuration file is correct and once it is, restart the server for the changes to take effect. Might as well verify that lighttpd is running correctly after restarting it.

pi@domo:~ $ lighttpd -f /etc/lighttpd/lighttpd.conf -t Syntax OK pi@domo:~ $ pi@domo:~ $ sudo systemctl restart lighttpd.service pi@domo:~ $ sudo systemctl status lighttpd.service ● lighttpd.service - Lighttpd Daemon Loaded: loaded (/lib/systemd/system/lighttpd.service; enabled) Active: active (running) since Tue 2018-04-10 15:42:14 ADT; 5min ago Process: 1275 ExecStartPre=/usr/sbin/lighttpd -t -f /etc/lighttpd/lighttpd.conf (code=exited, status=0/SUCCESS) Main PID: 1284 (lighttpd) CGroup: /system.slice/lighttpd.service └─1284 /usr/sbin/lighttpd -D -f /etc/lighttpd/lighttpd.conf Apr 10 15:42:14 domo lighttpd[1275]: Syntax OK Apr 10 15:42:14 domo systemd[1]: Started Lighttpd Daemon.

Time to check that the proxy set up works. On the desktop computer connected to the same network as the Raspberry Pi, I pointed the web browser to the following address: (or https://domo.local:4433/). Because a self signed SSL certificate is used, the browser will baulk and it will be necessary to create an exception. This only needs to be done once per browser. From then on, the mjpg_streamer web pages should be reached at once through a secure connection. Chromium displays an ominous warning about the link being unsecure.

MJPG-Streamer About page in Chromium with security exception enabled

Not to worry, the communications between the web browser and mjpg_streamer is encrypted; the browser just does not like the unsigned certificate.

All this has been done locally. To access the video stream from outside the local area network, a dynamic DNS address and the TCP port used by lighttpd (not the unencrypted port used by MJPG-Streamer) needs to be forwarded by the LAN router. I have already discussed all this before 3. Creating a dynamic domain name, 4. Updating the IP Destination Address, and 5. Forwarding TCP Ports in a previous post.

Then go to the router and forward a TCP port say 4433 for simplicity or whatever you want as long as there is no clash, to the IP address and the HTPPS port to which the lighttpd proxy is listening. In my case it is and 4433.

My dynamic DNS address to reach the Raspberry Pi is modom.twiligthparadox.com. So to see the video streamed from mpg_streamer, I enter either of the following addresses in a web browser.
  https://modomo.twilightparadox.com:4433/stream.html. As to be expected, I had to enable an exception in Firefox because of the self signed certificate and the browser displayed a warning over the HTTPS secure icon.

MJPG-Streamer About page in Firefox with security exception enabled

As said before, the communications between the web browser and mjpg_streamer is encrypted.

Other Clients: VLC, Kodi and Domoticz toc

Here quick explanations on how to access the video stream from three clients that are not web browsers.


As explained in the streamer documentation, the video can be viewed with VLC from VideoLAN. In the GUI, click on the Media menu at the top of the window and then select Open Network stream... (Ctrl-N). Enter the following URL:

A dialog window will pop up asking for the user name and password. Or you can specify the user name and password in the URL.


The application can also be launched from a terminal:

michel@hp:~$ vlc

On my desktop I can use local host name, domo.local, instead of the IP address. On my Android tablets and TV box, this is not possible and I must use the explicit numeric IP address.

Of course, if I wanted to use the encrypted stream, I would use the HTTPS protocol with port 4433. And if I were doing this from a computer not connected to my local network, I would use the dynamic domain name.


Since I am paranoid, I will probably not include the password and user name in the URL thus ensuring that these would not be transmitted in cleartext at any point.


To show the stream in Kodi, I simply followed the instructions on the Wiki. It could not be simpler in principle. Since Kodi is on an Android device on the local network, I created a simple text file, named webcam.strm, with the following content.


The filename can be anything reasonable I assume, but the extension must remain .strm I think.

The hardest bit was to copy that file on the device storage. I have used two different methods. The simplest is to copy the file from my desktop to a USB stick and then connect the latter to the Android device and copy the file into a subdirectory of the SDCard directory which can later be accessed from Kodi.

The other method was to install and start an SSH/SFTP Server and then use Filezilla to copy over the file. I used SSH/SFTP Server - Terminal by Banana Studio. I logged in on port 2222 as user ssh without a password using the SFTP - SSH File Transfer Protocol and it worked without a problem. And there was no need to walk up and down the stairs.

Which ever way the strm file is created on the device, it is best to add it to your Favourites for quick and easy access. Use the Kodi menu system to find the file, highlight it and press the C to add it to Favourites.

I really don't know much or anything at all to be honest, about Android TV devices and even less about Kodi so enough said.


As far as I know, Domoticz does not do video streaming. I only say that because, every now and then I see someone asking how to go about it. When the video stream icon is pressed, I believe that Domoticz is merely transmitting a sequence of snapshots. I do use the fact that the home automation system does take a snapshot with a connected camera when a specific event occurs and will send that picture by email. I have set it up so that that picture is taken about 2 seconds after a light is turned on or off (on is better). It's a cheap way to verify that everything is working when I am away.

I used to do that with uvccapture as detailed in the Domoticz Wiki page entitled Camera Setup. I don't want to install uvccapture since mjpg_streamer will presumably control the web cam at all times. That is no problem because, the video streamer will take snapshots. Just like with uvccapture and with video streaming this is done with a URL, albeit a different one:


The image shows how to set up the camera parameters in Domoticz.

Edit Camera form in Domoticz

A New Script toc

There are numerous examples of bash scripts for starting and stopping MJPG-Streamer dating back quite a few years. I just adapted one of those, but I don't recall exactly which one. I saved the file under the name webcam-streamer in a hidden directory called .local/bin in my home directory.

pi@domo:~$ mkdir -p .local/bin pi@domo:~$ nano.local/bin/mjpg-streamer
#!/bin/bash # adjust these INPUT_PLUGIN="/usr/local/lib/mjpg-streamer/input_uvc.so"; DEVICE="/dev/video0"; FRAMES="10"; RESOLUTION="1280x720"; OUTPUT_PLUGIN="/usr/local/lib/mjpg-streamer/output_http.so"; PORT="8085"; CREDENTIALS="-c stream:michel" # the following are defaults and should not need to be changed EXEC="/usr/local/bin/mjpg_streamer" WEB_DIR="/usr/local/share/mjpg-streamer/www"; # mjgp_streamer often does not start on first try. Why ? start_streamer(){ for i in {1..5} # try up to 5 times do ${EXEC} -b -i "${INPUT_PLUGIN} -n -d ${DEVICE} -f ${FRAMES} -r ${RESOLUTION}" -o "${OUTPUT_PLUGIN} -p ${PORT} -w ${WEB_DIR} ${CREDENTIALS}" > /dev/null 2>&1 sleep $((1+i)) # waiting progressively longer if pgrep mjpg_streamer > /dev/null then echo "mjpg_streamer started" return fi done echo "could not start mjpg_streamer" } # Carry out specific functions when asked to by the system case "$1" in start) if pgrep mjpg_streamer > /dev/null then echo "mjpg_streamer already running" else start_streamer fi ;; stop) if pgrep mjpg_streamer > /dev/null then killall mjpg_streamer echo "mjpg_streamer stopped" else echo "mjpg_streamer is not running" fi ;; restart) if pgrep mjpg_streamer > /dev/null then killall mjpg_streamer echo "mjpg_streamer stopped" else echo "mjpg_streamer is not running" fi start_streamer ;; status) pid=`ps -A | grep mjpg_streamer | grep -v "grep" | grep -v mjpg_streamer. | awk '{print $1}' | head -n 1` if [ -n "$pid" ]; then echo "mjpg_streamer is running with pid ${pid}" echo "mjpg_streamer was started with the following command line" cat /proc/${pid}/cmdline ; echo "" else echo "mjpg_streamer is not running" fi ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 ;; esac exit 0

The script tries up to five times before giving up when starting or restarting the webcam streamer. That's because starting the daemon would often fails on the first few tries for some unknown reason.

The script needs to be made executable and the directory in which it is located will be added to the environment search path by editing the hidden file .profile in my home directory.

pi@domo:~$ chmod +x .local/bin/webcam-streamer pi@domo:~$ mkdir -p .local/bin pi@domo:~$ nano .profile
# set PATH so it includes user's private .local/bin if it exists if [ -d "$HOME/.local/bin" ] ; then PATH="$HOME/.local/bin:$PATH" fi

The change will take effect only on the next reboot. The last step is to add a reboot entry in crontab.

pi@domo:~ $ crontab -e

# Start the webcam on reboot @reboot /home/pi/.local/bin/webcam-streamer start && sleep 5 && /home/pi/.local/bin/webcam-streamer restart

Note how the cron reboot task starts the streamer and then restarts it about five seconds later. The reason for this can be gleaned from the following image which comes from the streamer with just a single start after a reboot.

First image from WebCam

The web cam is working but something is wrong. Stopping and restarting the streamer stops the ghostly stream. Of course your mileage may vary with different equipment.

Both the need to try more than once to start the streamer and the ghostly stream are persistent problems. I have reinstalled MJPG-Streamer on a clean copy of a fully updated and upgraded version of Rasbian Jessie without any improvement. Tests with another camera suggest that this is a problem with the Logitech C270 Webcam and not related to MJPG-Streamer. Accordingly the cron task with other cameras could be a single command.

# Start the webcam on reboot @reboot /home/pi/.local/bin/webcam-streamer start


  1. Raspberry Pi Webcam Over the Internet Using MJPG-Streamer by Jacob Salmela, May 31, 2014.
  2. Setup Guide: Raspberry Pi | MJPEG Streamer Install & Setup & FFMpeg Recording by Austin St. Aubin, March 11,2018.
  3. Raspberry Pi camera board video streaming by Miguel Mota, Sept. 25, 2013, Updated Jan. 19, 2014.

Remote Start and Stop toc

What happens if for some reason the web cam streamer is not working properly and I am away from the house? To my mind, the easiest solution was to create a virtual switch in my home automation system to activate the script.

This is easily done. Create a virtual switch in Domoticz. Here is a quick reminder of the procedure.

  1. Click on the Setup tab.
  2. Click on the Hardware item in the menu.
  3. If the virtual hardware Dummy (Does nothing, ...) already exists move on to step 4.
    • Complete the fields
      Name: = Virtuel, and
      Type: = Dummy (Does nothing... that is picked from the drop down list.
    • Click on the Add button at the bottom of the page. The virtual hardware will now show up in the table at the top of the page.
  4. Click on Create Virtual Sensors in the virtual (Dummy) hardware.
  5. Name the sensor, I used Web Cam On/Off and set the Sensor Type: to Switch.
  6. Click on the OK button. A message saying where the switch was installed will briefly flash on the window.
  7. Click on the Setup tab again.
  8. Click on the Devices item in the menu.
  9. Lookup the idx number of the newly created switch in the index column (idx).
  10. Click on the Switches tab.
  11. Click on the Edit button of the newly created switch.
  12. Enter script:///home/pi/.local/bin/webcam-streamer start in the On Action: field.
  13. Enter script:///home/pi/.local/bin/webcam-streamer stop in the Off Action: field.

    Editing the virtual camera in Domoticz

  14. Click on the Save button.
  15. Click on the Back button to return to the Switches tab.

I didn't particularly like the light bulb icon or any of the other icons available for this particular device. I created a webcam icon from the one already in the www/images directory of Domoticz. See Domoticz: give a facelift by customizing the icons for details on doing this.

Views of the virtual Web Cam On/Off switch in Domoticz

So I can always turn on or off the web cam streamer using this control. There is one problem though. The status of the virtual device does not necessarily correspond to the status of the daemon. However this is easily solved by modifying the script file created in the previous section.

With a bit more experience using MJPG-Streamer, I have decided to modify things a bit. The principal change, is that I no longer want to run the streamer constantly as a daemon. I did not like that the LED indicator on the webcam was always on. While it should be possible to turn it off with the -l (or --led) option of the input_uvc.so plugin, in practice that did not work. In any case, I had an uncomfortable feeling of being a voyeur in my own home spying on family and friends. I would rather that the camera only work when the house is empty. Strangely, I have no qualms about the outside IP camera always being on.
April 23, 2018

First, add a couple of constants that will need to be adjusted for the true IP address of the Rasberry Pi hosting the home automation program and for the true index number of the virtual device created in Domoticiz at the top of the script file.

pi@domo:~ $ nano .local/bin/webcam-streamer
# adjust these # Domoticz URL="" IDX="165"

The end of the script is also changed. After the case..esac statement, there are few extra lines of code that will update the status of the Domoticz virtual device to reflect whether MJPG-Streamer is running or not. And an update option is added. It can be seen to do nothing in the case statement except to go on to the lines that update the status of the Domoticz virtual switch.

update) ;; *) echo "Usage: $0 {start|stop|restart|status|update}" exit 1 ;; esac if pgrep mjpg_streamer > /dev/null then ONOFF="1" else ONOFF="0" fi curl "${URL}/json.htm?type=command&param=udevice&idx=${IDX}&nvalue=${ONOFF}" exit 0

An HTML request will be sent to the Domoticz web server whenever the script is invoked with a start, stop, restart or update option. No request is send when the status option is selected or when there is no specified option or when there is an error.

From now on the cron deamon will only update Domoticz on the status of MJPG-Streamer. This is done at boot time and only once an hour thereafter because it seems to be something with a low priority.

pi@domo:~ $ crontab -e
... # m h dom mon dow command # ## Start the webcam on reboot and then stop it to get rid of ghost images @reboot /home/pi/.local/bin/webcam-streamer start && sleep 10 && /home/pi/.local/bin/webcam-streamer stop # # Once an hour on the 25th minute update Domoticz webcam status 25 * * * * /home/pi/.local/bin/webcam-streamer update #

To ensure that the webcam video is streamed when the house is empty, I modified the enable_timers.sh script that controls conditional timers in Domoticz. It is a straighforward thing to add the following at the end of the script.

if [ "$ACTION" = "enabletimer" ] then ACTION="start" else ACTION="stop" fi #echo "/home/pi/.local/bin/webcam-streamer $ACTION" /home/pi/.local/bin/webcam-streamer $ACTION

Slow Camera toc

When my web cam is operated in YUYV pixel format, MJPG-Streamer takes on the chore of compressing the video stream before sending it on. That will occupy more than half of the cpu time. This could be acceptable in a multicore system, such as the Raspberry Pi 3 or the Orange Pi Zero, but I would not do it with a single core Raspberry Pi B+.

However the last section does offer a partial solution. Do not start the streamer when the computer is booted, in other words, make sure to stop the streamer in the reboot entry in crontab and do not start it in the conditional timers script. Remotely start and stop MJPG-Streamer only when you want to view the video feed. Watching a video of one's own living room is not the most entertaining activity, so I would assume that this will not be done for long. Hopefully, the Raspberrry Pi will have enough oomph to process the HTTP request to turn the streamer off when it is running, but that remains to be seen.

If someone does that, I would be happy to hear how this works in practice.

Downloads toc

Here are the complete files discussed in the above post.

Installing the MJPG-Streamer Video Streamer->