<?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>Diego's Rants &#187; script</title>
	<atom:link href="http://blog.massanti.com/tag/script/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.massanti.com</link>
	<description>Confessions from a Geek</description>
	<lastBuildDate>Wed, 27 Oct 2010 11:22:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>MKMP4: An automated H264 / HE-AAC (aacPlus) encoder script for Mac and Linux / Unix</title>
		<link>http://blog.massanti.com/2008/09/26/mkmp4-automated-h264-aacplus-encoder-script-mac-linux/</link>
		<comments>http://blog.massanti.com/2008/09/26/mkmp4-automated-h264-aacplus-encoder-script-mac-linux/#comments</comments>
		<pubDate>Fri, 26 Sep 2008 23:43:30 +0000</pubDate>
		<dc:creator>Diego Massanti</dc:creator>
				<category><![CDATA[Computers & Tech]]></category>
		<category><![CDATA[Video Encoding]]></category>
		<category><![CDATA[aacPlus]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[h264]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://blog.massanti.com/?p=562</guid>
		<description><![CDATA[I have been nothing but amazed about the feedback that i got on my prior tutorials on how to automate the whole chain of free and open source tools to create amazing quality video at really low bitrates (great for flash streaming, etcetera). I usually write such tools and scripts for myself or for clients, [...]]]></description>
			<content:encoded><![CDATA[<p>I have been nothing but amazed about the feedback that i got on my prior tutorials on how to automate the whole chain of free and open source tools to create amazing quality video at really low bitrates (great for flash streaming, etcetera).</p>
<p>I usually write such tools and scripts for myself or for clients, but due to the fact that it seems a lot of people is interested in the process, I&#8217;m releasing here the new version of my encoding tools for the Mac and any Linux / Unix variant.</p>
<h3>Needed tools and applications</h3>
<p>For all this to work, you will need the following things</p>
<ul>
<li>The latest GIT version of the one and only <a href="http://www.videolan.org/developers/x264.html">x264 encoder</a>.</li>
<li>The latest SVN version of <a href="http://www.mplayerhq.hu/design7/dload.html">mplayer</a></li>
<li>The latest version of the <a href="http://gpac.sourceforge.net/home_download.php">GPAC utilities</a></li>
<li>My build of the <a href="http://blog.massanti.com/wp-content/uploads/2008/09/aacplusencoder.zip">3GPP HE-AAC encoder</a> if you are on a Mac, or the <a href="http://www.nero.com/enu/nero-aac-codec.html">Nero Digital Audio Encoder</a> if you are on unix / linux.</li>
</ul>
<blockquote class="mac">
<h3>Extra pre-requisites for Mac OS X</h3>
<p>Mac OS X users need to install the <a title="Mac Developer's Center" href="http://developer.apple.com/mac/">Apple Developer Tools (aka XCode)</a> in order to compile software, also, for building the x264 encoder, you will need to get and install <a href="http://www.tortall.net/projects/yasm/wiki/Download">YASM</a>.</p></blockquote>
<p>Now, you have to build and install all the tools, AND they have to be on any directory in your executable path. M<strong>y scripts assume that all the tools are in your executable path</strong>.<br />
<span id="more-562"></span></p>
<h2>Building x264</h2>
<p>Building x264 is usually a matter of just typing:</p>
<pre>./configure</pre>
<p>in the source directory, and then the usual:</p>
<pre>make</pre>
<p>and</p>
<pre>make install</pre>
<p>If you happen to have any problem with the building process, usually a simple google search with the error string is all you need.</p>
<h2>Building mplayer</h2>
<p>The process of building mplayer is certainly similar, BUT if you plan to use the video thumbnail and poster frame generation on my scripts, you will have to get and compile the jpeg libraries (if you don&#8217;t have them already) BEFORE building mplayer, this should be also a really easy thing to do: go get the libjpeg sources from <a href="http://www.ijg.org/">HERE</a>, and then configure, build and install.</p>
<p>Now, you have to download the latest SVN version of mplayer, assuming that you have the subversion client enabled, you can get the whole source tree by typing:</p>
<pre>svn checkout svn://svn.mplayerhq.hu/mplayer/trunk mplayer</pre>
<p>Now, you need to enable some things at configure time for mplayer and mencoder to work nice with the scripts, so our configure line will look something like this</p>
<pre>./configure --disable-gui --enable-png --enable-jpeg</pre>
<p>Note: there should be no reason at all for the &#8211;enable-jpeg flag, but for some reason that I ignore, mplayer wont detect my libjpeg install if i don&#8217;t force it like that, also, the &#8211;disable-gui option is to save some compile time, since we don&#8217;t plan to use any of the GUI features on mplayer.</p>
<p>Now, its time to build, so type:</p>
<pre>make</pre>
<p>and then, if you get no errors, you are safe to type:</p>
<pre>make install</pre>
<p>At this point you should have a working install, but since we want to be 100% sure that you REALLY have a working install, in any terminal type this:</p>
<pre>mencoder -ovc help</pre>
<p>and you should get something like this (please notice the x264 part, that is fundamental for everything to work)</p>
<pre>Available codecs:

   copy     - frame copy, without re-encoding. Doesn't work with filters.
   frameno  - special audio-only file for 3-pass encoding, see DOCS.
   raw      - uncompressed video. Use fourcc option to set format explicitly.
   lavc     - libavcodec codecs - best quality!
   vfw      - VfW DLLs, read DOCS/HTML/en/encoding-guide.html.
   qtvideo  - QuickTime DLLs, currently only SVQ1/3 are supported.
   x264     - H.264 encoding</pre>
<p>now let&#8217;s verify the mplayer part, again, in any terminal type:</p>
<pre class="pre_terminal">mplayer -vo help</pre>
<p>and you should get something like this (here, notice the PNG and JPEG bits, this is fundamental if you plan to use the thumbnail and poster generation features).</p>
<pre>Available video output drivers:
	macosx	Mac OSX Core Video
	quartz	Mac OSX (Quartz)
	xv	X11/Xv
	x11	X11 ( XImage/Shm )
	xover	General X11 driver for overlay capable video output drivers
	gl	X11 (OpenGL)
	gl2	X11 (OpenGL) - multiple textures version
	null	Null video output
	mpegpes	MPEG-PES file
	yuv4mpeg	yuv4mpeg output for mjpegtools
	png	PNG file
	jpeg	JPEG file
	tga	Targa output
	pnm	PPM/PGM/PGMYUV file
	md5sum	md5sum of each frame</pre>
<blockquote class="warning">
<h3>Very Important!</h3>
<p>After you compile and install mplayer, <strong>you need to copy</strong><strong> the midentify.sh script into any directory inside your executable path</strong>, for example <em>/usr/local/bin</em>. <strong>This is mandatory</strong>, because the <em>MKMP4</em> script will <strong>NOT</strong> be able to correctly identify the source video files without this tool. The <em><strong>midentify</strong></em> script (called <em>midentify.sh</em>) is located inside the <strong>TOOLS</strong> directory in the mplayer source tree.</p></blockquote>
<p>At this point, almost everything is ready, now it is time for the next step.</p>
<h2>Building and configuring the GPAC utilities</h2>
<p>If you are on Linux / Unix, building the GPAC utilities is a really simple process.</p>
<p>Get the latest stable release from <a href="http://gpac.sourceforge.net/home_download.php">here</a>, and then do the usual ./configure, make and make install.</p>
<blockquote class="mac"><p>For Mac OS users there is an extra step that you have to do if you want to be able to build and install the GPAC utilities without headaches, and it involves the editing of a source file in the package.</p>
<p>So, after you have downloaded the sources, open the file <strong>src/utils/os_net.c</strong> , line <strong>78</strong> reads:</p>
<pre>#ifndef __DARWIN__</pre>
<p>right <strong>AFTER</strong> it, add the following:</p>
<pre>typedef unsigned long u_long;</pre>
<p>save the file, and you can now configure, build and install the GPAC utilities (MP4Box) on Mac OS without any problem.</p></blockquote>
<h2>Installing the HE-AAC (aacPlus) audio encoder.</h2>
<p>This is a pretty simple step, if you are on a Mac, <a title="Download the AacPlus Encoder for Mac OS" href="http://blog.massanti.com/wp-content/uploads/2008/09/aacplusencoder.zip">get this encoder that i have built myself from the 3GPP sources</a> and copy it to <strong>/usr/local/bin</strong>, and if you are on linux, get the <a href="http://www.nero.com/enu/nero-aac-codec.html">Nero Digital Audio Encoder</a> from <a href="http://www.nero.com/enu/down-ndaudio.html">HERE</a> and again, copy it to <strong>/usr/local/bin</strong>. You can actually move the encoders to any directory that IS inside your executable path, /usr/local/bin is a good choice though <img src='http://blog.massanti.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<h2>Putting it all togheter.</h2>
<p>At this point, you have pretty much everything you would need to encode amazing quality H264 video and aacPlus audio, the only one remaining thing is some tool to put all this togheter in an *easy to use* way, so i have created the following bash script which pretty much simplifies the whole process.</p>
<pre class="brush: bash; title: ;">#! /bin/bash

# This bash script has been created by Diego Massanti
# www.massanti.com
#
# set -x # uncomment this for debugging
shopt -s nullglob # so the glob expands to nothing when there are no .mov files.

# User settings:

fileext=&quot;.mov&quot; # Set this variable to the video file extension that you want to search for when encoding whole directories.

# End user settings
# You should not change anything below this line unless you know what you are doing.

usage()
{
cat &lt;&lt; EOF
usage: $0 -f  [-w ] -b  [-q][-k][-t][-o ]

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* h264 video with he-aac audio encoding script by Diego Massanti. *
*                September 2008, Made in Argentina.               *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

OPTIONS:
   	-h	Show this message
-f	Path to the file to encode &lt; REQUIRED
   	-w	Resize video to fit inside this width while keeping the aspect ratio &lt; OPTIONAL
   	-b	Desired video bitrate &lt; REQUIRED
-o	Output directory for compressed media &lt; OPTIONAL (will use same as source if ommited)
   	-q 	Better quality encoding using 2 passes (slower) &lt; OPTIONAL
-k	Do not delete (keep) temporary files &lt; OPTIONAL
EOF
}
audiobitrate=48000
platform=&quot;&quot;
uname=`uname`
if [ $uname == &quot;Darwin&quot; ]; then
## 99% of chances that this is a Mac
platform=&quot;Mac&quot;
else
platform=&quot;Linux&quot;
fi

width=&quot;&quot;
bitrate=
deltemp=TRUE
quality=FALSE
poster=FALSE
filename=&quot;&quot;
rsize=&quot;&quot;
outdir=`pwd`
outFileName=&quot;&quot;
itemVideoBitrate=&quot;&quot;

while getopts &quot;:f:w:o:b:qktv&quot; OPTION; do
case $OPTION in
w ) width=$OPTARG;;
f ) filename=$OPTARG;;
b ) bitrate=$OPTARG;;
k ) deltemp=FALSE;;
q ) quality=TRUE;;
t ) poster=TRUE;;
o ) outdir=`cd &quot;$OPTARG&quot;; pwd`;;
h ) usage;;
\? ) usage
exit 1;;
* ) echo $usage
exit 1;;
esac
done

