Record a podcast of your favourite radio show using PHP & Shell

Following my previous post on mixing PHP and shell scripting under Linux, I have a more practical and complete example coming up in this post, which will come after a little introduction, so bear with me!

If you are like me, you probably have run into situations where your favourite radio show(s) is/are not available as a podcast, either because the station doesn’t do podcasting or because they don’t podcast that particular show. That got me thinking, couldn’t I just make my own podcast of the show out of their stream? Of course that is quite possible, but requires a bit of work.

Before we go further, I must give you a bit of a legal disclaimer! Please do not use any methods described or provided here to do anything illegal. Sometimes the shows are not available as podcasts for legal reasons beyond the station’s control, some other times the stations use streaming technologies where the fine print in the terms of service make it illegal for you to tune in using “alternative” methods like the ones described here. Last but not least, keep recorded material for personal use and DO NOT redistribute, whether for profit or not.

Back on track, I imagined a solution that can tune in at the correct time, record my show that runs for X minutes then convert into MP3 for easy playback on my phone or mp3 player. Luckily, Linux has a plethora of tools and commands that can achieve that exact goal, it is just a matter of piecing it together!

In short, here’s how I got it to work:

  1. Cron job-schedules will be used to fire off the recording at the right time. Check wikipedia’s excellent cron page for more information on this tool and how you can use it.
  2. mplayer will perform the tuning in and decoding of the stream into raw wave format. Mplayer can be used both as a command line and as a GUI tool, it supports pretty much every format out there.
  3. Last but not least, lame will do the conversion into mp3.

Then I used PHP to piece everything together, here’s a quick breakdown of events:

  1. PHP script gets invoked by a cron or manually from the command line. It takes three arguments: URL to stream, length in minutes and file name/path to use for the mp3 file.
  2. PHP invokes mplayer using a pipe so it runs in the background, sleeps for the length of the show.
  3. PHP wakes up, terminates that specific instance of mplayer (i.e. you can safely run multiple instance of this script simultaneously).
  4. Lame is invoked to convert into mp3 and the temporary raw wave file is removed.

Of course there are many things your imaginative mind could tinker with to spice things up, such as:

  • With a bit of work, you could use this on a video stream, too!
  • You could swap lame for mencoder or ffmpeg, which convert audio and/or video from pretty much anything to pretty much everything! You could create the output files using AAC for example.
  • If you still prefer mp3 like me, there are many many settings and flags you can pass to lame to adjust quality settings and encoding options.

Here is a link to my “podcaster” script, it is free to download and use for personal use (keeping in mind the disclaimer above). I am sure there many improvements that can be made to it. If you make any, then kindly email me or post in the comments section below.

Last but not least, for the more novice readers, who are wondering how to get the direct URL to the stream. Here are some tips:

  • If your station’s stream usually comes up in a dedicated window, look at the HTML code (Ctrl+U in Firefox) and in most cases you’ll find a reference to stream URL, or the playlist containing that URL we’re after.
  • If you are working with a playlist that you found through the first tip or your station provides a direct link to the playlist, you’ll find most playlist formats (e.g. m3u, asx) to be text or XML-based. You could use something like wget to download the file, then a text editor like vim to read the content.
  • Some playlists are nested (if supported by the format), where one playlist contains a link to another playlist, which in turn contains the actual link to the stream URL.
  • The stream URL is most likely using one of three protocols: HTTP, MMS, RTSP.

I hope you’ve found this helpful!

Mixing PHP and shell scripting (under Linux)

PHP plays very well with command line. On one hand, you can execute PHP from the command line using the, wait for it, “php” command! On the other hand, inside PHP you have many options for executing commands on the command line, which is the one I want to focus on here.

Before you proceed reading this article and get all excited about PHP and command line having babies together, I must warn you that I find most hosting companies don’t allow their users to access command line from within PHP. So, you might want to check on that first!

First example is the one I use the most. At work I maintain close to a hundred deployments of this one product, so when I need to run quick deployments, I can do this:
$sites = explode("\n",trim(`ls -1d /var/www/*`));

Note the tick character (`) in PHP means execute this string in shell. Also one thing people always confuse are the flags I am passing to the command “ls” (list, aka dir), the first is a digit one (1) and it means one column containing names only, the second, means return directories only.

At the end of the day, this will give me an array of all folders under /var/www, which I loop through in PHP, connect to the database to do some work and/or perform tasks in the file system. You could get fancier using a more advanced command to look up your targets such as find.

The second example is very useful for people who work with audio and/or video files. You can take advantage of awesome Linux commands such as ffmpeg and mencoder to allow your users to upload pretty much any kind of audio/video and convert it with ease into the format you prefer for playback and storage. The best part is, you can run the conversion command in the background so it doesn’t hold the page from loading (asynchronously, like AJAX). Here’s one example:

$cmd = 'nice lame -q 9 --resample 44100 '.escapeshellarg($source_file).' '.escapeshellarg($dest_file)." &\r\n";
$handle = popen($cmd,'r');

Nice is a prefixing command (like sudo), which basically sets a lower priority on this process not to lock up your server. Lame is the popular mp3 encoder. escapeshellarg() escpaes arguments for the command line interface (important!). The ampersand (&) puts this as a background process. Note that you could not use exec(), which is why I am opening up a pipe using popen(). Last but not least, the carriage return and new line characters (\r and \n) simulate hitting enter after a command when you are typing in a shell session, which is what the pipe does.

I will stop here since this post is getting too long. I should mention that the only limitation I know of with working with shell in PHP, is that you can never work with interactive prompts (e.g. being asked for a password when executing a command like ssh, scp, rsync or even svn update). However, there are ways to work around most of those scenarios (certificates, authentication caching…etc), which may not be best practices, but are available none the less if you really need to.

On the other hand, if you are building a PHP CLI solution (e.g. interactive installer the command line), you can make use of interactive prompts using existing shell libraries for PHP.