Video surveillance in FreeBSD using motion, ffserver, ffmpeg

The program allows you to record motion and surveillance ip-cameras or web-cameras.
The first option. Ip-camera used in conjunction with the motion. Tested Ubiquiti Aircam mini camera and D-Link DCS-930L.
Installing motion:
# Cd / usr / ports / multimedia / motion
# Make install clean

Rule configuration file at /usr/local/etc/motion.conf. It is well commented by default, leaving only the options you want:

daemon on
# You will need to create a folder motion at this address by default is not created
process_id_file /var/run/motion/motion.pid
setup_mode off

If you are using a webcam or analog camera, then specify the path to the device:
#videodevice / dev / video0

# V4L2_PIX_FMT_SN9C10X: 0 ‘S910’
# V4L2_PIX_FMT_SBGGR8: 1 ‘BA81’
# V4L2_PIX_FMT_MJPEG: 2 ‘MJPEG’
# V4L2_PIX_FMT_JPEG: 3 ‘JPEG’
# V4L2_PIX_FMT_RGB24: 4 ‘RGB3’
# V4L2_PIX_FMT_UYVY: 5 ‘UYVY’
# V4L2_PIX_FMT_YUYV: 6 ‘YUYV’
# V4L2_PIX_FMT_YUV422P: 7 ‘422P’
# V4L2_PIX_FMT_YUV420: 8 ‘YU12’

# We ip-camera, specify the mode:
v4l2_palette 2

input 8
norm 0
rotate 0

width 640
height 480

framerate 10

# Path to Kotoku mjpeg camera. In the case of Ubiquiti Aircam mini is:
netcam_url http://172.16.0.105/snapshot.cgi
# In the case of D-Link DCS-930L, the path will be kind http://172.16.0.105/video.cgi

If necessary, specify the authorization to the camera:
#netcam_userpass admin: admin
netcam_http 1.0
auto_brightness off

# Camera sensitivity to motion:
threshold in 2500

threshold_tune off

noise_level 32
noise_tune on
gap 60

# The maximum recording time for one video file in seconds:
max_mpeg_time 2000

# We will not take pictures in the format jpeg:
output_all off
output_normal off
output_motion off
quality 75

################################################## ##########
# FFMPEG related options
# Film (mpeg) file output, and deinterlacing of the video input
# The options movie_filename and timelapse_filename are also used
# By the ffmpeg feature
################################################## ##########

ffmpeg_cap_new on
ffmpeg_cap_motion off
ffmpeg_timelapse 0
ffmpeg_timelapse_mode daily

# The video quality (bit rate)
ffmpeg_bps 150000
ffmpeg_variable_bitrate 0

ffmpeg_video_codec mpeg4

ffmpeg_deinterlace off

snapshot_interval 0

# Overlay text on video
text_right% Y-% m-% d \ n% T-% q
text_changes off
text_event% Y% m% d% H% M% S

# Increase text size:
text_double on

# Path to save the video:
target_dir / usr / local / www / motion / video

# The file name format:
snapshot_filename% v_% Y_% m_% d_% H% M% S
jpeg_filename% v-% Y% m% d% H% M% S-% q
movie_filename% v_% Y.% m.% d_% H.% M.% S
timelapse_filename% Y% m% d-timelapse

################################################## ##########
# HTTP Based Control
################################################## ##########
control_localhost on
control_html_output on

quiet on

Here you can specify commands or scripts to be executed when some events:
# Command to be executed when an event starts. (Default: none)
# An event starts at first motion detected after a period of no motion defined by gap.
; on_event_start value

# Command to be executed when an event ends after a period of no motion
# (Default: none). The period of no motion is defined by option gap.
; on_event_end value

# Command to be executed when a picture (.ppm | .jpg) is saved (default: none)
# To give the filename as an argument to a command append it with% f
; on_picture_save value

# Command to be executed when a motion frame is detected (default: none)
; on_motion_detected value

# Command to be executed when motion in a predefined area is detected
# Check option ‘area_detect’. (Default: none)
; on_area_detected value

# Command to be executed when a movie file (.mpg | .avi) is created. (Default: none)
# To give the filename as an argument to a command append it with% f
; on_movie_start value

# Command to be executed when a movie file (.mpg | .avi) is closed. (Default: none)
# To give the filename as an argument to a command append it with% f
; on_movie_end value

# Command to be executed when a camera can not be opened or if it is lost
# NOTE: There is situations when motion does not detect a lost camera!
# It depends on the driver, some drivers do not detect a lost camera at all
# Some hang the motion thread. Some even hang the PC! (Default: none)
; on_camera_lost value

