ZoneMinder Virtual Camera


Have you ever wanted to stream a video file to ZoneMinder, just like a typical IP camera stream? What follows is how to set that up.

Prerequisites

The following assumes you have a fully functional ZoneMinder system and you have a pre-recorded video file, in a format that ffmpeg understands. If you have ZoneMinder installed, then you more than likely have ffmpeg, and the ffserver binary, already installed on your system.

These instructions are intended for Linux distributions running systemd.

Create an ffserver.conf file

Create the file ffserver.conf and save it under the /etc folder:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#
# To run the server:
# ffserver -f /etc/ffserver.conf
#
 
# Port on which the server is listening. You must select a different
# port from your standard HTTP web server if it is running on the same
# computer.
HTTPPort 8090
RTSPPort 8554
 
# Address on which the server is bound. Only useful if you have
# several network interfaces.
HTTPBindAddress 0.0.0.0
RTSPBindAddress 0.0.0.0
 
# Number of simultaneous HTTP connections that can be handled. It has
# to be defined *before* the MaxClients parameter, since it defines the
# MaxClients maximum limit.
MaxHTTPConnections 2000
 
# Number of simultaneous requests that can be handled. Since FFServer
# is very fast, it is more likely that you will want to leave this high
# and use MaxBandwidth, below.
MaxClients 1000
 
# This the maximum amount of kbit/sec that you are prepared to
# consume when streaming to clients.
MaxBandwidth 1000
 
# Access log file (uses standard Apache log file format)
# '-' is the standard output.
#CustomLog /var/log/ffserver
CustomLog -
 
#
# FEEDS
#
 
# Rather than play the feeds externally and reference them here,
# just specify the filename directly in the Stream section.
 
#<feed camfeed1.ffm>
#    File /tmp/camfeed1.ffm
#    FileMaxSize 2M
#    ACL allow 127.0.0.1
#    ACL allow 192.168.1.0 192.168.1.255
#</Feed>
 
#
# STREAMS
#
 
<stream camstream1.sdp>
    File "/path/to/video1.mpg"
    Format rtp
    Noaudio
    VideoFrameRate 5
    VideoSize 640x480
    ACL allow 127.0.0.1
    ACL allow 192.168.1.0 192.168.1.255
</Stream>
 
<stream camstream2.sdp>
    File "/path/to/video2.mpg"
    Format rtp
    Noaudio
    VideoFrameRate 5
    VideoSize 640x480
    ACL allow 127.0.0.1
    ACL allow 192.168.1.0 192.168.1.255
</Stream>

In the config file, adjust the frame rate and resolution to exactly match the video file(s). If these do not exactly match, the video might still play but ffserver will try to transcode the video on the fly, which comes with the cost of much cpu overhead.

Don't forget to adjust the ACL's to match your network.

Note that some older versions of ffserver do not support the RTSPBindAddress parameter. If your version of ffserver complains about this parameter, or any of the other parameters, remove the parameter if it complains it doesn't know what it is.

Anyone who has ever used ffmpeg, knows that there are a million parameters one can possibly use. Yes, a million. I counted. For those nerd enough to want to know all the possibilities, please refer to the ffserver documentation. Yes, I am a nerd. I read it all.

Create an ffserver unit file

Create the file ffserver.service and save it under /etc/systemd/system folder:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# systemd configuration for ffserver
# /etc/systemd/system/ffserver.service
 
[Unit]
Description=ffserver streaming server
Before=zoneminder.service
 
[Service]
ExecStart=/usr/bin/ffserver -f /etc/ffserver.conf
#ExecReload=/bin/kill -HUP $MAINPID
Type=simple
User=root
Group=root
Restart=always
 
[Install]
WantedBy=multi-user.target

Now, enable then start the new service file:
sudo systemctl enable ffserver
sudo systemctl start ffserver

Program each virtual camera in ZoneMinder

Create a new monitor in ZoneMinder using the following parameters:
Source Type: ffmpeg
Source Path: rtsp://127.0.0.1:8554/camstream1.sdp
Remote Method: RTP/Unicast (or UDP for 1.30.2 and newer)
Target colorspace: 32bit
Width: 640
Height: 480
That's it! You're all done!