I’m : a programmer, writer, podcaster, geek, and coffee enthusiast.

Podcast App Playback Speeds

One of my most surprisingly difficult decisions for Overcast is how to label the playback speeds.

In the early days of iOS podcast playback, when Apple first implemented multiple speed settings, they used inaccurate labels. Apple’s “2x” setting, for instance, was really 1.5x. Their “1.5x” setting was really 1.25x. And their “½x” setting was really 0.8x.

Podcast apps therefore face a difficult choice: do you use Apple’s old label scheme, which is familiar but inaccurate, or do you use correct labels? Here’s how the top apps chose, as of today:1

Note that nobody has a true speed of less than 0.5 or greater than 2.0, and nobody offers any unique intermediate speeds such as 1.1x or 0.9x that actually sound different from nearby “even” speeds such as 1.0 or 1.25. Why?

As far as I can tell, all popular podcast players on iOS are using Apple’s AVAudioPlayer or AVPlayer rate parameter to offer variable-speed playback. Under the hood, those use the AUiPodTime AudioUnit, which only supports a handful of speeds:

The kTimePitchParam_Rate parameter declared in AudioUnitParameters.h is used to control audio playback rate from 0.5x to 2.0x speed. AudioUnitParameterValue is a Float32 rounded by the unit to whichever of the following is closest: 0.5, 0.66667, 0.8, 1.0, 1.25, 1.5, 2.

If you dive down to very low-level APIs, you can use different audio units to vary playback speed by different amounts, or you can bundle a third-party time-stretching algorithm such as Dirac. But they’re much more complex to use, much harder on the CPU and battery, and mostly designed for music. They’re not nearly as natural-sounding and listenable as Apple’s built-in (but limited) AVAudioPlayer/iPodTime algorithm that’s specifically designed for processing speech.

It’s very unlikely, therefore, that we’ll see an iOS podcast app that can legitimately offer playback faster than 2x. (And that’s probably for the best: true 2x playback is very fast and hard to keep up with.)3

Labeling the speeds in the interface is still a non-obvious choice, though.

If you use the old, inaccurate labels, people accustomed to the old labels will see your speeds as equivalent. You can even offer a “3x” label, representing 2x playback, since Apple’s old scheme topped out at a “2x” label for 1.5x playback.

But this tricks customers and reviewers into thinking you’re offering something you’re really not, and thinking any competitors with speed-accurate labels are inferior.

If you use speed-accurate labels, you’ll look worse in direct comparisons. Customers will request that you add speeds from inaccurately-labeled apps (e.g. “3x”) that you already support. This will haunt you in reviews and feature comparisons forever. But you’ll be technically correct.

Overcast will use speed-accurate labels. I’ll take the heat in reviews.

  1. It’s easy to measure: use a separate stopwatch (either a real one or a second iOS device) and see how much real time passes relative to the podcast’s timestamp. ↩︎

  2. Pocket Casts has a speed slider that advertises 0.1x-granularity over a range of 0.5–3.0. Between 0.5 and 2.0, it appears to be rounding to the nearest kTimePitchParam_Rate value.

    During “3x” playback, the audio is actually playing at 2x speed, but every 1.5 seconds, it skips ahead by 0.5 seconds. Playback completes in the correct amount of time for true “3x”, but you’re missing a third of what’s being said.

    I asked Pocket Casts’ developer about this, and the app isn’t specifically creating this behavior — this is just what happens when you give AVPlayer a rate of greater than 2.0.

    I’ve tried listening to a few shows like this, but I don’t find it useful. I’d rather unsubscribe to a third of my shows or skip a third of the episodes. ↩︎

  3. This is probably why Apple originally used the misleading labels: to give people what’s probably best for them, while giving them the illusion that they’re getting what they think they want. It was a very 2008-era-Apple decision. ↩︎