# If several cameras, there is need to specify the path to the same configuration files:
; thread /usr/local/etc/thread2.conf
; thread /usr/local/etc/thread3.conf
; thread /usr/local/etc/thread4.conf

We start motion:
# /usr/local/etc/rc.d/motion Start

We now have a video surveillance system is almost ready. Videos are stored at / usr / local / www / motion / video
To watch the video in real time, you can use the daemon ffserver and ffmpeg, reaching complete with motion or use the web face ip-camera.
I made easier, put into regular html-page picture from the camera at intervals of 1 sec update:

<Html> <head> <meta http-equiv = “Content-ype” content = “text / html; charset = utf-8”> <title> Camera 1 </ title> </ head> <body> <br / > <br /> <div align = “center” width = “1024”> <span> <b> <h2> Camera 1 </ h2> </ b> </ span> <IMG width = “640” height = “480” border = “1” name = “image1” style = “border-color: # 000;”> <SCRIPT language = “JavaScript” type = “text / javascript”> var t = 1 // refresh interval var img1 = “http://192.168.11.5/image.jpg?” document.images [“image1”]. src = img1 Start (img1, “image1”); function Start (img, name) {tmp = new Date (); tmp = “&” + tmp.getTime () document.images [name] .src = img + tmp var delay = function () {Start (img, name); }; setTimeout (delay, t * 1000)} </ SCRIPT> <br /> <span style = “font-weight: bold; font-size: 18px;”> <a href=”files.php”> FILES </ a > </ sp </ div> </ body> </ html>
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

<Html>
<Head>
<Meta http-equiv = “Content-ype” content = “text / html; charset = utf-8”>
<Title> Camera 1 </ title>
</ Head>
<Body>
<br />
<br />
<Div align = “center” width = “1024”>
<Span> <b> <h2> Camera 1 </ h2> </ b> </ span>
<IMG width = “640” height = “480” border = “1” name = “image1” style = “border-color: # 000;”>
<SCRIPT language = “JavaScript” type = “text / javascript”>
var t = 1 // refresh interval
var img1 = “http://192.168.11.5/image.jpg?”
document.images [“image1”]. src = img1
Start (img1, “image1”);
function Start (img, name) {
tmp = new Date ();
tmp = “&” + tmp.getTime ()
document.images [name] .src = img + tmp
var delay = function () {Start (img, name); };
setTimeout (delay, t * 1000)
}
</ SCRIPT>
<br />
<Span style = “font-weight: bold; font-size: 18px;”> <a href=”files.php”> FILES </a> </ sp
</ Div>
</ Body>
</ Html>

More there is a need somehow to catalog files found. For this I used the php-script, it must be put on a level higher than the directory with video files. The essence of the script – once a day (need to put on crowns) files entries are arranged in folders with names – recording date:

<? Php date_default_timezone_set (‘Europe / Moscow’); $ Dir = glob (“video / *. Avi”); foreach ($ dir as $ fileAvi) {$ data = date (“dmY”, filemtime ($ fileAvi)); mkdir (‘video /’.$ data, 0777, true); $ FileAviCastrat = str_replace (‘video /’, ”, $ fileAvi); copy ($ fileAvi, ‘video /’.$ data.’ / ‘. $ fileAviCastrat); unlink ($ fileAvi); }?>
1
2
3
4
5
6
7
8
9
10
11
12
13

<? Php
date_default_timezone_set (‘Europe / Moscow’);
$ Dir = glob (“video / *. Avi”);
foreach ($ dir as $ fileAvi) {
$ Data = date (“d-m-Y”, filemtime ($ fileAvi));
mkdir (‘video /’.$ data, 0777, true);
$ FileAviCastrat = str_replace (‘video /’, ”, $ fileAvi);
copy ($ fileAvi, ‘video /’.$ data.’ / ‘. $ fileAviCastrat);
unlink ($ fileAvi);
}
?>

To display the files and folders on the html-page, use the following script:

