How, in 2025, to put music and podcasts on an MP3 player

Say someone doesn’t have a phone, but wishes to listen to music and podcasts. You may remember there used to be these devices on which you could put music files, and then listen to them with headphones. (If you are older, you may remember devices into which you could insert physical objects containing the music.) And you couldn’t do other things that you didn’t actually want to do on them. Mad, I know.

They have fallen out of fashion somewhat, but they still exist, and Currys sell a perfectly nice serviceable one called the Majority MP3 Player, pictured here.

So if you have one of those devices, the question is then how do we get the things we want to listen to on to it? It pops up as an external drive, so if you already have some MP3 files from somewhere, you can drag and drop them on to the device and they appear and play fine. If you have a CD (remember them?), you could rip it to MP3 files and add them.

But what if you want to listen to archive episodes of a podcast, or only have the songs you want via a Spotify account?

Podcasts

Podcasts are, at their core, an RSS feed of MP3 files (well, usually; keep reading). They try and hide the URL of the RSS feed behind all their apps and websites, but you can find other websites that will dig it out for you, or you can get it from e.g. the HTML source of an Apple Music podcast page. For example, Greeking Out by National Geographic:
curl -s https://podcasts.apple.com/us/podcast/greeking-out-from-national-geographic-kids/id1483233279
  | awk -F '"feedUrl"' '{if ($2)print $2}'
...tells us its RSS feed is at https://feeds.megaphone.fm/ESP4751925729.

[Update: Smylers recommends GPodder which can download all episodes of a podcast given its feed, sync with an external MP3 player, add metadata, and more.]

With that, though, I did not want to go through and manually click a hundred of so MP3 links. So I wrote a small script to do that for me:

import requests
import xml.etree.ElementTree as ET
import re

def sanitize(filename):
    return re.sub(r'[\\/*?:"<>|]', "", filename)

def download_feed(url):
    response = requests.get(url)
    response.raise_for_status()
    root = ET.fromstring(response.content)

    # Extract and print season, episode, title, and MP3 URL
    for item in root.findall('.//item'):
        title = item.find('title').text
        mp3 = item.find('enclosure').get('url')
        season = item.find('{http://www.itunes.com/dtds/podcast-1.0.dtd}season')
        episode = item.find('{http://www.itunes.com/dtds/podcast-1.0.dtd}episode')
        if episode is None:
            continue
        season = season.text
        episode = episode.text
        title = sanitize(title)
        download_mp3(mp3, f'{title}.mp3')

def download_mp3(url, filename):
    response = requests.get(url, stream=True)
    response.raise_for_status()
    with open(filename, 'wb') as file:
        for chunk in response.iter_content(chunk_size=8192):
            file.write(chunk)
    print(f"Downloaded {filename}")

feed_url = 'https://feeds.megaphone.fm/ESP4751925729'
download_feed(feed_url)

It turns out the MP3s have no order metadata, so the player sorts alphabetically, and the episodes appear as E1, E10, E2, and so on. so you could do some post processing here to tidy that up (eg with mutagen). Or not bother in our case.

That wasn’t the end of the story, sadly; Greeking Out has moved to YouTube for series 11 (I am too tired to understand this). But that is actually easier for us, because people have wanted to download things off of YouTube for ever, and written nice programs where you give them the playlist ID and it does its magic:

 yt-dlp -x PLQlnTldJs0ZR17ATC92ecGmespxuX7cxI --audio-format mp3
(This is not actually what I ran, because I forgot it had an MP3 output mode, and originally downloaded them all as something else and then converted.)

Songs

I went for an easy option here, and bought the songs being requested on Apple Music, which downloads them to a Music folder on my computer in M4A format. Converting those to MP3 was then straightforward (I think you could even do this one at a time in Apple Music but that sounds dull), something like this:

for i in ~/Music/Music/Media.localized/Music/SIX/Six_\ The\ Musical\ \(Studio\ Cast\ Recording\)/*;
    ffmpeg -i "$i" ./(path change-extension mp3 (path basename $i));
end
...which created a folder of MP3 files that could then be copied across to the player.

This then gives us a device, full of audio, with long battery life, works anywhere, and nothing else to be distracted by when on a 4.5 hour train journey from Glasgow to Glenfinnan. It’s a shame that it’s this complicated, especially to get the archive of a podcast, as that feels like something people might well want to do. But I guess the (not incorrect) assumption is that almost everyone will have a phone device that they can do this on, and this is all a bit pointless. But this is my way to put off all the issues of having a phone to at least a little bit further in the future.