if [ &quot;$1&quot; == &quot;&quot; ]; then
usage
exit 0
fi

if [ &quot;$filename&quot; == &quot;&quot; ]; then
echo
echo you MUST supply a file to encode!, use the -f parameter. i.e: -f mymovie.avi
echo
usage
exit 1
fi
if [ &quot;$bitrate&quot; == &quot;&quot; ]; then
echo
echo you MUST specify a target bitrate!, use the -b parameter. i.e: -b 512
echo
usage
exit 1
fi

if [ &quot;$width&quot; != &quot;&quot; ]; then
rsize=&quot;-vf scale=$width:-3&quot;
rsizemsg=&quot;fit into $width pixels wide&quot;
else
rsize=&quot;&quot;
rsizemsg=&quot;Movie is not being resized.&quot;
fi

# Check if output directory exists
if [ -d &quot;$outdir&quot; ]; then
echo &quot;Target directory set to: $outdir&quot;

else
echo &quot;Error: '$outdir' does not exist!!&quot;
echo &quot;Can not continue, please make sure that the specified output directory exists. Exiting...&quot;
exit 1
fi

# Start the magic...

showMessage() {
echo &quot;MKMP4 : &quot;$1&quot;&quot;
}

initialize() {
if [ -d &quot;$filename&quot; ]; then
$filename = `cd $filename; pwd`
showMessage &quot;Output directory set to: $outdir.&quot;
showMessage &quot;Triggering the encoder with all media files in directory: $filename.&quot;
for file in &quot;$filename&quot;*$fileext; do
if [ -f &quot;$file&quot; ]; then
showMessage &quot;Will encode file: $file&quot;
startEncoders &quot;$file&quot;

fi
done
elif [ -f &quot;$filename&quot; ]; then
showMessage &quot;Triggering the encoder with source media: $filename.&quot;
startEncoders &quot;$filename&quot;

else
# input is no file and no directory ? WTF ?
echo &quot;Something really weird has happened here: $filename is not valid, exiting...&quot;
exit 1
fi
}

