podcast-go

TUI podcast downloader for Apple Podcasts
Log | Files | Refs | README | LICENSE

README.md (8972B)


      1 <div align="center">
      2 
      3 # Podcast Downloader
      4 ### Vibe coded Go TUI for downloading your favorites
      5 
      6 <img src="./media/demo-podcastdownload.gif" width="800" alt="Demo of the TUI">
      7 
      8 </div>
      9 
     10 ---
     11 
     12 ## Features
     13 
     14 - **Search by name**: Search for any podcast by name using Apple's podcast directory
     15 - **Podcast Index support**: Search podcasts not in Apple's index (e.g., Radio France, European podcasts)
     16 - **Unified search**: Automatically searches both Apple and Podcast Index when credentials are configured (with deduplication)
     17 - **Lookup by ID**: Direct lookup using Apple Podcast ID for faster access
     18 - **Interactive selection**: Browse and select specific episodes to download
     19 - **Preview metadata**: View detailed podcast/episode metadata before downloading
     20 - **Back navigation**: Navigate back through screens without restarting
     21 - **Batch downloads**: Select multiple episodes at once with visual progress tracking
     22 - **ID3 tagging**: Automatically writes ID3v2 tags (title, artist, album, track number)
     23 - **Smart file naming**: Episodes are saved with track numbers for proper ordering
     24 - **Resume support**: Skips already downloaded files
     25 
     26 ## Requirements
     27 
     28 - Go 1.21 or later
     29 - [just](https://github.com/casey/just) (optional, for build commands)
     30 
     31 ## Installation
     32 
     33 ### Clone from GitHub
     34 
     35 ```bash
     36 git clone https://github.com/eloualiche/podcast-go.git
     37 cd podcast-go
     38 ```
     39 
     40 ### Build
     41 
     42 Using just (recommended):
     43 
     44 ```bash
     45 just build
     46 ```
     47 
     48 Or using go directly:
     49 
     50 ```bash
     51 go build -o podcastdownload main.go
     52 ```
     53 
     54 ### Install globally (optional)
     55 
     56 To use `podcastdownload` from anywhere:
     57 
     58 ```bash
     59 go install
     60 ```
     61 
     62 Or move the binary to your PATH:
     63 
     64 ```bash
     65 sudo mv podcastdownload /usr/local/bin/
     66 ```
     67 
     68 ## Usage
     69 
     70 ### Basic Commands
     71 
     72 ```bash
     73 # Search for a podcast by name (uses Apple Podcasts by default)
     74 ./podcastdownload "the daily"
     75 
     76 # Search with multiple words
     77 ./podcastdownload "new york times podcast"
     78 
     79 # Lookup by Apple Podcast ID (faster, no search step)
     80 ./podcastdownload 1200361736
     81 
     82 # Specify output directory
     83 ./podcastdownload -o ~/Music "the daily"
     84 ```
     85 
     86 ### Using Podcast Index
     87 
     88 Some podcasts (like Radio France, many European podcasts) are not indexed by Apple Podcasts. You can search these using [Podcast Index](https://podcastindex.org/), an open podcast directory with over 4 million podcasts.
     89 
     90 #### Setup
     91 
     92 1. Get free API credentials at https://api.podcastindex.org (instant, no approval needed)
     93 
     94 2. Set environment variables (**use single quotes** to preserve special characters):
     95 
     96 ```bash
     97 export PODCASTINDEX_API_KEY='your_api_key'
     98 export PODCASTINDEX_API_SECRET='your_api_secret'
     99 ```
    100 
    101 > **Important**: Many API secrets contain `$` characters. Using double quotes will cause the shell to interpret `$` as a variable, breaking authentication. Always use single quotes.
    102 
    103 3. Add to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.) to persist:
    104 
    105 ```bash
    106 # Podcast Index API credentials
    107 export PODCASTINDEX_API_KEY='your_api_key'
    108 export PODCASTINDEX_API_SECRET='your_api_secret'
    109 ```
    110 
    111 #### Usage
    112 
    113 When Podcast Index credentials are configured, searches automatically query **both** Apple and Podcast Index, with duplicate results removed:
    114 
    115 ```bash
    116 # Unified search (searches both Apple + Podcast Index automatically)
    117 ./podcastdownload "france inter"
    118 
    119 # Force search only Podcast Index
    120 ./podcastdownload --index podcastindex "france inter"
    121 ./podcastdownload --index pi "radio france"  # shorthand
    122 
    123 # Force search only Apple
    124 ./podcastdownload --index apple "the daily"
    125 ```
    126 
    127 ### Finding a Podcast ID
    128 
    129 The podcast ID can be found in any Apple Podcasts URL:
    130 
    131 ```
    132 https://podcasts.apple.com/us/podcast/the-daily/id1200361736
    133                                                   ^^^^^^^^^^
    134                                                   This is the ID
    135 ```
    136 
    137 You can also:
    138 1. Open Apple Podcasts app or website
    139 2. Navigate to the podcast page
    140 3. Copy the URL - the ID is the number after `id`
    141 
    142 ## Workflow
    143 
    144 ### 1. Search or Lookup
    145 
    146 When you run the app with a search query, you'll see matching podcasts:
    147 
    148 ```
    149 Search Results: "the daily"
    150 Found 25 podcasts
    151 
    152 ▸ The Daily                                         The New York Times
    153   The Daily Beans                                   MSW Media
    154   Daily Tech News Show                              Tom Merritt
    155   ...
    156 ```
    157 
    158 ### 2. Select Episodes
    159 
    160 After choosing a podcast, browse the episode list:
    161 
    162 ```
    163 The Daily
    164 by The New York Times • 2847 episodes
    165 
    166 ▸ ○ [  1] The Sunday Read: 'The Kidnapping...       2024-01-07  45:32
    167   ● [  2] A Landmark satisfies Lawsuit...           2024-01-06  28:15
    168   ● [  3] The Fight Over the Future...              2024-01-05  31:42
    169   ...
    170 
    171   Showing 1-20 of 2847  •  2 selected
    172 
    173   ↑/↓ navigate • space select • a toggle all • v preview • enter download • esc/b back • q quit
    174 ```
    175 
    176 ### 3. Download
    177 
    178 Selected episodes are downloaded with a progress bar:
    179 
    180 ```
    181 Downloading...
    182 
    183   Episode 1 of 2
    184   002 - A Landmark Lawsuit.mp3
    185 
    186   ████████████████████░░░░░░░░░░░░░░░░░░░░ 52%
    187 
    188   ✓ 0 completed
    189 ```
    190 
    191 ### 4. Output
    192 
    193 Episodes are saved to a folder named after the podcast:
    194 
    195 ```
    196 The Daily/
    197 ├── 001 - The Sunday Read.mp3
    198 ├── 002 - A Landmark Lawsuit.mp3
    199 └── 003 - The Fight Over the Future.mp3
    200 ```
    201 
    202 Each file includes ID3 tags:
    203 - **Title**: Episode title
    204 - **Artist**: Podcast creator/network
    205 - **Album**: Podcast name
    206 - **Track**: Episode number
    207 
    208 ## Keyboard Controls
    209 
    210 ### Search Results Screen
    211 
    212 | Key | Action |
    213 |-----|--------|
    214 | `↑` / `k` | Move cursor up |
    215 | `↓` / `j` | Move cursor down |
    216 | `Enter` | Select podcast |
    217 | `v` | Preview podcast metadata |
    218 | `q` / `Ctrl+C` | Quit |
    219 
    220 ### Episode Selection Screen
    221 
    222 | Key | Action |
    223 |-----|--------|
    224 | `↑` / `k` | Move cursor up |
    225 | `↓` / `j` | Move cursor down |
    226 | `Space` / `x` | Toggle episode selection |
    227 | `a` | Select/deselect all episodes |
    228 | `PgUp` | Page up |
    229 | `PgDn` | Page down |
    230 | `v` | Preview episode metadata |
    231 | `Enter` | Start downloading selected |
    232 | `Esc` / `b` | Go back to search results |
    233 | `q` / `Ctrl+C` | Quit |
    234 
    235 ### Download Screen
    236 
    237 | Key | Action |
    238 |-----|--------|
    239 | `Esc` / `b` | Go back to episode selection |
    240 | `q` / `Ctrl+C` | Cancel and quit |
    241 
    242 ### Complete/Error Screen
    243 
    244 | Key | Action |
    245 |-----|--------|
    246 | `Enter` / `q` | Exit |
    247 | `Ctrl+C` | Exit |
    248 
    249 ## Build Commands
    250 
    251 Using `just`:
    252 
    253 ```bash
    254 just build    # Build the binary
    255 just run      # Build and run
    256 just clean    # Remove build artifacts
    257 ```
    258 
    259 Or use `just --list` to see all available commands.
    260 
    261 ## Dependencies
    262 
    263 | Library | Purpose |
    264 |---------|---------|
    265 | [Bubble Tea](https://github.com/charmbracelet/bubbletea) | TUI framework |
    266 | [Lip Gloss](https://github.com/charmbracelet/lipgloss) | Terminal styling |
    267 | [Bubbles](https://github.com/charmbracelet/bubbles) | Progress bar, spinner components |
    268 | [gofeed](https://github.com/mmcdole/gofeed) | RSS/Atom feed parsing |
    269 | [id3v2](https://github.com/bogem/id3v2) | MP3 ID3 tag writing |
    270 
    271 ## How It Works
    272 
    273 1. **Search/Lookup**: Uses Apple's iTunes Search API or Podcast Index API to find podcasts
    274 2. **Feed Parsing**: Fetches and parses the podcast's RSS feed using gofeed
    275 3. **Download**: Downloads MP3 files from the enclosure URLs in the RSS feed
    276 4. **Tagging**: Writes ID3v2 tags to each downloaded file
    277 
    278 ### Search Providers
    279 
    280 | Provider | Flag | Coverage | Notes |
    281 |----------|------|----------|-------|
    282 | Apple Podcasts | `--index apple` (default) | Large, US-centric | No API key needed |
    283 | Podcast Index | `--index podcastindex` | 4M+ podcasts, open | Free API key required |
    284 
    285 ## Troubleshooting
    286 
    287 ### "No RSS feed URL found"
    288 
    289 Some podcasts don't expose their RSS feed publicly. This app requires access to the RSS feed to download episodes.
    290 
    291 ### "No downloadable episodes found"
    292 
    293 The podcast's RSS feed doesn't contain audio enclosures, or uses a format not recognized as audio.
    294 
    295 ### Download seems stuck
    296 
    297 Some podcast CDNs may be slow. The progress bar updates every 1% of download progress. For large files on slow connections, this may take a moment.
    298 
    299 ### Podcast Index: "Authorization header doesn't match"
    300 
    301 This usually means your API secret contains special characters that got mangled. Check:
    302 
    303 1. **Use single quotes** when setting environment variables:
    304    ```bash
    305    # Wrong - $ gets interpreted as variable
    306    export PODCASTINDEX_API_SECRET="secret$with$dollars"
    307 
    308    # Correct - single quotes preserve literal value
    309    export PODCASTINDEX_API_SECRET='secret$with$dollars'
    310    ```
    311 
    312 2. **Verify your credentials** are set correctly:
    313    ```bash
    314    echo "Key: [$PODCASTINDEX_API_KEY]"
    315    echo "Secret: [$PODCASTINDEX_API_SECRET]"
    316    ```
    317 
    318 3. **Check for trailing whitespace** - copy credentials carefully from the email.
    319 
    320 ### Podcast Index: "API credentials not set"
    321 
    322 Set the environment variables before running:
    323 ```bash
    324 export PODCASTINDEX_API_KEY='your_key'
    325 export PODCASTINDEX_API_SECRET='your_secret'
    326 ```
    327 
    328 Get free credentials at https://api.podcastindex.org
    329 
    330 ## License
    331 
    332 MIT