<?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>meloncholy</title> <atom:link href="http://meloncholy.com/feed/" rel="self" type="application/rss+xml" /><link>http://meloncholy.com</link> <description>Andrew Weeks</description> <lastBuildDate>Sat, 05 May 2012 01:47:16 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.2</generator> <item><title>Node.js Video Gallery</title><link>http://meloncholy.com/blog/node-js-video-gallery/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=node-js-video-gallery</link> <comments>http://meloncholy.com/blog/node-js-video-gallery/#comments</comments> <pubDate>Mon, 30 Apr 2012 16:28:49 +0000</pubDate> <dc:creator>Andrew</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[Node.js]]></category> <guid
isPermaLink="false">http://meloncholy.com/?p=267</guid> <description><![CDATA[A few months ago, I wrote a Metro-style video gallery with Ajax, infinite scrolling and other fun stuff. I&#8217;ve now rewritten it in Node.js, which was surprisingly cathartic after coding the PHP original. There&#8217;s a load of bumf about the &#8230; <a
class="more-link" href="http://meloncholy.com/blog/node-js-video-gallery/">Keep&#160;reading&#160;<span
class="meta-nav">&#62;</span></a>]]></description> <content:encoded><![CDATA[<p>A few months ago, I wrote a Metro-style video gallery with Ajax, infinite scrolling and other fun stuff. I&#8217;ve now rewritten it in Node.js, which was surprisingly cathartic after coding the PHP original.</p><p>There&#8217;s a load of bumf about the <a
href="http://meloncholy.com/portfolio/video-gallery/">original PHP version here</a> (mostly relevant) and some supplementary info about <a
href="http://meloncholy.com/portfolio/node-video-gallery/">this version here</a>, though probably the best thing to do is to try the <a
href="http://bits.meloncholy.com/node-video-gallery/">demo site</a>. Yay!</p><p><a
href="https://github.com/meloncholy/node-video-gallery" class="source-link">Source on GitHub</a><span
id="more-267"></span></p><h2>Nota bene</h2><p>The front end code is (almost) identical to that in the PHP version. It could do with updating a bit, e.g. to use the HTML5 history API rather than <code>#!</code> and moving the jQuery events over to <code>on</code>. But other than that I think it works fine.</p><p>I redid an existing project so I could focus on how Node, and not the app itself, works. It was definitely a learning process for me, and I&#8217;m sure I could have done things better (and would probably do some bits better if I were starting again now). So if you have any feedback on how I could improve things, I&#8217;d love to hear.</p><p>With those health warnings out of the way&hellip;</p><h2>Settings</h2><p>You&#8217;ll need to set up a MySQL database first (see <a
href="#sample-content">sample content</a>). Then there are some configuration things to do</p><p><code>/config/app.json</code> (Please rename <code>app-sample.json</code>.)</p><ul><li><strong>localPort</strong> &#8211; Local port to use</li><li><strong>sessionSecret</strong> &#8211; Session secret for Express</li><li><strong>siteUrl</strong> &#8211; Public URL for your site</li><li><strong>mode</strong> &#8211; <em>development</em> or <em>production</em>. <em>development</em> gives more error messages, while <em>production</em> uses minimized, combined public JS files that load a lot faster.</li><li><strong>batchSize</strong> &#8211; Number of videos to load at once in infinite scroll.</li><li><strong>videoCount</strong> &#8211; Approximate number of videos in the database. Just used for bragging rights in a few places.</li><li><strong>cookiePath</strong> &#8211; Cookie path to use. Unless you want to restrict it to a subfolder, I&#8217;d suggest using <code>/</code>.</li><li><strong>siteTitle</strong> &#8211; Name of the site. Used in browser title bar and elsewhere.</li><li><strong>siteTitlePost</strong> &#8211; Text to stick in the title bar after the video name (where appropriate).</li><li><strong>siteDescription</strong> &#8211; Meta description content.</li><li><strong>maxRelatedVideos</strong> &#8211; If we haven&#8217;t come via a search (via a link or refresh), show this many related videos at the side of a video.</li><li><strong>maxSimilarVideos</strong> &#8211; Show this many similar videos at the bottom of a video. See video.js for more. This number should obviously work for the largest video size offered.</li><li><strong>prettyLink</strong> &#8211; Prepend this to each video&#8217;s URL for SEO, so if this were <code>amazing-stunts</code>, the URLs would be something like <code>http://example.com/#!amazing-stunts/name-of-this-video</code>.</li><li><strong>jQueryCdnUrl</strong> &#8211; In <em>production</em> mode, load jQuery from here.</li><li><strong>gaAccount</strong> &#8211; Your Google Analytics UA number.</li><li><strong>gaDomain</strong> &#8211; Your Analytis domain.</ul><p>Example</p><pre>
{
	"localPort": 3000,
	"sessionSecret": "session secret",
	"siteUrl": "http://bits.meloncholy.com/node-video-gallery/",
	"mode": "development",
	"batchSize": 20,
	"videoCount": 300,
	"cookiePath": "/",
	"siteTitle": "Video Gallery",
	"siteTitlePost": " | Video Gallery",
	"siteDescription": "This Video Gallery is a web app with lots of jQuery and Node goodness. Yum.",
	"maxRelatedVideos": 19,
	"maxSimilarVideos": 7,
	"prettyLink": "video",
	"jQueryCdnUrl": "http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js",
	"gaAccount": "UA-XXXXXXXX-X",
	"gaDomain": "meloncholy.com"
}
</pre><p><code>/config/database.json</code></p><ul><li><strong>host</strong> &#8211; Database host</li><li><strong>database</strong> &#8211; Database name</li><li><strong>user</strong> &#8211; Database user</li><li><strong>password</strong> &#8211; Database password</ul><p>Example</p><pre>
{
	"host": "localhost",
	"database": "database",
	"user": "user",
	"password": "password"
}
</pre><h2>Dependencies</h2><p>To get it to work, you&#8217;ll also need</p><ul><li><a
href="https://github.com/visionmedia/express">Express</a></li><li><a
href="https://github.com/visionmedia/jade">Jade</a></li><li><a
href="https://github.com/pgte/konphyg">Konphyg</a></li><li><a
href="https://github.com/meloncholy/vid-streamer">VidStreamer.js</a></li></ul><h2 id="sample-content">Sample content</h2><p>If you want to get going quickly, you can use the sample videos, photos and database from the <a
href="https://github.com/meloncholy/video-gallery">PHP Video Gallery</a> on GitHub (placeholder and database folders resp.).</p><p>And try something like this for <code>vidStreamer.json</code> (in <code>/node_modules/vid-streamer/config</code>) to get it to serve up the sample content.</p><pre>
{
	"mode": "development",
	"forceDownload": false,
	"random": true,
	"rootFolder": "/path/to/express/public/",
	"rootPath": "node-video-gallery/",
	"server": "VidStreamer.js/0.1"
}
</pre><h2>Thanks</h2><p>The download includes Longtail Video&#8217;s <a
href="http://www.longtailvideo.com/">JW Player</a>, released under Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) licence. Commercial licences are also available. You&#8217;re of course welcome to swap the player for another one if you don&#8217;t like it, though you&#8217;ll need to change some of the source files that set up parameters to pass to the player.</p><p>The sample video footage comprises some short video clips and still images of these video clips by <a
href="http://www.theycallusanimals.com/">Catrin Hedstr&ouml;m</a> and released under a Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) licence. It&#8217;s gorgeous footage too &#8211; do check it out!</p><p><a
href="https://github.com/meloncholy/node-video-gallery" class="source-link">Source on GitHub</a></p><h2>Legal fun</h2><p>Copyright &copy; 2012 Andrew Weeks http://meloncholy.com</p><p>Video Gallery is licensed under the <a
href="http://meloncholy.com/licence/">MIT licence</a>.</p><p>Includes some code written by others; see source for credits and licence details (though it&#8217;s all permissive).</p> ]]></content:encoded> <wfw:commentRss>http://meloncholy.com/blog/node-js-video-gallery/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>VidStreamer.js &#8211; a simple Node.js video streamer</title><link>http://meloncholy.com/blog/vidstreamer-js-a-simple-node-js-video-streamer/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=vidstreamer-js-a-simple-node-js-video-streamer</link> <comments>http://meloncholy.com/blog/vidstreamer-js-a-simple-node-js-video-streamer/#comments</comments> <pubDate>Thu, 19 Apr 2012 16:19:27 +0000</pubDate> <dc:creator>Andrew</dc:creator> <category><![CDATA[Code]]></category> <category><![CDATA[JavaScript]]></category> <category><![CDATA[Node.js]]></category> <guid
isPermaLink="false">http://meloncholy.com/?p=252</guid> <description><![CDATA[I&#8217;ve been really keen to learn Node.js for a while now, so I decided to translate the video gallery I wrote a while ago into Node (nearly done!). At the back end, the video gallery uses xmoovStream Server to stream &#8230; <a
class="more-link" href="http://meloncholy.com/blog/vidstreamer-js-a-simple-node-js-video-streamer/">Keep&#160;reading&#160;<span
class="meta-nav">&#62;</span></a>]]></description> <content:encoded><![CDATA[<p>I&#8217;ve been really keen to learn Node.js for a while now, so I decided to translate the <a
href="http://meloncholy.com/portfolio/video-gallery/">video gallery</a> I wrote a while ago into Node (nearly done!). At the back end, the video gallery uses <a
href="http://stream.xmoov.com/">xmoovStream Server</a> to stream the videos to the popular JW Player (I used Flash videos as I wanted to support bitrate switching).</p><p>As using a LAMP stack to support a Node app seemed wrong, I wrote a simple JavaScript video streamer. Most of the requirements came from looking at how xmoovStream Server works.</p><ul><li>Supports http pseudostreaming</li><li>Streams Flash video and can resume streams</li><li>Streams other video and file formats and can resume these streams too</li><li>Works with JW Player&#8217;s bitrate switching</li></ul><p><a
href="https://github.com/meloncholy/vid-streamer" class="source-link">Source on GitHub</a> <span
id="more-252"></span></p><h2>Using VidStreamer</h2><p>To make a standalone video streamer, try something like this</p><pre>
var http = require("http");
var vidStreamer = require("vid-streamer");
var app = http.createServer(vidStreamer);
app.listen(3000);
console.log("VidStreamer.js up and running on port 3000");
</pre><p>And here&#8217;s an example of including it in an Express app</p><pre>
var app = require("express").createServer();
var vidStreamer = require("vid-streamer");
app.get("/videos/", vidStreamer);
app.listen(3000);
</pre><h2>Settings</h2><p>There are a few things to twiddle in <code>/config/vidStreamer.json</code>. (Please rename <code>vidStreamer-sample.json</code>.)</p><ul><li><strong>mode</strong> &#8211; Not actually used right now. :)<li><strong>forceDownload</strong> &#8211; Tell the browser to show a save file dialog.<li><strong>random</strong> &#8211; Show a random file instead of the one named (see below).<li><strong>rootFolder</strong> &#8211; The root folder from which files are returned. Accessing subfolders is possible by putting them in the path.<li><strong>rootPath</strong> &#8211; The path assumed to match up with the root folder.<li><strong>server</strong> &#8211; Server string returned in the header.</ul><p>Standalone example</p><pre>
{
	"mode": "development",
	"forceDownload": false,
	"random": false,
	"rootFolder": "/path/to/videos/",
	"rootPath": "videos/",
	"server": "VidStreamer.js/0.1"
}
</pre><p>Example for Express. (Note that rootPath should be relative to the root URL of your Express app.)</p><pre>
{
	"mode": "development",
	"forceDownload": false,
	"random": false,
	"rootFolder": "/path/to/express/public/",
	"rootPath": "",
	"server": "VidStreamer.js/0.1"
}
</pre><h2>Serving random files</h2><p>You can use VidStreamer to serve up random files instead of the actual file requested. This can be useful if you&#8217;re demoing an app that&#8217;s supposed to have hundreds of videos but you don&#8217;t want to go to the trouble of making them all.</p><ul><li>Which file to return is calculated from the requested file name, so the same one will be returned each time for the same name. This is useful if you want to switch between video bitrates for example.</li><li>The file returned will be of the same type (same extension) as the requested file.</li><li>The file returned will be from the same folder as the requested file.</li></ul><h2>Thanks</h2><p>I hadn&#8217;t really thought about how to write video streamer before, so <a
href="http://delog.wordpress.com/2011/04/25/stream-webm-file-to-chrome-using-node-js/">Devendra Tewari&#8217;s post</a> and of course the xmoovStream Server source were very useful to me.</p><p><a
href="https://github.com/meloncholy/vid-streamer" class="source-link">Source on GitHub</a></p><h2>Legal fun</h2><p>Copyright &copy; 2012 Andrew Weeks http://meloncholy.com</p><p>VidStreamer.js is licensed under the <a
href="http://meloncholy.com/licence/">MIT licence</a>.</p> ]]></content:encoded> <wfw:commentRss>http://meloncholy.com/blog/vidstreamer-js-a-simple-node-js-video-streamer/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Aaarg!</title><link>http://meloncholy.com/blog/aaarg-web-pages-that-suck/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=aaarg-web-pages-that-suck</link> <comments>http://meloncholy.com/blog/aaarg-web-pages-that-suck/#comments</comments> <pubDate>Thu, 26 Jan 2012 20:07:50 +0000</pubDate> <dc:creator>Andrew</dc:creator> <category><![CDATA[Comment]]></category> <guid
isPermaLink="false">http://meloncholy.com/?p=234</guid> <description><![CDATA[A few years ago, I came across a couple of sites on Web Pages That Suck. (Both of which, I&#8217;m delighted to say, are still in more or less their original states five years after that post was published.) While &#8230; <a
class="more-link" href="http://meloncholy.com/blog/aaarg-web-pages-that-suck/">Keep&#160;reading&#160;<span
class="meta-nav">&#62;</span></a>]]></description> <content:encoded><![CDATA[<p>A few years ago, I came across a couple of sites on <a
href="http://www.webpagesthatsuck.com/10-worst-web-pages-featured-on-web-pages-that-suck-in-2006.html">Web Pages That Suck</a>. (<a
href="http://www.hrodc.com/index.htm">Both</a> of <a
href="http://www.dokimos.org/ajff/">which</a>, I&#8217;m delighted to say, are still in more or less their original states five years after that post was published.)</p><div
id="attachment_237" class="wp-caption alignnone" style="width: 570px"><a
href="http://meloncholy.com/wordpress/wp-content/uploads/hrodc-postgraduate-training-courses.jpg"><img
src="http://meloncholy.com/wordpress/wp-content/uploads/hrodc-postgraduate-training-courses-thumb.jpg" alt="" title="HRODC postgraduate training courses" width="560" height="300" class="size-full wp-image-237" /></a><p
class="wp-caption-text">HRODC postgraduate training courses</p></div><div
id="attachment_239" class="wp-caption alignnone" style="width: 570px"><a
href="http://meloncholy.com/wordpress/wp-content/uploads/accept-jesus-forever-forgiven.jpg"><img
src="http://meloncholy.com/wordpress/wp-content/uploads/accept-jesus-forever-forgiven-thumb.jpg" alt="" title="ACCEPT JESUS, FOREVER FORGIVEN!" width="560" height="300" class="size-full wp-image-239" /></a><p
class="wp-caption-text">ACCEPT JESUS, FOREVER FORGIVEN!</p></div><p>While both are, of course, fine examples of important web design maxims, surely their impact would be much greater if they could be finessed into one great web page? After all, who could resist combining the eloquent brevity of a 1.2MB page full of tables with the understated finesse of animated rainbow gifs and autoplaying music?</p><p>Turns out I couldn&#8217;t. And, having just rediscovered the result, I thought I&#8217;d stick it up here.</p><p><a
href="http://bits.meloncholy.com/aaarg/">Aaarg!</a></p><p><em>To enjoy the full experience, including the music and a bird that follows your cursor around, please view in an old version of IE.</em></p> ]]></content:encoded> <wfw:commentRss>http://meloncholy.com/blog/aaarg-web-pages-that-suck/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Serving up random-but-consistent sample videos</title><link>http://meloncholy.com/blog/serving-up-random-but-consistent-sample-videos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=serving-up-random-but-consistent-sample-videos</link> <comments>http://meloncholy.com/blog/serving-up-random-but-consistent-sample-videos/#comments</comments> <pubDate>Tue, 03 Jan 2012 16:01:28 +0000</pubDate> <dc:creator>Andrew</dc:creator> <category><![CDATA[.htaccess]]></category> <category><![CDATA[Code]]></category> <category><![CDATA[PHP]]></category> <guid
isPermaLink="false">http://meloncholy.com/?p=181</guid> <description><![CDATA[Need to serve up some sample images or videos that are apparently random, but remain consistent each time you show them? Download source I recently uploaded a Video Gallery web app I&#8217;d made (demo, code download). Unfortunately I don&#8217;t have &#8230; <a
class="more-link" href="http://meloncholy.com/blog/serving-up-random-but-consistent-sample-videos/">Keep&#160;reading&#160;<span
class="meta-nav">&#62;</span></a>]]></description> <content:encoded><![CDATA[<p>Need to serve up some sample images or videos that are apparently random, but remain consistent each time you show them?</p><p><a
href="https://github.com/meloncholy/consistent-random" class="source-link">Download source</a></p><p>I recently uploaded a <a
href="http://meloncholy.com/portfolio/video-gallery/">Video Gallery</a> web app I&#8217;d made (<a
href="http://bits.meloncholy.com/video-gallery/">demo</a>, <a
href="https://github.com/meloncholy/video-gallery">code download</a>). Unfortunately I don&#8217;t have the real videos and pictures that it was supposed to use, so I thought I&#8217;d cut some clips from the silent-but-gorgeous <a
href="http://www.theycallusanimals.com/">They Call Us Animals</a> music video footage. But the Video Gallery has about 300 different videos in the database, and I really didn&#8217;t want to make 900 sample clips (each one in 720p, 480p and 360p). So I made about 10, which seems enough to give a little variety.</p><p>But I couldn&#8217;t just serve up any video. Using the HTTP pseudostreaming support in <a
href="http://www.longtailvideo.com/players/">JW Player</a>, the site lets users change video sizes while they&#8217;re watching, and the player will switch to a different resolution source file if one is available to improve the viewing experience. It looks good, but the effect was rather spoiled when the video selector returned a higher resolution version of a completely different clip.</p><p>So I wrote a little PHP script that would serve up an apparently random sample video consistently. <span
id="more-181"></span></p><h2>Using the code</h2><p>First set <code>$folder</code> to point at the folder where the files you want to serve are located. It&#8217;s currently set up to use the folder where the file is uploaded.</p><p>The file selector will serve up jpegs, pngs and flv files from the box. If you want to allow others, add their file extensions and MIME types to the <code>$ext_list</code> array. There are examples for CSS, PDF and HTML files in the source. (On a side note, please don&#8217;t add PHP to the list and use <code>$folder = '.'</code> unless you don&#8217;t mind it returning itself sometimes.)</p><p>To get a random-but-consistent file, link to it as any other file</p><pre>
&lt;a href="http://example.com/rotate.php?file=kittens.flv"&gt;link&lt;/a&gt;
</pre><pre>
&lt;img src="http://example.com/rotate.php?file=kittens.jpg" /&gt;
</pre><p>The file returned will be of that same type (flv or jpg above). It will not be kittens.flv, but you will get the same one every time you ask for kittens.flv.</p><h2>The code</h2><p>After performing a few checks on the file type and allowed extensions, I used <a
href="http://php.net/manual/en/function.crc32.php"><code>crc32</code></a> to convert the supplied filename into an integer and ran it through the modulus operator to get a number in the range of the file count in the current folder. Then it reads the chosen file and we&#8217;re done. And that&#8217;s it.</p><pre>
$ext_list = array();
$ext_list['gif'] = 'image/gif';
$ext_list['jpg'] = 'image/jpeg';
$ext_list['jpeg'] = 'image/jpeg';
$ext_list['png'] = 'image/png';
$ext_list['flv'] = 'video/x-flv';
$file = null;
$vid = null;
$vids = null;
$content_type = null;
if (!isset($_GET['file'])) return;
$file = pathinfo($_GET['file']);
// Just in case there's other stuff in the folder too (like this file)
if (!array_key_exists($file['extension'], $ext_list)) return;
if (substr($folder, -1) != '/') $folder .= '/';
// Select a file based on the given extension.
$vids = glob($folder . '*.' . $file['extension']);
$vid = $vids[abs(crc32($file['basename'])) % count($vids)];
$content_type = 'Content-type: ' . $ext_list[$file['extension']];
header ($content_type);
readfile($vid);
</pre><h2>Fun with .htaccess</h2><p>Supplying random-but-consistent videos like this changes their path, as it&#8217;s now necessary to include (at least) <code>consistent-random.php?file=</code>. Not ideal, but a few lines added to .htaccess can point the original paths at the new placeholder files.</p><pre>
RewriteBase /video-gallery/
RewriteRule ^images/thumb/([-_a-zA-Z0-9\.]+)$ placeholder/images/thumb/consistent-random.php?file=$1 [L]
RewriteRule ^images/full/([-_a-zA-Z0-9\.]+)$ placeholder/images/full/consistent-random.php?file=$1 [L]
RewriteRule ^videos/([-_a-zA-Z0-9\.]+.flv)$ placeholder/videos/consistent-random.php?file=$1 [L]
</pre><p>And we&#8217;re done! The Video Gallery now thinks it&#8217;s supplying the videos and images as originally intended, not the placeholder ones it&#8217;s actually showing.</p><p><a
href="https://github.com/meloncholy/consistent-random" class="source-link">Download source</a></p> ]]></content:encoded> <wfw:commentRss>http://meloncholy.com/blog/serving-up-random-but-consistent-sample-videos/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
