CCTV at home or how to lead an Orwellian household

I have recently acquired 5 Foscam FI8918W ip cameras for monitoring my house.

While this may seem like a step towards wearing a tinfoil hat, I have several reasons for doing so:

  • It’s a fun geek project that is a subset of a larger endeavor to wire my house (think remote control)
  • I love to know when the UPS guy dropped a package so I don’t have hundreds of dollars worth of electronics sitting on my front porch
  • I get to know how the freaking chicken get out of their cage
  • I get to know when the fucking raccoon is doing his patrol at night so I can shoot it in the face
  • I would like to do fast motion videos of the garden through the seasons
  • And yeah I’ll admit it, I like to keep an eye on stuffs

These little cams are absolutely great, some key features include: cat5 & wifi (wep, wpa, wpa2) network access, nightvision, pan 300 degrees, tilt 120 degrees, remote control & view. I wish I had bought a couple of outside ones though. The problem with most cameras is that they do night vision by shining some infrared LEDs, if your camera is inside pointing outside, the IR will get reflected by the window and the outside won’t be visible. I have yet to mess with the angles and such to try and fix that.

What an inside camera pointed at the outside looks like at night

The web interface for the cams is great, although not all the features are supported in browsers other than IE (for example sound, microphone and multicam) but video & remote control are fine.

If you want to record what the cams see, you’ll want a server on your network. In my case I use my Linux box and run the following script every hour:

pkill -9 wget
nohup wget http://<cam1_ip>/videostream.asf?user=<username>&pwd=<password> -O /cameras/cam1_`date +%F_%T`.asf > /dev/null 2>&1 &
nohup wget http://<cam2_ip>/videostream.asf?user=<username>&pwd=<password> -O /cameras/cam2_`date +%F_%T`.asf > /dev/null 2>&1 &
nohup wget http://<cam3_ip>/videostream.asf?user=<username>&pwd=<password> -O /cameras/cam3_`date +%F_%T`.asf > /dev/null 2>&1 &
nohup wget http://<cam4_ip>/videostream.asf?user=<username>&pwd=<password> -O /cameras/cam4_`date +%F_%T`.asf > /dev/null 2>&1 &
nohup wget http://<cam5_ip>/videostream.asf?user=<username>&pwd=<password> -O /cameras/cam5_`date +%F_%T`.asf > /dev/null 2>&1 &
rm /cameras/cam*_`date --date="5 days ago" +%F_`*.asf

This hourly rotation makes it convenient to quickly locate a file pertaining to an event you’re interested in. I am removing files older than 5 days but this can easily be adjusted on the last line. The directory where this all ends up is exported to a web server for remote access which yields the following results:

As you can see, an hour on 1 cam takes about 500M of disk space. This is because the cams do not have the processing power to compress the video stream, and this is fine by me, I don’t want them doing anything of the sort. The hourly cron could very well be augmented to encode new files but storage is cheap, my server not beefy and 5 days are more than enough for me.

As for making the cameras themselves available on the web, this frankly takes some guts. This is obviously a very critical device that you do not want anybody to have access to. One could simply forward some ports on their routers and rely on the cam’s authentication mechanism (make sure to change the default of admin/<blank>…). I don’t want the cams to even face the world where they are susceptible to exploits and bruteforce attacks so I proxy their access through my web server. This allows me to restrict IP access (default deny of course). I am also able to keep an eye on the logs and in general adds a layer of protection.

Here is the .htaccess file that does this magic for one of the cams (you’ll need to have mod_proxy enabled)

Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)$ http://<cam_ip>/videostream.cgi?user=<username>&pwd=<password> [P]

Foscam made it really easy to mess with the cam, all of the options that are available through their web interface are also available through direct URL calls which makes it easy to integrate the camera functionalities in a script (like the recording above). I’ve even started writing my own web interface for semi-public access that allows for visual customization as well and very granular function control.

the following URLs can be appended with “&user=<username>&pwd=<password>” so as to authenticate directly.

  • http://<cam_ip>/snapshot.cgi gives you the current image
  • http://<cam_ip>/video.cgi gives you live video
  • http://<cam_ip>/live.htm gives you live video
  • http://<cam_ip>/set_misc.cgi?ptz_patrol_rate=20 lets you change the rotation speed of the motors.
  • http://<cam_ip>/set_misc.cgi?ptz_center_on_start=0 turns off the initial power-on rotation
  • http://<cam_ip>/set_misc.cgi?led_mode=2 disables the front status LED
  • http://<cam_ip>/reboot.cgi will reboot the cam
  • http://<cam_ip>/decoder_control.cgi?command=0&onestep=1 tilts up
  • http://<cam_ip>/decoder_control.cgi?command=2&onestep=1 tilts down
  • http://<cam_ip>/decoder_control.cgi?command=4&onestep=1 tilts left
  • http://<cam_ip>/decoder_control.cgi?command=6&onestep=1 tilts right
  • http://<cam_ip>/set_misc.cgi?ptz_auto_patrol_type=1 sets the patrol type, possible values: 0: none; 1: horizontal; 2: vertical; 3: horizontal + vertical
  • http://<cam_ip>/get_misc.cgi displays functional values
  • http://<cam_ip>/get_log.cgi displays access log
  • http://<cam_ip>/get_params.cgi displays configuration values