startEncoders() {
firstPass &quot;$1&quot;
if [ &quot;$quality&quot; == &quot;TRUE&quot; ]; then
secondPass &quot;$1&quot;
fi
extractAudio &quot;$1&quot;
encodeAAC &quot;$1&quot;
mux &quot;$1&quot;
if [ $poster == &quot;TRUE&quot; ]; then
createThumbnail &quot;$1&quot;
fi
if [ $deltemp == &quot;TRUE&quot; ]; then
cleanTemporaryFiles &quot;$1&quot;
fi
}
firstPass() {
local iFile=&quot;${1##*/}&quot;	# remove directory and keep only file name.
# First, lets get some basical information about this file, as FPS.
MOVIE_FPS=`midentify &quot;$1&quot; | grep FPS | cut -d = -f 2`
# Lets print some info to stdout.
showMessage &quot;Encoding: $1&quot;
showMessage &quot;Resizing to: $rsizemsg.&quot;
showMessage &quot;Total Bitrate: $bitrate kbps.&quot;
let &quot;caudiobitrate = $audiobitrate / 1000&quot;
let &quot;itemVideoBitrate = $bitrate - $caudiobitrate&quot;
showMessage &quot;Video Bitrate: $itemVideoBitrate kbps.&quot;
showMessage &quot;Audio Bitrate: $caudiobitrate kbps.&quot;
showMessage &quot;Platform: $platform.&quot;
# Lets start the encoding for the first pass.
showMessage &quot;Starting video encoding pass 1...&quot;
mencoder &quot;$1&quot; -o &quot;$outdir/${iFile%%.*}_temp.264&quot; -passlogfile &quot;$outdir/${iFile%%.*}&quot;_temp.log $rsize -ovc x264 -x264encopts bitrate=$itemVideoBitrate:frameref=8:bframes=3:b_adapt:b_pyramid:weight_b:partitions=all:8x8dct:me=umh:subq=6:trellis=2:brdo:threads=auto:pass=1:analyse=all -of rawvideo -nosound

}

secondPass() {
local iFile=&quot;${1##*/}&quot;	# remove directory and keep only file name.
showMessage &quot;Starting video encoding pass 2...&quot;
mencoder &quot;$1&quot; -o &quot;$outdir/${iFile%%.*}_temp.264&quot; -passlogfile &quot;$outdir/${iFile%%.*}&quot;_temp.log $rsize -ovc x264 -x264encopts bitrate=$itemVideoBitrate:frameref=8:bframes=3:b_adapt:b_pyramid:weight_b:partitions=all:8x8dct:me=umh:subq=6:trellis=2:brdo:threads=auto:pass=2:analyse=all -of rawvideo -nosound
}

extractAudio() {
local iFile=&quot;${1##*/}&quot;	# remove directory and keep only file name.
showMessage &quot;Extracting Audio...&quot;
mplayer &quot;$1&quot; -af resample=48000:0:2,channels=2,volnorm=1:0.25,format=s16le -ao pcm:file=&quot;$outdir/${iFile%.*}_temp.wav&quot; -vc dummy -vo null
}

encodeAAC() {
local iFile=&quot;${1##*/}&quot;	# remove directory and keep only file name.
if [ &quot;$platform&quot; == &quot;Mac&quot; ]; then
enhAacPlusEnc &quot;$outdir/${iFile%.*}_temp.wav&quot; &quot;$outdir/${iFile%.*}_temp.aac&quot; $audiobitrate s
else
neroAacEnc -br 48000 -he -if $outdir/${iFile%.*}_temp.wav -of $outdir/${iFile%.*}_temp.mp4
fi
}

mux() {
local iFile=&quot;${1##*/}&quot;	# remove directory and keep only file name.
MP4Box -add &quot;$outdir/${iFile%.*}_temp.264#video:fps=$MOVIE_FPS&quot; &quot;$outdir/${iFile%.*}.m4v&quot;
if [ &quot;$platform&quot; == &quot;Mac&quot; ]; then
MP4Box -add &quot;$outdir/${iFile%.*}_temp.aac&quot; -sbr &quot;$outdir/${iFile%.*}.m4v&quot;
else
MP4Box -add &quot;$outdir/${iFile%.*}_temp.mp4#audio&quot; &quot;$outdir/${iFile%.*}.m4v&quot;
fi
name=$outdir/${iFile%.*}
album=&quot;The Mac Video Archive&quot;
author=&quot;Apple Computer // massanti.com&quot;
comment=&quot;Professionally encoded by Diego Massanti&quot;
created=&quot;2007&quot;
MP4Box -inter 500 -itags album=&quot;$album&quot;:artist=&quot;$author&quot;:comment=&quot;$comment&quot;:created=&quot;$created&quot;:name=&quot;$name&quot; -lang English &quot;$outdir/${iFile%.*}&quot;.m4v
}

createThumbnail() {
local iFile=&quot;${1##*/}&quot;	# remove directory and keep only file name.
mplayer &quot;$1&quot; -ss 10 -nosound $rsize -ssf lgb=1.0 -sws 7 -vo jpeg:outdir=$outdir -frames 1
mv &quot;$outdir/00000001.jpg&quot; &quot;$outdir/${iFile%.*}.jpg&quot;
mplayer &quot;$1&quot; -ss 10 -nosound -vf scale=150:-3 -ssf lgb=1.0 -sws 7 -vo jpeg:outdir=$outdir -frames 1
mv &quot;$outdir/00000001.jpg&quot; &quot;$outdir/${iFile%.*}_small.jpg&quot;
}

cleanTemporaryFiles() {
local iFile=&quot;${1##*/}&quot;	# remove directory and keep only file name.
showMessage &quot;Removing temporary files...&quot;
rm &quot;$outdir/${iFile%.*}&quot;_temp*
}

initialize</pre>
<p>You can also download the script by clicking <a title="Download the MKMP4 encoding script" href="http://blog.massanti.com/wp-content/uploads/2008/09/mkmp4.zip">here</a> in order to keep proper code formatting. Installation is really simple, just move it to <strong>/usr/local/bin</strong>, give it execution rights (<strong>chmod +x /usr/local/bin/mkmp4</strong>) and done.</p>
<p>This script is really easy to use and implement, basically the script expects the following <strong>MANDATORY</strong> parameters in the command line:</p>
<ul>
<li>-f to specify the source media <strong>(can be a single file or a whole directory with media files)</strong></li>
<li>-b to specify the target bitrate for the final h264 encoded movie</li>
<li>-w to specify the target width for the final h264 encoded movie</li>
</ul>
<p>So for example, typing:</p>
<pre>mkmp4 -f /path/to/some/video.avi -b 512 -w 640</pre>
<p>will create a MP4 video file with a bitrate of 512kbps and a frame width of 640 pixels (please note that mencoder will correctly take care of the aspect ratio for the final movie and the resize will just look OK.)</p>
<p>Optional parameters for the MKMP4 script:</p>
<ul>
<li>-q turns on 2 pass encoding: This will increase the final quality (and the encoding time), but it worths the extra wait if you care about quality.</li>
<li>-k to keep temporary files: The script will create several temporary files during the encoding process, if for whatever reason you want to keep that files, you should use this option.</li>
<li>-o to specify a target directory: By default, the mkmp4 script will place the output video in the working directory (the directory from where you called the script), if you want to change that behavior, just use this option.</li>
<li>-t to turn ON thumbnail and poster frame generation: If you use this flag, mkmp4 will create a thumbnail and a poster frame that you can then use if you plan to publish your videos on the web.</li>
</ul>
<p>The following command line will create a 512kbps video, will set the target width to 640 pixels AND will use 2 pass encoding, will <strong>not</strong> delete temporary files, will create thumbnails and poster frames, and will place the files on the <em><strong>/target/directory/</strong></em> directory.</p>
<pre>mkmp4 -f /path/to/some/video.avi -b 512 -w 640 -k -q -t -o /target/directory/</pre>
<h3>Some things you need to know and FAQ&#8217;s about this script:</h3>
<ul>
<li>By default, when the -f parameter is a directory, the script will search for any .mov file inside it, encode it, and place the final mp4 file into the directory set in the -o parameter (or the current directory if you have ommited that parameter), if you want to change that behavior, just change the value of the <em><strong>fileext</strong></em> variable inside the script to whatever file extension you want to process.</li>
<li>Why are you reducing the audio level by 5db ? This is because with some old audio formats, for some reason that I really ignore, mplayer will distort the audio output. Now, if you take a closer look, you will see that right after the volume filter, im applying a normalization filter to get the audio back to 0db, so the output audio level will always be correct no matter what happens.</li>
<li>Why are you forcing the audio output to be always stereo ? what if i want to encode mono material ?: Just modify the audio encoder trigger.</li>
<li>The output media produced by this script is automatically interleaved and is fully compatible (and has been tested) with <a href="http://www.adobe.com/products/flashmediaserver/">Flash Media Server 3</a> and <a href="http://www.wowzamedia.com/">Wowza Media Server Pro</a>.</li>
</ul>
<p>There are a lot of things that could be improved around here, and so far i have not tested this in any platform other than Mac OS Leopard, but so far, this should work in any Linux / Unix variant too without too much work.</p>
<p>If you are interested to get an idea of how the video results will look, you can take a look a <a href="http://blog.massanti.com/apple-video-archive/iphone/">The Apple Video Archive</a> here on this site.</p>
<p>As usual, comments / feedback and suggestions are welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.massanti.com/2008/09/26/mkmp4-automated-h264-aacplus-encoder-script-mac-linux/feed/</wfw:commentRss>
		<slash:comments>67</slash:comments>
		</item>
		<item>
		<title>Keeping track of your users hardware / Software with Sparkle and PHP.</title>
		<link>http://blog.massanti.com/2008/04/15/sparkle-php-updates-script-tracking/</link>
		<comments>http://blog.massanti.com/2008/04/15/sparkle-php-updates-script-tracking/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 05:52:23 +0000</pubDate>
		<dc:creator>Diego Massanti</dc:creator>
				<category><![CDATA[Apple / Macintosh]]></category>
		<category><![CDATA[Computers & Tech]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[sparkle]]></category>

		<guid isPermaLink="false">http://massanti.com/?p=145</guid>
		<description><![CDATA[Some months ago I started using the amazing Sparkle framework to manage the auto-update features on my MediaInfo Mac application, and it wasn&#8217;t until today that I decided to update my Sparkle version to the latest one from the SVN and give it a try, mostly because I&#8217;m planning to release upcoming MediaInfo Mac builds [...]]]></description>
			<content:encoded><![CDATA[<p><img class="right" title="Sparkle Dialog Screenshot" src="http://blog.massanti.com/wp-content/uploads/2008/04/sparkle.jpg" alt="" />Some months ago I started using the amazing <a href="http://sparkle.andymatuschak.org/">Sparkle</a> framework to manage the auto-update features on my <a href="http://massanti.com/mediainfo">MediaInfo Mac</a> application, and it wasn&#8217;t until today that I decided to update my Sparkle version to the latest one from the SVN and give it a try, mostly because I&#8217;m planning to release upcoming MediaInfo Mac builds as 32 and 64bit Universal Binaries, but that&#8217;s a different story.</p>
<p>I have found that with the new Sparkle version, you can kindly ask the user if he/she wants to send anonymous information about the system they are using to run your application, like the MacOS version, amount of RAM, number of processors, language, etc. This is specially useful for many reasons (at least for me), first, I&#8217;m starting the process of localizing my application, so that gives me a pretty good idea of what languages are the most used so far, and, finally, it will let me now <strong>when</strong> I <strong>could</strong> stop caring about Tiger and start a Leopard only version of my Software.</p>
<p>The idea is pretty simple, you have a PHP script that generates the whole AppCast compatible feed, and all the hardware / software information is passed as url parameters, as in <em><strong>feed.php?osVersion=10.2.5&amp;lang=en</strong></em> &#8230; etc.</p>
<p>So, by using good old Google, i found a <a href="http://www.randomsequence.com/articles/php-rss-appcast-generator/">really good script to generate the AppCast feed</a>, but, i also needed a way to store the tracking data into a DB for later usage, and, i came up with this (really barebones, but working) prototype.</p>
<p>So, i did some minor modifications to the original PHP code; first, i changed the way to parse the version number from the file names, so as long as you use the <em><strong>application_name_1.5.zip</strong></em> pattern it will work, please note that you can put as much revision or subversion numbers as you wish: <strong><em>application_name_1.2.3.4.5.zip</em></strong> should also work.</p>
<p>This is the code snippet as i have it working now on my development server:</p>
<pre><code>&lt;?php
// ----------------------------------------------------------- //
// Script to generate an RSS appcast from folder contents
// Version 1.0.1
//
// (cc) Random Sequence 2007, Some Rights Reserved
//
// Licenced under a creative commons Attribution ShareAlike licence
// http://creativecommons.org/licenses/by-sa/3.0/
// ----------------------------------------------------------- //
// REQUIRES PHP 5 or greater
// Tested with APACHE 1 &amp; 2 on Mac OS X, Debian Linux   

// -------------------- BEGIN CONFIG ------------------------- //

$title = "Downloads";           // Used as feed title in feed readers
$description = "File List";     // Used as feed description in feed readers

// these are the types of files to list in the appcast &amp; their MIME Types. Use lower case.
$fileTypes = array( "zip"=&gt;"application/zip",
                    "tgz"=&gt;"application/x-gtar",
                    "tar"=&gt;"application/x-tar",
                    "dmg"=&gt;"application/octet-stream"
                    );

// -------------------- END OF CONFIG ------------------------ //

$appcastHeader = "&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;
&lt;rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:sparkle=\"http://www.andymatuschak.org/xml-namespaces/sparkle\"&gt;
&lt;channel&gt;
    &lt;title&gt;MediaInfo Mac Software Updates Feed&lt;/title&gt;
    &lt;link&gt;http://massanti.com/mediainfo&lt;/link&gt;
    &lt;description&gt;AppCast compatible feed for MediaInfo Mac Updates&lt;/description&gt;
    &lt;language&gt;en&lt;/language&gt;
";
$appcastTemplate = "
        &lt;item&gt;
            &lt;guid  isPermaLink=\"false\"&gt;*guid*&lt;/guid&gt;
            &lt;title&gt;*title*&lt;/title&gt;
            &lt;description&gt;&lt;![CDATA[*description*]]&gt;&lt;/description&gt;
            &lt;pubDate&gt;*pubdate*&lt;/pubDate&gt;
            &lt;enclosure
                sparkle:version=\"*version*\"
                type=\"*type*\"
                url=\"*url*\"
                length=\"*length*\" /&gt;
        &lt;/item&gt;";

$appcastFooter = "
&lt;/channel&gt;
&lt;/rss&gt;";
$dir = getcwd()."/releases";
$files = scandir("$dir");
$etag = sha1(implode("/",$files));
rsort($files);

// support for conditional fetch
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &amp;&amp; $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
    header('HTTP/1.1 304 Not Modified');
    exit;
}

$appcast = $appcastHeader;

$link = "http://".$_SERVER["HTTP_HOST"].$_SERVER["PHP_SELF"];

$appcast = str_replace("*link*",$link,$appcast);
$appcast = str_replace("*title*",$title,$appcast);
$appcast = str_replace("*description*",$description,$appcast);

foreach ($files as $file) {
	preg_match("/.*\.([a-z09]{1,3})$/i",$file,$matches);
	if (isset($matches[1]) &amp;&amp; isset($fileTypes[strtolower($matches[1])]) !== false) {
		$appcastFile = $appcastTemplate;
		$folderUrl = "http://".$_SERVER["HTTP_HOST"].substr($_SERVER["PHP_SELF"],0,strrpos($_SERVER["PHP_SELF"],"/"))."/releases/";
		$guid = $folderUrl.sha1($file);
		$path_parts = pathinfo($file);
		$title = mb_convert_case( str_replace("_", " ", $path_parts['filename']) , MB_CASE_TITLE, "UTF-8");
		//$description = preg_replace("/^(.*?)([0-9]+[a-z])\.([a-z09]{1,3})$/i","$1",$file);
		$description = getFileDescription("releases/".$file.".html");
		$pubdate = date("D, d M Y H:i:s",filectime("releases/".$file));
		$type = $fileTypes[strtolower($matches[1])];
		$url = $folderUrl.$file;
		$length = filesize("releases/".$file);
		preg_match("/(\d+\.)+\d+/", $file, $m_version);
		$version = $m_version[0];
		//$version = preg_replace("/^(.*?)([0-9]+[a-z])\.([a-z09]{1,3})$/i","$2",$file);
		$appcastFile = str_replace("*guid*",$guid,$appcastFile);
		$appcastFile = str_replace("*title*",$title,$appcastFile);
		$appcastFile = str_replace("*description*",$description,$appcastFile);
		$appcastFile = str_replace("*version*",$version,$appcastFile);
		$appcastFile = str_replace("*pubdate*",$pubdate,$appcastFile);
		$appcastFile = str_replace("*type*",$type,$appcastFile);
		$appcastFile = str_replace("*url*",$url,$appcastFile);
		$appcastFile = str_replace("*length*",$length,$appcastFile);
		$appcast .= $appcastFile;
	}
}

// Reads a file called filename.html and returns the HTML output

function getFileDescription($fileName) {
	$handle = @fopen("$fileName", "r");
	$rValue = "";
	if ($handle) {
		while (!feof($handle)) {
			$buffer = fgets($handle, 4096);
			$rValue .= $buffer;
		}
		fclose($handle);
	}
	return $rValue;
}

$appcast .= $appcastFooter;
/*"GET /u.php?UUID=F2958FD0-2EC9-40CA-8171-C63D663AAE90&amp;
		osVersion=10.5.4
		cputype=7
		cpu64bit=1
		cpusubtype=4
		model=P5KC
		ncpu=4
		lang=en
		appName=MediaInfo%20Mac&amp;appVersion=0.7.7.50
		cpuFreqMHz=2400
		ramMB=2048 HTTP/1.1" 200 575 "-" "MediaInfo Mac/0.7.7.50 Sparkle/282"
		*/
// Database Functions

$vars = array('osVersion' , 'cputype', 'cpu64bit', 'cpusubtype', 'model', 'ncpu', 'lang', 'appName', 'appVersion', 'cpuFreqMHz', 'ramMB', 'UUID');
$values = array();
$shouldInsert = true;
foreach ($vars as $item) {
	if (isset($_GET[$item])) {
		$values[$item] = html_entity_decode($_GET[$item]);
	} else {
		if ($item != 'cpu64bit') {
			$shouldInsert = false;
		}

	}
}
if (isset($_GET['cpu64bit'])) {
	$values['cpu64bit'] = html_entity_decode($_GET['cpu64bit']);
} else {
	$values['cpu64bit'] = '0';
}

if ($shouldInsert == true) {
	$mysqli = new mysqli("yourDBHost", "yourDBUser", "yourDBPassword", "yourDBName");

	if (mysqli_connect_errno()) {
	    printf("Connect failed: %s\n", mysqli_connect_error());
	    exit();
	}

	$stmt = $mysqli-&gt;prepare("INSERT INTO stats (os_version, cpu_type, cpu_64bit, cpu_subtype, model, n_cpu, lang, app_name, app_version, cpu_freq, ram_mb, UUID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
	$stmt-&gt;bind_param('siississsiis', $values['osVersion'], $values['cputype'], $values['cpu64bit'], $values['cpusubtype'], $values['model'], $values['ncpu'], $values['lang'], $values['appName'], $values['appVersion'], $values['cpuFreqMHz'], $values['ramMB'], $values['UUID']);
	$stmt-&gt;execute();
	$stmt-&gt;close();

}

header("Content-type: application/xml; charset=UTF-8");
header("ETag: $etag");

echo $appcast;
exit;
?&gt;</code></pre>
<p>As usual, suggestions or improvements are welcome <img src='http://blog.massanti.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.massanti.com/2008/04/15/sparkle-php-updates-script-tracking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serverside video resizing script for ffmpeg or Mencoder</title>
		<link>http://blog.massanti.com/2007/10/01/serverside-video-resizing-script/</link>
		<comments>http://blog.massanti.com/2007/10/01/serverside-video-resizing-script/#comments</comments>
		<pubDate>Mon, 01 Oct 2007 23:00:35 +0000</pubDate>
		<dc:creator>Diego Massanti</dc:creator>
				<category><![CDATA[Computers & Tech]]></category>
		<category><![CDATA[Web & Design]]></category>
		<category><![CDATA[aspect]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[ffmpeg]]></category>
		<category><![CDATA[keep]]></category>
		<category><![CDATA[midentify]]></category>
		<category><![CDATA[movies]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ratio]]></category>
		<category><![CDATA[resize]]></category>
		<category><![CDATA[scale]]></category>
		<category><![CDATA[script]]></category>

		<guid isPermaLink="false">http://massanti.com/2007/10/01/serverside-video-resizing-script/</guid>
		<description><![CDATA[Some days ago, while working on a project that involves the re-encoding of a lot of videos coming from several sources, aspect ratios, resolutions, etc, i found myself in the situation where i needed to &#8220;standarize&#8221; somehow all the videos to a prefixed size in order to place them on a fixed space in a [...]]]></description>
			<content:encoded><![CDATA[<p>Some days ago, while working on a project that involves the re-encoding of a lot of videos coming from several sources, aspect ratios, resolutions, etc, i found myself in the situation where i needed to &#8220;standarize&#8221; somehow all the videos to a prefixed size in order to place them on a fixed space in a web page.<br />
While most linux tools like ffmpeg or mencoder include native functions to scale or resize the video, they don&#8217;t care about the aspect ratios or about the fact that most video encoders expect mod16 values for the height and width values.<br />
So my situation was like this:</p>
<p>I needed to make all the videos 480 pixels high, and scale the width proportionally.</p>
<p>That being said, i came up with this PHP script that i call from inside a bash script:</p>
<pre class="brush: php; title: ;">#!/usr/bin/php
&lt;?php
$cmdWidth = 'midentify '.$argv[1];
$finalHeight = $argv[2];
exec($cmdWidth, $output);

foreach ($output as $value) {
    if (strstr($value, &quot;ID_VIDEO_WIDTH&quot;)) {

		$width = parseResult($value);
    }
    if (strstr($value, &quot;ID_VIDEO_HEIGHT&quot;)) {
    	$height = parseResult($value);
    }
}
$frameSize = $width / $height;
$finalWidth = $finalHeight * $frameSize;
echo getMod16(round($finalWidth)) . &quot;x&quot; . getMod16(round($finalHeight)) . &quot;\n&quot;;
function parseResult($line) {
	$v1 = explode(&quot;=&quot;,$line);
	$v20 = $v1[1];

	//var_dump($v2);
	return $v20;
}
function getMod16($number){
	while (fmod($number, 16) != 0) {
		$number ++;
	}
	return $number;
}
?&gt;</pre>
<p>This script assumes that you have the &#8220;midentify&#8221; utility (wich comes with mplayer) installed in your path, and expects 2 arguments, being argument 1 the movie you want to resize and argument 2 the actual height you want to reach.<br />
That being said, suppose you have a movie that is 848 pixels width and 480 pixels high and you want to re-scale it so it fits inside a 400 pixels high space, you would call the script like this:</p>
<p><code>./resizer mymovie.avi 400</code></p>
<p>The script will output this:</p>
<p><code>720x400</code></p>
<p>You can use later this value as an input parameter for ffmpeg for example.</p>
<p>Before somebody asks, the reason because i used PHP instead of BASH, is simply because bash does not supports floats.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.massanti.com/2007/10/01/serverside-video-resizing-script/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

