Playing streams off the web with FFplay

Compact Radio

Goran Mladenovic

With just a few lines of shell code, you can build a flexible and easily adaptable stream player.

You don't need to start resource-hungry multimedia applications to get a bit of Internet radio. Some command-line programs on Linux can play streams off radio stations. And, a simple shell script is quite enough as a wrapper to manage Internet radio stations easily or to download streams and then play them at your leisure.

The core of the script is a module from the FFmpeg suite [1], which also includes FFplay along with FFmpeg, FFprobe, and FFserver.

FFplay lets you easily enjoy a web station on the command line (Figure 1). For example, the following command is all you need to play the WABC radio station from New York:

$ ffplay http://8703.live.streamtheworld.com:80/WABCAM_SC

With this approach in mind, and with some Bash magic, you can cobble together a slim radio receiver for the shell.

Figure 1: Thanks to the individualized window title, you can easily tell which station FFplay is currently playing.

Collecting URLs

When searching for a good Internet address that can handle most radio stations, you'll sooner or later land at Live-radio [2]. You can find hundreds of radio stations there, in various genres from rock to classical to talk.

As mentioned previously, you simply give the FFplay program a URL as a parameter that it uses to call up a radio station stream. To get this URL, you need to open the PLS files, which are actually meant for the external player, in an editor. You can get these files from Live-radio. Listing 1 shows the sample structure of such a file.

The content in square brackets on the first line makes the contents pretty obvious: It's essentially a playlist. The Title1
is the display name of the radio station; File1
through File2
provide the station's URLs (there can be one or more of these). Because we're talking about a continuous stream, a Length1
of -1
indicates that the player should continuously stream the broadcast. The other entries are largely self-explanatory. Sometimes, the PLS file indicates two or more streams, of which you can choose the one you want.

Homemade

You now need a script for a small web radio that connects the URLs with a name suitable for selectability. This is done via an associative array in Bash. In this case, you start it with a declare
statement along with the -A
option.

The assembled URLs now go into the array. In Listing 2, the array is set up on lines 3 through 7, where the display names act as keys. Thus, all entries are in one place, and you don't need to alter the actual script code later if you add new stations.

Line 9 includes a simple clear
to clear the terminal before you begin the program output with an echo
command. Line 12 has a select
statement that uses the key in the previously defined array to build a menu. Here, the exclamation point before the name of the array variables ensures that shell outputs the key. The [@]
subscript for STATION
receives these values enclosed in quotes so that the select
statement interprets the space characters in the names correctly.

After the do
statement, two variables TITLE
and URL
obtain the correct assigned values. After that, ffplay
plays the station, with the subsequent options controlling width, height, and title of the output window. The &>/dev/null
command at the end ensures that the program messages don't show up on the screen.

Some stations take a few seconds before FFplay picks up the stream, at which point the output window appears and the software plays the station. If the radio program doesn't suit you, simply shut off the station and select another one from the menu. You end the shell script with the Ctrl+C key combination.If you want to extend the list with further stations, simply expand the associative array at the beginning of the script with the corresponding entries. Be careful, however, not to have any same-named keys, in which case the shell will reassign the key to the newer entry.

To install the script system-wide, it would help to keep the station list in a separate file. This would let users each maintain their own list of stations. In principle, the only change to the script would be in lines 3 through 7 by replacing the URL lines with a source <filename>
statement.