I’m very happy with them, they’re great products and fun to play with. One downside is their microphones which are pretty horrible but I don’t care much about sound. Here are a few pictures of them in action:

Inside cam pointed outside during the day

Nightvision in the chicken coop

[flv: 640 480]

12 Replies to “CCTV at home or how to lead an Orwellian household”

  1. Here is my script for recording the files while remuxing on the fly to a mkv file which is indexed and thus you can seek within.

    ffmpeg is only remuxing so it is not more of a burden than wget itself and the result can be played by any player. The loop kills the process every hour and starts it up again.

    while true
    do eval “(ffmpeg -i ‘’ -acodec copy -vcodec copy `date +%F_%H-%M-%S.mkv`) &”
    sleep 3600
    kill $PID

    1. Really cool! Thanks for sharing.

      I’m actually doing things differently now, I’m using Motion to capture only the frames where something happened and at the end of the day using ffmpeg to turn them into a movie.

      It certainly removes a TON of captured frames that are irrelevant but as always with motion detection, it’s tricky to make it smart. I think I’m going to go back to the nuclear approach that is recording everything.

      Your script is some awesome bash-foo! I’m not sure I like the sleep approach though as it will inevitably build up some lag. Thank you very much for sharing it!

  2. Hello! Great article!

    A small question … How do I play videos. ASF? With VLC the movie you can not fast forward …

    Thank you!

    1. Don’t quote me on this I’m not a video encoding expert but it is my understanding that these ASF files having been recorded live, they are missing indexing information. Because live video doesn’t have a start and an end by nature. Some post processing can add this indexing information but I’ve never done it. I use mplayer on the mac and navigation through the video is a little funky because of the missing indexes but mplayer does a decent job at figuring things out.

      I hope this helps.

  3. Great job!

    But I tried to follow your script to record the MP4 vedio from my LNE3003 IP Camera. I used the following script based on yours – some changes because I running the plugbox linux on Dockstar. I’ve verified the path and file name of the MP4 video file by seeing it on Realplayer on Windows XP.


    pkill -9 wget
    nohup wget –http-user=xxxx –http-password=yyyy -O cam_`date +%F_%T`.mp4 > /dev/null 2>&1 &

    After running, it just generate the following empty file

    -rw-r–r– 1 root root 0 Jan 4 22:41 cam_2011-01-04_22:41:52.mp4
    -rw-r–r– 1 root root 0 Jan 4 22:25 cron.log

    Could you please give me some further guidance to make it work? specifically

    1. Do you have mplayer or other vedio player installed on your Linux box?
    2. my cron job does not start as expected, would you mind to share your cron job script and how you submit the cron job?

    Much appreciated!

    1. In response to to #1, I do not have any video player installed on my linux server, all that is happening with wget is an HTTP transaction so codec/video player matters are not relevant to just saving the stream on your server.

      Now You should try to do a small proof of concept before you turn it into an automated cron, try to run the following commands manually and see if you get some bytes in that file:
      wget –http-user=xxxx –http-password=yyyy -O cam_`date +%F_%T`.mp4 (you can CTRL+C out of it after a few seconds)

      the things that make me half suspicious are the http-user & http-password parameters. On my cam, credentials are passed in the URL through get variables but your cam is different might very well be doing NTLM authentication in which case indeed you’ll need these parameters. Did you make sure you have 2 dashes “-” in front of these parameters?

      Did you make sure that you could access the streams directly through a video player like mplayer before you started wgetting them?

      The advantage of running the commands manually is that you’ll see what wget says is happening instead of sending everything to /dev/null. It’s important to build complex commands from the ground up.

      Try this and let me know what you find, I’ll be happy to help you get it going.

      1. Thanks for your quick response!

        1. good to know I don’t need to install any player because there is no readily available for the plugbox yet.

        2. I did do a small proof run before going to cron job. the results I presented in my last post was results from a short run.

        3. yes, those are the sytax in my wget version, if I use your “&user” and &password way, I got “unauthorized” error. Ys, those are two dashes.

        4. Yes, I can stream into my windows RealPlayer and VLC player, but using rtsp:// or did not work saying things like “cannot locate the file”

        5. when running the job without /dev/null, the job will hang forever saying that

        HTTP Request sent, waiting for response

        and the generated new file size keeps as 0 unchanged after even 10 minutes. The wget process was not running although it was listed in the ps -l results.

        Any other thoughts?

        Thank you again!

        1. Well there you have it, RSTP is not HTTP. Wget supports HTTP (among other things) but not RSTP. You need to check if you cam supports video streaming via HTTP or my method won’t work. From what I’m reading about your cam it doesn’t stream on any other protocol than RSTP so my wget based script will not work. This is why they say you need Media Player or Quicktime.

          I’m not sure how you would achieve saving the stream on a Linux box with such a restriction. You might be able to command line a VLC/mplayer command that would save the stream. This is going to take some research and might not even be doable.

          This is one of the reasons why the FOSCAMs are great, they have very open APIs and standard ways of accessing the stream. I suggest you stop wasting your time on my scripts they’re HTTP centric :

          Sorry and good luck.

Leave a Reply

Your email address will not be published. Required fields are marked *