The Localhost Podcast CLI Tool

Justin Wernick <>
Curly Tail, Curly Braces
2025-10-19

Abstract

I use a podcast player to queue up media from my computer to watch on my phone. I've recently written a new CLI tool to streamline my process.

Like many of us, I have an archive of various media - audio and video - that I keep on my computer. I also have a smartphone which is a great device to consume this media. As an example, say I have an audiobook. It's nice to archive those files on my computer, for cheap mass storage and easy backups. But it's also nice to listen to the book while I'm in the car or doing chores, when I have my phone with me.

For a few years now, the solution that I've used to this dilemma is what I call my "Localhost Podcast". I've been using a few different programs tied together with a bash script to create an RSS feed for the media, start a local web server, and download it into the podcast player on my phone. It's been working reasonably well, except for a few niggles.

I was in the mood for a small project, and so I've put my whole end to end flow into a single new Rust program. As a bonus, I could fix the rough edges which were annoying me.

I've called my new CLI tool Localhost Podcast, and it's available on Crates.io, with code available on SourceHut.

What does this CLI app do?

I have a directory on my computer which is my podcast directory. What that really means is that it has a localhost-podcast.toml file describing my various feeds.

This is what my config looks like:

host = "192.168.0.12"
port = 9090

["Localhost Books"]
description = "Audiobooks from Justin's collection"
image = "books/thumb.jpg"
dir = "books"
extensions = ["mp3", "ogg"]
out = "books/rss.xml"

["Localhost Cool Tunes"]
description = "Only the coolest tunes from Justin's collection"
image = "music/thumb.png"
dir = "music"
extensions = ["mp3", "ogg"]
out = "music/rss.xml"

["Localhost Movies"]
description = "The best video content from Justin's collection"
image = "movies/thumb.jpg"
dir = "movies"
extensions = ["mp4", "mkv", "avi"]
out = "movies/rss.xml"

When I want to send an audiobook, music album, or movie to my phone, I copy its files to the relevant subdirectory, ./books/, ./music/ or ./movies/.

When I run localhost-podcast in the directory with the config file, it will start by reading localhost-podcast.toml for all of its settings. Then, for each feed described in the config file, it will find any matching files and put them into an rss.xml file.

Some nice high level features in building the feed:

After the RSS files are built, it will immediately start a web server using the same port listed in the config.

All together this means that I only need to drop the media files into right directories and run localhost-podcast, and I'm ready to download the new tracks onto my phone.

Other interesting implementation anecdotes

Audio file metadata is more complicated than I thought

I don't know why, but I had this expectation that reading the metadata from audio files would be relatively simple. After all, audio players, file explorers, and tag management software like Picard all makes it look like this is the same for every audio file. What I hadn't though about is that each audio container stores the metadata in its own way.

I ended up settling on a library called Symphonia for reading the audio metadata. It's primarily a library for reading the actual audio, not just the metadata, but it had the best support I found for many different audio formats in one crate. It also handles having any file thrown at it and it figures out if the file is in any of the formats that it supports.

Theoretically it would be nice to have something similar for video, but audio was my primary concern for now.

Natural ordering and Unicode

Another area that things go deep and I feel I only scratched the surface is in the natural ordering of filenames. I basically only support the ASCII base 10 digits, 0-9. That is perfectly good for my personal use case.

The problem is that those aren't the only numeric characters. If you consider the full set of Unicode, there are many other numeric characters, for example Japanese numerals. Should these be taken into account when doing natural ordering? I don't know! Since I don't personally use those characters, I don't have a good intuition on how they should be sorted, so it's not simple for me to implement myself without a research dive.

SourceHut

I've been eyeing SourceHut for a while as a different forge to host my open source software. I like having my own Git server to control my own data, but it is limited. I don't want to let anyone I don't know have write access to anything on that server, which means that most collaboration tools like issue reports or pull requests can't work. Also, I don't have it linked to any CI server.

Many forges are kind of the same. For the most part, GitLab and Gitea look like they're trying to copy GitHub's homework. I also use Codeberg, which also looks just like GitHub but has the advantage that it is explicitly run as a non-profit to support free software, which avoids some of the sins of GitHub. SourceHut looks like it is trying to do something a bit different.

I'm not going to go into details on SourceHut here, except to say that this Localhost Podcast CLI was partly a way for me to try out SourceHut. Since I did it all alone I didn't use all of their collaboration features, but I was pleasantly surprised by the parts I did interact with.

I'd like to specifically call out their CI server. One fantastic feature that I would love to see from other CI products is that I can drop a potential config file into the web UI to trigger a build without committing. This meant that I could go through the typical trial and error of setting up CI without the many little meaningless Git commits. And when I got the config wrong and the build failed, it had a seamless option to SSH into the failed build environment to troubleshoot.

I'm considering using SourceHut further, while still mirroring any SourceHut repos to my own Git server so that it is included in my backups.

Wrapping up

At this point the localhost-podcast CLI matches my use case. I've called the current version 1.0.0, and I'm actively using it myself and enjoying it.

I hope that it can bring values to others too!


If you'd like to share this article on social media, please use this link: https://www.worthe-it.co.za/blog/2025-10-19-the-localhost-podcast-cli-tool.html

Copy link to clipboard

Tags: blog, music, rust, linux


Support

If you get value from these blog articles, consider supporting me on Patreon. Support via Patreon helps to cover hosting, buying computer stuff, and will allow me to spend more time writing articles and open source software.


Related Articles

The Localhost Podcast

I wanted to manage the process of syncing audiobooks from my computer to my phone better. The solution that worked well for me is to use a podcasting app and an RSS feed. This article explains why this works well for me, and how you can try it out.

How to Train Your Git Server

Have you considered hosting your own Git server? It's easier than you might think. In this article, I go step by step through setting up a simple self-hosted Git server which only supports private repositories for a single person.

Subscribe to my RSS feed.