One-off recordings with Audio Hijack Pro

I’ve written once or twice about using Audio Hijack Pro to record a few weekly BBC radio shows from their internet streams. I use the BBC’s Listen Again feature to schedule the recordings not when the shows are running, but late at night when I’m not using my office computer. The BBC also runs irregular programs of just one or two episodes that I like to record. In the past, I’ve always just recorded these one-off shows when I see that they’re available; there was no obvious way to schedule one-time recordings of these programs because I wouldn’t know the stream URL in advance.

Since the BBC revamped its web site, the stream URLs for upcoming shows are easy to determine. Just go to the page with the show’s description and copy the eight-character string at the end of the URL

The stream URL will be that eight-character string appended to the end of

I’ve set up a dummy recording session in Audio Hijack Pro called “BBC” that has all my usual settings. When I want to record a one-time show, I make a copy of it and change the URL, the schedule, and the tags.

An AppleScript called “Add Show to iTunes Radio Playlist” runs after the recording is made. It’s a simplified version of the AppleScripts I use for the weekly programs; it does everything they do but get a track listing from the show’s web page.

 1:  (* Audio Hijack Script *** (C) Copyright 2003-2007, Rogue Amoeba Software, LLC
 2:  "set shufflable" and "set bookmarkable" lines added on 20070725 
 3:  "add to Radio shows" line added on 20080904 *)
 5:  on process(theArgs)
 7:    --Coerce args to be a list
 8:    if class of theArgs is not list then
 9:      set theArgs to {theArgs}
10:    end if
12:    --Into iTunes ye files shall go
13:    tell application "iTunes"
14:      repeat with theFile in theArgs
15:        set aTrack to (add theFile)
16:        delay 60
17:        set bookmarkable of aTrack to true
18:        set shufflable of aTrack to false
19:        add (get location of aTrack) to playlist "Radio shows"
20:      end repeat
21:    end tell
23:  end process

As you can see from the comments at the top, the script is adapted from an example provided by Rogue Amoeba. My additions are Lines 16-19, which set a couple of track properties and put the track in my “Radio shows” playlist. The delay 60 command provides plenty of time for the track to get into iTunes before we try to set its properties. I’ve found that if I run the script without the delay, Lines 17-19 don’t do anything. The script is saved in the ~/Library/Application Support/Audio Hijack Pro/Recording Scripts folder.

One last script. A couple of years ago I wrote a Python script that printed out the schedule of of weekly shows to be recorded. With the addition of a few lines, it now prints out both the weekly and one-off shows:

                          God's Jukebox: S------ from 12:30 AM to  3:35 AM (185 min)
Monty Python's Wonderful World of Sound: --t---- from 10:30 PM to 11:35 PM  (65 min)
                      Sounds of the 60s: S------ from 12:10 PM to  2:15 PM (125 min)
                      Sounds of the 70s: -M----- from  8:00 PM to 10:05 PM (125 min)
                     Trevor Nelson Soul: ---W--- from  8:00 PM to  9:05 PM  (65 min)

The weekly shows and one-offs are distinguished by the case of the letter indicating the day of the week. Notice that tonight’s Monty Python show uses a lowercase t instead of uppercase. The script is called ahtimers, and it uses the appscript library.

 1:  #!/usr/bin/env python
 3:  from appscript import *
 4:  import datetime
 6:  # Get a list of all the sessions.
 7:  allsessions = app('Audio Hijack Pro').sessions.get()
 9:  # Make a list with the sessions that have scheduled timers.
10:  timersessions = []
11:  for s in allsessions:
12:      for t in s.timers.get():
13:          if t.scheduled():
14:            timersessions.append(s)
15:            break # go to next session after finding a scheduled timer
17:  # Get the length of the longest name of a timersession.
18:  longest = max(len( for s in timersessions)
21:  # Make a 7-character string with the days that the timer runs.
22:  def timerdays(t):
23:    daylist = ['-'] * 7
25:    # Put a lowercase letter in daylist where the next recording is scheduled.
26:    dstring = 'smtwtfs'
27:    wday = (t.next_run_date.get().weekday() + 1) % 7 # convert from Mon=0 to Sun=0
28:    daylist[wday] = dstring[wday]
30:    # Put uppercase letters in daylist where regular recordings are scheduled. This
31:    # may overwrite the lowercase from the section above.
32:    if t.runs_Sunday():
33:      daylist[0] = 'S'
34:    if t.runs_Monday():
35:      daylist[1] = 'M'
36:    if t.runs_Tuesday():
37:      daylist[2] = 'T'
38:    if t.runs_Wednesday():
39:      daylist[3] = 'W'
40:    if t.runs_Thursday():
41:      daylist[4] = 'T'
42:    if t.runs_Friday():
43:      daylist[5] = 'F'
44:    if t.runs_Saturday():
45:      daylist[6] = 'S'
46:    return ''.join(daylist)
49:  # Print the info for all the sessions with enabled timers.
50:  for s in timersessions:
51:    for t in s.timers.get():
52:      if t.scheduled():
53:        dur = t.duration()
54:        durstr = '(%d min)' % (dur/60)
55:        st = t.start_time()
56:        et = st + datetime.timedelta(seconds = dur)
57:        dow = timerdays(t)
58:        ststr = st.strftime("%l:%M %p")
59:        etstr = et.strftime("%l:%M %p")
60:        fmtstr = "%" + str(longest) + "s: %s from %s to %s %s"
61:        print fmtstr % (, dow, ststr, etstr, durstr.rjust(9))

The additional lines are 25-28. Two things are worth noting:

  1. appscript uses Python’s datetime module when returning date information, and datetime takes Monday to be the beginning of the week. Since I consider Sunday the beginning of the week, Line 27 converts the output of weekday() to my convention.
  2. Both one-time and weekly timers will return a value for next_run_date, so the daylist string will have lowercase letters for both types of program after Line 28. Lines 30-46 go on to overwrite the lowercase letters with uppercase letters for the weekly timers.

When I get to the office tomorrow morning, the Monty Python documentary will waiting for me, ready to be synced to my iPod.