Hacking WordPress for Podcasting different Media[20051014]
Two days ago, Apple annouced an iPod that can playback video. This means the next big thing is going to be video podcasting.
My writerly side has been wanting to do something like that for awhile now. How cool would it be to have your own video show? I keep trying to come up with an interesting story that can be shot on budget and broken up into a few segments. Business model would be simple. Each episode would be 5 to 10 minutes long, stands alone fairly well, but the completed season can form a single movie. Something along the lines of Star Wars: Clone Wars.
But I am too stupid/lazy as a writer.
BUT I am a bit less lazy as a hacker, so I started fiddling around with the WordPress engine to get it to support this functionality. Or more accurately support this functionality for my larger needs.
You see, WordPress is already enthusiastic about supporting podcasting. The functionality is automatic: when you make a post, it takes any links to media files and generates enclosures (what podcast listeners look for to find the media). Great for anybody to quickly start his own podcast.
The problem is that it is TOO enthusiastic about it. What do I mean?
Well look at Rocketboom. Daily 3 minute net news show. They’re main format is in MPEG-4 Quicktime, but you have links from the first post to get the show in Windows Media format, download it via Torrent, or even have it on you PSP or mobile cell phone. And they have a separate feed for EACH of these formats. Any podcast listener of one feed WON’T be forced to download the show in all the other formats.
By being too enthusiastic in creating media enclosures, WordPress will force some listeners to download ALL versions of anything I post. This is bad for them (content in formats they aren’t interested in seeing taking up space) and bad for me (hurts my bandwidth). Plus, if I use a feed service like FeedBurner to track and publicize my cast, I can’t get separate stats for each media format (plus in experimenting I found FeedBurner gets confused if there are multiple enclosures).
Now, there is a manual work around this. As the podcasting documentation for WordPress notes, you can generate a feed just for a specific category on your WordPress site. So you can post the Quicktime version of your show under one category, the Windows Media version of the show in another, and have separate feeds for each. But that means your work will only increase as you add more formats (a different post for each format), and all those posts will show up your homepage even though they are all exactly the same except for the category they are under!
So what is a WordPress user suppose to do?
[Rudy-San draws his coding katana].
Warning, the next little bit is goinf to be technical mumbo jumbo not interested to most of you. Scroll down until you see NEXT to skip it if you are not interested.
Using my newly learned PHP skillz I hacked WordPress to do two things:
- Generate enclosures only for media of a specific format. The format to enclose is given by the request parameter ‘media’ in the podcast URL. For example the podcast URL for just QuickTime media posted to a WordPress site would be:
http://mywordpressblog.com/?feed=rss2&media=video/quicktimePretty cool eh? I can then take this link and use it with FeedBurner to get stas JUST for Quicktime viewers.
Enclosures in the RSS feed that is the podcast are generated by the rss_enclosure() method, found in the feed-functions.php. I edited this function to support my new functionality. My changes are in RED, and note any line that ends with
/means it continues on the next line (no newline character!):function rss_enclosure() { global $id, $post; if (!empty($post->post_password) && ($_COOKIE['wp-postpass_'.COOKIEHASH] / != $post->post_password)) return; $custom_fields = get_post_custom(); if( is_array( $custom_fields ) ) { while( list( $key, $val ) = each( $custom_fields ) ) { if( $key == 'enclosure' ) { if (is_array($val)) { foreach($val as $enc) { $enclosure = split( "n", $enc ); if (!empty($_REQUEST[’media’])) { if ($_REQUEST[’media’] / != trim($enclosure[ 2 ])) { continue; } } print “<enclosure url=’” .trim( htmlspecialchars($enclosure[ 0 ]) ) .”‘ length=’” .trim( $enclosure[ 1 ] ) .”‘ type=’” .trim( $enclosure[ 2 ] ) .”‘/>n”; } } } } } } - Support other media formats. Currently, WordPress only will enclose media types that are defined as audio or video. But what about torrents? Their format name is application/x-bittorrent. Most podcast listeners support it, but by default WordPress
The logic that determines the media to enclose is defined the function do_enclose() in the functions.php file. I added an array of String values of specific formats you may also want to podcast (in my example, only torrents). Again, here is the function, with my changes in RED.
function do_enclose( $content, $post_ID ) { global $wp_version, $wpdb; include_once (ABSPATH . WPINC . '/class-IXR.php'); $log = debug_fopen(ABSPATH . '/enclosures.log', 'a'); $post_links = array(); debug_fwrite($log, 'BEGIN '.date('YmdHis', time())."n"); $pung = get_enclosed( $post_ID ); $ltrs = 'w'; $gunk = '/#~:.?+=&%@!-'; $punc = '.:?-'; $any = $ltrs . $gunk . $punc; preg_match_all( / "{b http : [$any] +? (?= [$punc] * [^$any] | $)}x", / $content, $post_links_temp); debug_fwrite($log, 'Post contents:'); debug_fwrite($log, $content."n"); foreach($post_links_temp[0] as $link_test) : if ( !in_array($link_test, $pung) ) : // If we haven't pung it already $test = parse_url($link_test); if (isset($test['query'])) $post_links[] = $link_test; elseif(($test['path'] != '/') && ($test['path'] != '')) $post_links[] = $link_test; endif; endforeach; foreach ($post_links as $url) : if ( $url != '' && !$wpdb->get_var( "SELECT post_id FROM / $wpdb->postmeta WHERE / post_id = '$post_ID' AND / meta_key = 'enclosure' AND / meta_value LIKE ('$url%')") ) { if ( $headers = wp_get_http_headers( $url) ) { $len = (int) $headers['content-length']; $type = addslashes( $headers['content-type'] ); $allowed_types = array( 'video', 'audio' ); $allowed_specific_types = array(’application/x-bittorrent’); if( in_array( substr( $type, 0, strpos( $type, “/” ) ), $allowed_types ) || in_array( $type, $allowed_specific_types ) ) { $meta_value = “$urln$lenn$typen”; $wpdb->query( “INSERT INTO `$wpdb->postmeta` / ( `post_id` , `meta_key` , `meta_value` ) / VALUES ( ‘$post_ID’, ‘enclosure’ , ‘$meta_value’)” ); } } } endforeach; }
There you go; a couple of cool new functionality added, with minimal code fuss.
WordPress is open-source, so I want to give this code back to the community. Feel free to use it or modify it as you want to.
I think for the next little bit I may post up some of my old videos, and my brother’s (if he is okay with it) using this tech. Download iTunes or any other podcasting software to listen to them, or find them here on this site.
And then maybe when I run out of videos, I will have an actual show ready …
BTW the guys at Freevlog do a terrific job documenting how you can have your own video blog/podcast for free. You read that right; free as beer
.
