Skip to content
Brad Johnson, home
All projectsSoftware / 12 of 20

Gleeman

An iPhone podcast player that evens out a quiet co-host next to a loud host, on the phone.

Category
Software
Updated
2026-10-24
Status
v0.1.0, on my phone
Built with
Swift, SwiftUI, AVAudioEngine, SwiftData, TypeScript, Node.js, SQLite

Gleeman downloads each episode itself, from the show’s own feed, so the show still gets its download count and its inserted ads, and the leveled audio never leaves the phone.

Leveling happens in two parts. A first pass over the file measures loudness every 100 ms and plans a gain curve. Each moment’s gain comes from the speech in the two seconds around it, pauses are left out so the gain holds through them, and the curve leans toward turning down when the speaker changes. The curve is smoothed over 0.3 seconds, capped at 12 dB either way, aimed at -16 LUFS and kept under a -1 dBTP peak. It’s about 280 KB for a two-hour episode, stored next to the original and applied live through AVAudioEngine with a true-peak limiter. Nothing is re-encoded.

On one two-hour episode, the loudness range went from 11.9 LU to 4.4 LU. The same episode had 1,145 pauses longer than 0.6 seconds, and trimming each to 0.4 seconds took 16 minutes 43 seconds off. Trimming happens after the limiter, and playback positions are kept in the original file’s time.

A small Node server on the homelab polls my feeds every 10 minutes and proxies Podcast Index search. Without it, the app refreshes feeds itself and searches iTunes. There’s also a Mac version that shares the leveling code but keeps its own library.

In the Wheel of Time, a gleeman is a traveling storyteller.

Next project, 13dreamwalker