I listen to a lot of podcasts, maybe too many. I often want to share the episodes with friends, but it’s a bit tricky to do that with podcasts. I can send a link, but there are so many places to host podcasts on that it becomes a bit messy. And on the receiving side its also nicer to be able to listen to podcasts in your podcast player, which you can’t do if you get just a single podcast episode linked to you. But if I have a feed with all of my favourite episodes that becomes easy, they just have to subscribe to it. So now I am a podcast curator, you can find the feed here. Just put it into your podcast player like any other RSS link.
How I created this feed đź”—︎
Us non-believers of the recommendation algorithms have to do the curating ourselves. In the rest of this post I want to show how I created this feed.
According to Apple’s requirements, a feed item needs to have an enclosure
in
order to be recognized as a podcast. That needs to have three attributes:
url
: the link to the media filelength
: the length of the media filetype
: the type of the media file
For example:
<enclosure url="https://mcdn.podbean.com/mf/web/tsch9j/GIU_101_Entangled-Life-Part-1.mp3" length="audio/mpeg" type="100716509"> </enclosure>
The trouble I had when implementing this was that while I could get the link to the media file from my podcast app of choice (Antennapod), I couldn’t get the length or the type. I couldn’t get the full description either. To get those you need access to the RSS feed directly. The strategy I ended up with was basically to create a little program that can copy entries from one RSS feed to another.(sidenote: There is a web service for Swedish leftist media that does basically the same thing: https://mediakollen.org/. It is a curated feed of Swedish news, blogs, and podcasts with a leftist bent to them. I sent a pull request to them that does basically the same thing as I describe here, but for a Django service: https://codeberg.org/Konstellationen/mediakollen/pulls/851 )
AntennaPod isn’t that easy to modify for me, even if it is open source, so what I ended up doing was to go back to my trusty old companion Emacs. The amazing thing about Emacs is that it is so easy to modify. If you are familiar with the Unix shell and the power you get from composing together programs, Emacs works in a similar way but for interactive programs. Each emacs-lisp program becomes a library or framework to work with. Elfeed is an Emacs application that is an RSS reader, and for the purposes of this project it is also a framework for working with RSS feeds. This is Emacs, so I have access to all the internal functions.
When you have a podcast episode opened in Elfeed, the metadata is just one or two function calls away. I got the full enclosure tag with this code:
(elfeed-entry-enclosures elfeed-show-entry)
Other post metadata such as the link or the title can be accessed in a similar way. The description is stored in a separate database so you have to do something a little bit different:
(elfeed-deref (elfeed-entry-content elfeed-show-entry))
And metadata for the entire podcast feed can be found like so:
(elfeed-feed-title (elfeed-entry-feed elfeed-show-entry))
The final code can be seen below. When I have listened to a podcast episode (in
AntennaPod) that I want to add to my curated feed, I open up Elfeed, search for
the episode title, and then run the command my/add-podcast-to-curated-list
in
the buffer with the feed item. The emacs-lisp code creates a JSON object that
gets stored in a file, and then the python script reads the file line-by-line,
and then creates an RSS feed file that is put in the directory of my static
website.
Sample JSON of an episode:
{ "title": "General Intellect Unit : 101 - Entangled Life, Part 1", "description": "Curator's description:<br><br>wtf are fungi<br><br><a href=\"https://feed.podbean.com/generalintellectunit.net/feed.xml\">This podcast's feed</a><br><br>Original description: <br><br><p>In which we read \"Entangled Life\" by Merlin Sheldrake.</p>\n\n<p>The more we learn about fungi, the less makes sense without them.[truncated for brevity]", "link": "http://generalintellectunit.net/e/101-entangled-life-part-1/", "enclosure": [ "https://mcdn.podbean.com/mf/web/tsch9j/GIU_101_Entangled-Life-Part-1.mp3", "audio/mpeg", "100716509" ], "date": "2024-04-28" }
The Emacs command:
(defun my/add-podcast-to-curated-list () (interactive) (let* ((filename "~/Documents/blog/curated-podcast-episodes.json") (curator-description (read-from-minibuffer "Add a description as the curator: ")) (s (json-encode (list (cons 'title (format "%s: %s" (elfeed-feed-title (elfeed-entry-feed elfeed-show-entry)) (elfeed-entry-title elfeed-show-entry))) (cons 'description (let ((description (elfeed-deref (elfeed-entry-content elfeed-show-entry))) (feed-url (elfeed-feed-url (elfeed-entry-feed elfeed-show-entry)))) (concat (format "<a href=\"%s\">Subscribe to this podcast</a><br><br>" feed-url) (and (not (string-empty-p curator-description)) (format "<h2>Curator's description</h2><p>%s</p>" curator-description)) (format "<h2>Original description</h2>: %s" description)))) (cons 'link (elfeed-entry-link elfeed-show-entry)) (cons 'enclosure (or (car (elfeed-entry-enclosures elfeed-show-entry)) (user-error "no enclosure!"))) (cons 'date (ts-format "%Y-%m-%d" (ts-now))))))) (with-temp-buffer (insert s "\n") (write-region (point-min) (point-max) filename t)) (shell-command "python3 ~/.local/bin/create-curated-podcast-feed.py")))
I didn’t find a neat way to create an RSS feed with emacs-lisp, so I used the PyRSS2Gen library I found in the package repositories of my Linux distro.
import json import PyRSS2Gen as RSS2 import datetime from urllib.parse import urljoin, urlparse with open("/home/leo/Documents/blog/curated-podcast-episodes.json") as file: f = reversed(list(file)) items = [] for entry in f: feed = json.loads(entry) enclosure_link = feed["enclosure"][0] enclosure_link = urljoin(enclosure_link, urlparse(enclosure_link).path) # 'http://example.com/' items.append( RSS2.RSSItem( title = feed["title"], link = feed["link"], description = feed["description"], enclosure = RSS2.Enclosure(enclosure_link, feed["enclosure"][1], feed["enclosure"][2]) , guid = RSS2.Guid("https://a-blog-with.relevant-information.com/" + feed["link"], False), pubDate = feed["date"]), ) rss = RSS2.RSS2( title = "Relevant Podcasts", link = "localhost", description = "A selection of podcast episodes I like", lastBuildDate = datetime.datetime.now(), items = items) rss.write_xml(open("/home/leo/Documents/blog/static/curated-podcast-episodes.xml", "w"), "utf-8")
Articles from blogs I follow around the net
Pluralistic: Rosemary Kirstein's "The Steerswoman" (04 May 2024)
Today's links Rosemary Kirstein's "The Steerswoman": An unexpected and delightful series that almost disappeared. Hey look at this: Delights to delectate. This day in history: 2004, 2009, 2014, 2023 Upcoming appearances: Where to find me. …
via Pluralistic: Daily links from Cory Doctorow May 4, 2024Machines and tools
It’s International Workers Day, still celebrated as the May Day public holiday here in Queensland, at least when the Labor party is in office. So, it’s a good day for me to set out some tentative thoughts on work and its future. Via Matt McManus, I found …
via Crooked Timber May 1, 2024Gather your gossips
“Tracing the history of the words frequently used to define and degrade women is a necessary step if we are to understand how gender oppression functions and reproduces itself,” writes Silvia Federici, in Witches, Witch-Hunting, and Women. She continues: …
via A Working Library April 30, 2024Riding the waves of grief
Hi friends, I last wrote you here two months ago, a hasty note on my way back to California after my mom’s sudden death. Last month, on the day this newsletter normally goes out, I was instead helping to host my mom’s memorial service. Today I find myself…
via We Can Fix It April 25, 2024“AI” as support systems (for diagnostics)
One of the more reasonable use cases for modern “AI” (statistical pattern matching and generating machines) is to support doctors in diagnostics, especially in the evaluation of complex data sets / documents in order to determine potentially dangerous abn…
via english Archives - Smashing Frames April 22, 2024The Need for Poetry
I am thinking of how we need poetry To express ourselves Practicing feminism By bearing witness to genocide To echo the words of Sarah Ihmoud To get our no’s out. To express, to press out, to speak one’s mind. The … Continue reading →
via feministkilljoys April 11, 2024Generated by openring
-
There is a web service for Swedish leftist media that does basically the same thing: https://mediakollen.org/. It is a curated feed of Swedish news, blogs, and podcasts with a leftist bent to them. I sent a pull request to them that does basically the same thing as I describe here, but for a Django service: https://codeberg.org/Konstellationen/mediakollen/pulls/85 ↩︎