<? Php function filesize_get ($ file) {if (! File_exists ($ file)) return “file not found.”; $ Filesize = filesize ($ file); if ($ filesize> 1024) {$ filesize = ($ filesize / 1024); if ($ filesize> 1024) {$ filesize = ($ filesize / 1024); if ($ filesize> 1024) {$ filesize = ($ filesize / 1024); $ Filesize = round ($ filesize, 1); return $ filesize. “GB”; } Else {$ filesize = round ($ filesize, 1); return $ filesize. “MB”; }} Else {$ filesize = round ($ filesize, 1); return $ filesize. “KB”; }} Else {$ filesize = round ($ filesize, 1); return $ filesize. “byt”; }} Isset ($ _ GET [‘file’])? $ F = $ _ GET [‘file’]. ‘/’: $ F = ”; $ Dir = ‘/usr/local/www/motion/video/’.$f; $ Files = scandir ($ dir); $ Pos = 1; foreach ($ files as $ file) {if ($ file! = ‘.’ && $ file! = ‘..’) {if (is_dir ($ dir. ‘/’. $ file)) {echo ‘<b> ‘. $ Pos. ‘) <a Href=”?file=’.$file.'”>’. $ File. ‘</a> </ B> <br />’; } Else {if (strpos ($ file, ‘.avi’)) {$ filesize = filesize_get ($ dir. ‘/’. $ File); echo ‘<b>’. $ Pos. ‘) </ B> <a href=”/motion/video/’.$f.’/’.$file.'” type=”application/octet-stream”>’. $ File. ‘</a> -‘. $ Filesize. ‘<br />’; } Else {echo ‘<b>’. $ Pos. ‘) </ B>’. $ File. ‘<br />’; }} $ Pos ++; }}?>
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

<? Php
function filesize_get ($ file) {
if (! file_exists ($ file)) return “file not found.”;
$ Filesize = filesize ($ file);
if ($ filesize> 1024)
{
$ Filesize = ($ filesize / 1024);
if ($ filesize> 1024)
{
$ Filesize = ($ filesize / 1024);
if ($ filesize> 1024)
{
$ Filesize = ($ filesize / 1024);
$ Filesize = round ($ filesize, 1);
return $ filesize. “GB”;
}
else
{
$ Filesize = round ($ filesize, 1);
return $ filesize. “MB”;
}
}
else
{
$ Filesize = round ($ filesize, 1);
return $ filesize. “KB”;
}
}
else
{
$ Filesize = round ($ filesize, 1);
return $ filesize. “byt”;
}
}
isset ($ _ GET [‘file’])? $ f = $ _ GET [‘file’]. ‘/’: $ f = ”;
$ Dir = ‘/usr/local/www/motion/video/’.$f;
$ Files = scandir ($ dir);
$ Pos = 1;
foreach ($ files as $ file) {
if ($ file! = ‘.’ && $ file! = ‘..’) {
if (is_dir ($ dir. ‘/’. $ file)) {
echo ‘<b>’. $ Pos. ‘) <a Href=”?file=’.$file.'”>’. $ File. ‘</a> </ B> <br />’;
} Else {
if (strpos ($ file, ‘.avi’)) {
$ Filesize = filesize_get ($ dir. ‘/’. $ File);
echo ‘<b>’. $ Pos. ‘) </ B> <a href=”/motion/video/’.$f.’/’.$file.'” type=”application/octet-stream”>’. $ File. ‘</a> -‘. $ Filesize. ‘<br />’;
} Else {
echo ‘<b>’. $ Pos. ‘) </ B>’. $ File. ‘<br />’;
}
}
$ Pos ++;
}
}
?>

________________________________________________________________________

Second Embodiment. Ip-camera used in conjunction with motion + ffmpeg + ffserver. Tested Ubiquiti Aircam mini camera and D-Link DCS-930L.
In this case, you can organize video broadcast from your camera, if it has no web interface. You will need tweaking ffserver and run ffmpeg.
For this tuning motion leave as it is (as above, using motion will be recorded). And customizes configuration ffserver at /usr/local/etc/ffserver.conf:
Port 8090
BindAddress 0.0.0.0
MaxClients 100
MaxBandwidth 20000
NoDaemon

File /tmp/feed.ffm
FileMaxSize 3M

Feed feed.ffm
Format flv
VideoCodec flv
VideoFrameRate 30
VideoBufferSize 80000
VideoBitRate 200
VideoQMin 1
VideoQMax 5
VideoSize 352×288
PreRoll 1
Noaudio

Feed feed.ffm
Format swf
VideoCodec flv
VideoFrameRate 30
VideoBufferSize 50000
VideoBitRate 100
VideoQMin 1
VideoQMax 5
VideoSize 352×288
PreRoll 0
Noaudio

Run ffserver:
# /usr/local/etc/rc.d/ffserve Start

Run ffmpeg:
# Ffmpeg -s 352×288 -r 15 -f mjpeg -i http://172.16.0.105:8081/stream.mjpg http: // localhost: 8090 / feed.ffm

Now at http: // localhost: 8090 / test.swf have broadcast in flash, which can be built where you need to.