<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mike Renfro's Blog &#187; php</title>
	<atom:link href="http://blogs.cae.tntech.edu/mwr/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.cae.tntech.edu/mwr</link>
	<description>A partial repository of whatever comes to mind</description>
	<lastBuildDate>Sat, 31 Oct 2009 23:02:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Grabbing Stills and Making FLV Movies from Axis IP Cameras</title>
		<link>http://blogs.cae.tntech.edu/mwr/2007/11/07/grabbing-stills-and-making-flv-movies-from-axis-ip-cameras/</link>
		<comments>http://blogs.cae.tntech.edu/mwr/2007/11/07/grabbing-stills-and-making-flv-movies-from-axis-ip-cameras/#comments</comments>
		<pubDate>Wed, 07 Nov 2007 22:58:04 +0000</pubDate>
		<dc:creator>Mike Renfro</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blogs.cae.tntech.edu/mwr/2007/11/07/grabbing-stills-and-making-flv-movies-from-axis-ip-cameras/</guid>
		<description><![CDATA[About a week and a half ago, I was reminded of a long-dormant project to archive still images from an Axis IP camera. I started this up a few years ago as a favor to a coworker, but it never really got finished. Previously, it was a pretty simple cron job that would just authenticate [...]]]></description>
			<content:encoded><![CDATA[<p>About a week and a half ago, I was reminded of a long-dormant project to archive still images from an Axis IP camera. I started this up a few years ago as a favor to a coworker, but it never really got finished. Previously, it was a pretty simple cron job that would just authenticate to the camera and download the current still. At some point, it would also use ImageMagick to convert the captured JPEGs to an MPEG or similar, but it was decidedly non-optimal.</p>
<p>So now that I was reminded by people who were <strong>very</strong> interested in seeing the results (i.e., monitoring their remotely-located labs), I took another stab at it. Much better results this time. Now my customers get:</p>
<ul>
<li>Still images captured every 30 seconds</li>
<li>FLV movies of the day&#8217;s stills made every 5 minutes</li>
<li>A playlist that lets them browse through previous days&#8217; activity for as long as we keep the movies around</li>
</ul>
<p>The programs and pages that make this mini-site follow below:<br />
<span id="more-50"></span><br />
axisgrab.py &#8212; extracts current image from the designated Axis camera, encodes today&#8217;s images into an FLV</p>
<pre>
#!/usr/bin/python

basename='denso'
axisip='192.168.0.1'
axisuser='someuser'
axispass='somepassword'
flvcreator='TTU ME Department'

import urllib2, time, os, re, getopt, sys

def usage():
    print """axisgrab.py -- grab or encode images from an Axis IP camera
Usage: axisgrab.py --grab
       axisgrab.py --encode
"""

def main():

    try:
        optlist, args = getopt.getopt(sys.argv[1:], 'g:e:',
                                      [ 'grab', 'encode' ])
    except getopt.GetoptError:
        usage()
        sys.exit(2)

    for opt, junk in optlist:
        if (opt=='--grab'):
            auth_handler = urllib2.HTTPBasicAuthHandler()
            auth_handler.add_password('/',axisip,axisuser,axispass)
            opener = urllib2.build_opener(auth_handler)
            urllib2.install_opener(opener)
            axis_jpg=urllib2.urlopen('http://%s/axis-cgi/jpg/image.cgi' % ( axisip ) )

            filename='%s_%s_%s.jpg' % ( basename, time.strftime('%Y%m%d'), time.strftime('%H%M%S') )
            local_jpg=open(filename,'w')
            local_jpg.write(axis_jpg.read())
            local_jpg.close()
            os.chmod(filename,0644)

        if (opt=='--encode'):
            os.system('mencoder -really-quiet -ovc lavc -lavcopts vcodec=flv -mf fps=25:type=jpg \\'mf://%s_%s*.jpg\\' -of lavf -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -o %s_%s.flv &gt;&amp;/dev/null' % ( basename, time.strftime('%Y%m%d'), basename, time.strftime('%Y%m%d') ))

            playlistname="playlist-%s.xml" % ( basename )
            playlist=open(playlistname,'w');
            playlist.write("""
            &lt;?xml version="1.0" encoding="utf-8"?&gt;
            &lt;playlist version="1" xmlns="http://xspf.org/ns/0/"&gt;
            &lt;trackList&gt;
            """)

            files=os.listdir(".")
            files.sort()
            repattern="%s.+flv" % ( basename )
            recompiled=re.compile(repattern)
            for file in files:
                if recompiled.search(file):
                    playlist.write("    &lt;track&gt;\n")
                    playlist.write("      &lt;title&gt;%s&lt;/title&gt;\n" % (file))
                    playlist.write("      &lt;creator&gt;%s&lt;/creator&gt;\n" % (flvcreator))
                    playlist.write("      &lt;location&gt;%s&lt;/location&gt;\n" % (file))
                    playlist.write("      &lt;info&gt;force_download.php?file=%s&lt;/info&gt;\n" % (file))
                    playlist.write("    &lt;/track&gt;\n")

            playlist.write("""
            &lt;/trackList&gt;
            &lt;/playlist&gt;
            """)

if __name__ == "__main__":
    main()
</pre>
<p>index.php &#8212; main web interface to the images and movies</p>
<pre>
&lt;?php
  // If I did all this correctly, you shouldn't have to change
  // anything but the basename variable.
$basename = "denso";

$today = date("Ymd"); // e.g., 20070901
$mediabase = $basename."_".$today; // axisgrab.py stores images with this naming scheme
$imagewidth = 480; // Controlled on the camera video/image settings
$imageheight = 360; // Controlled on the camera video/image settings
?&gt;

&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Denso Lab Camera Feed&lt;title&gt;
&lt;script type="text/javascript" src="swfobject.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
var browser = navigator.appName;
var version = parseInt(navigator.appVersion);

function showImage(object) {
  var imageToShow = object.options[object.selectedIndex].value;

  if (browser == 'Netscape') {
    if (version &gt;= 3) document.dropImage.src = imageToShow;
    else              alert('Your browser does not support the image object - sorry');
  }
  else if (browser == 'Microsoft Internet Explorer') {
    if (version &gt;= 4) document.dropImage.src = imageToShow;
    else              frames[0].location.href = imageToShow;
  }
}
//--&gt;&lt;/script&gt;
&lt;meta http-equiv="refresh" content="300"&gt;

&lt;/head&gt;
&lt;body&gt;
&lt;table&gt;
&lt;tr valign="top"&gt;
&lt;td&gt;
&lt;h1&gt;Denso Lab Camera Footage&lt;/h1&gt;

&lt;p&gt;Select a day from the list below to play, or click the icon at the right of the filename to download.&lt;/p&gt;
&lt;p id="player1"&gt;&lt;a href="http://www.macromedia.com/go/getflashplayer"&gt;Get the Flash Player&lt;/a&gt; to see this player.&lt;/p&gt;
&lt;script type="text/javascript"&gt;
   var s1 = new SWFObject("mediaplayer.swf","single","480","480","7");
s1.addParam("allowfullscreen","true");
s1.addParam('allowscriptaccess','always');
s1.addVariable("file","&lt;?php echo "playlist-".$basename.".xml"; ?&gt;");
s1.addVariable('displayheight','360');
s1.write("player1");
&lt;/script&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;h1&gt;Still Images&lt;/h1&gt;
&lt;form name="imageForm"&gt;
&lt;select name="imageSelect"&gt;
&lt;?php
if ($dh = opendir('./')) {
  $files = array();
  while (($file = readdir($dh)) !== false) {
    if (substr($file, strlen($file) - 4) == '.jpg') {
      array_push($files, $file);
    }
  }
  closedir($dh);
}

// Sort the files and display
sort($files);

foreach ($files as $file) {
  echo "&lt;option value=$file&gt;$file&lt;/option&gt;\n";
}
?&gt;
&lt;/select&gt;
&lt;input name="submitName" type="button" value="Show" onClick="showImage(document.imageForm.imageSelect)"&gt;
&lt;/form&gt;

&lt;SCRIPT LANGUAGE="JavaScript"&gt;&lt;!--
if (browser == 'Netscape')
  document.write('&lt;IMG SRC="&lt;?php echo $mediabase."_0000.jpg"; ?&gt;" NAME="dropImage" WIDTH=&lt;?php echo $imagewidth;?&gt; HEIGHT=&lt;?php echo $imageheight;?&gt;&gt;');
 else if (browser == 'Microsoft Internet Explorer') {
   if (version &gt;= 4)
     document.write('&lt;IMG SRC="&lt;?php echo $mediabase."_0000.jpg"; ?&gt;" NAME="dropImage" WIDTH=&lt;?php echo $imagewidth;?&gt; HEIGHT=&lt;?php echo $imageheight;?&gt;&gt;');
    else
      document.write('&lt;IFRAME FRAMEBORDER=0 WIDTH=&lt;?php echo $imagewidth;?&gt; HEIGHT=&lt;?php echo $imageheight
;?&gt; MARGINHEIGHT=0 MARGINWIDTH=0 SCROLLING=no SRC="&lt;?php echo $mediabase."_0000.jpg"; ?&gt;"&gt;&lt;/IFRAME&gt;');
 }
//--&gt;&lt;/SCRIPT&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</pre>
<p>swfobject.js and mediaplayer.swf are part of <a href="http://www.jeroenwijering.com/?item=JW_Media_Player">Jeroen Wijering&#8217;s JW Media Player</a>.</p>
<p>Cron jobs on the webserver (to grab 2 images per minute):</p>
<pre>
* * * * * (cd /path/to/axis/folder &amp;&amp; ./axisgrab.py --grab &amp;&amp; sleep 30 &amp;&amp; ./axisgrab.py --grab)
0,5,10,15,20,25,30,35,40,45,50,55 * * * * (cd /path/to/axis/folder &amp;&amp; ./axisgrab.py --encode)
</pre>
<p>The results:<br />
<a href='http://blogs.cae.tntech.edu/mwr/files/2007/11/axisscreenshot.png' title='axisscreenshot.png'><img src='http://blogs.cae.tntech.edu/mwr/files/2007/11/axisscreenshot.thumbnail.png' alt='axisscreenshot.png' /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.cae.tntech.edu/mwr/2007/11/07/grabbing-stills-and-making-flv-movies-from-axis-ip-cameras/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
