podcast_helper.api module

Podcast Helper — FastAPI HTTP surface.

Exposes every public function in podcast_helper as an HTTP endpoint so podcast-helper can be dropped behind any reverse proxy and consumed by other services. Kept intentionally minimal:

  • /feed and /latest: JSON responses over an RSS / Atom URL.

  • /probe: JSON classification of any URL (file / direct / rss / yt-dlp-<extractor>) — invaluable for operators debugging podcast ingest.

  • /stream: chunked StreamingResponse of raw f32le PCM bytes for any audio-bearing URL. Downstream ASR services can pipe the response directly.

  • /record: server-side archive to a compressed file, returned via FileResponse; the temp file is cleaned up by a BackgroundTask once the response has been fully streamed to the client.

  • /gui (and / which redirects to it): a self-contained single-page episode browser (Tailwind CDN + vanilla JS) that drives the very same /feed / /probe / /record endpoints — no extra server logic.

Install the extra to get the runtime dependencies:

pip install 'podcast-helper[api]'

Then run the app with any ASGI server:

uvicorn podcast_helper.api:app --host 0.0.0.0 --port 8000

Usage Example

>>> # Start the server:
>>> #   uvicorn podcast_helper.api:app --reload
>>> # List a feed's episodes:
>>> #   curl 'http://localhost:8000/feed?url=https://feeds.npr.org/510289/podcast.xml'
>>> # Get the latest episode:
>>> #   curl 'http://localhost:8000/latest?url=https://feeds.npr.org/510289/podcast.xml'
>>> # Archive a URL to disk (server-side ffmpeg):
>>> #   curl -o ep.mp3 -X POST -F 'url=…' -F 'output_format=mp3' \
>>> #        http://localhost:8000/record
>>> # Full OpenAPI docs at http://localhost:8000/docs

Author

Warith Harchaoui, Ph.D. — https://linkedin.com/in/warith-harchaoui/

podcast_helper.api.get_feed(url=fastapi.Query, max_episodes=fastapi.Query)

Return the feed’s episodes as JSON (most-recent first).

Parameters:
  • url (str)

  • max_episodes (int | None)

Return type:

fastapi.responses.JSONResponse

podcast_helper.api.get_latest(url=fastapi.Query)

Return the latest episode (with a non-empty audio enclosure) as JSON.

Parameters:

url (str)

Return type:

fastapi.responses.JSONResponse

podcast_helper.api.gui()

Serve the self-contained single-page ‘episode browser’ GUI.

The page (defined in podcast_helper.gui) is a build-step-free HTML + Tailwind-CDN + vanilla-JS client that calls the very same /feed / /probe / /record endpoints defined below. It adds no server-side logic — it is purely a friendlier front door to the API.

Returns:

The complete HTML document (status 200, text/html).

Return type:

HTMLResponse

podcast_helper.api.health()

Simple liveness probe — no dependency check, just proves the app is up.

Return type:

dict

podcast_helper.api.probe(url=fastapi.Query, show_url=fastapi.Query)

Report how podcast-helper classified a URL (source_kind, is_live, headers).

Parameters:
Return type:

fastapi.responses.JSONResponse

async podcast_helper.api.record(background, url=fastapi.Form, output_format=fastapi.Form, sample_rate=fastapi.Form, mono=fastapi.Form, frame_ms=fastapi.Form, speed=fastapi.Form)

Archive any audio-bearing URL to a compressed file server-side, then return the file as the response body.

Parameters:
  • background (fastapi.BackgroundTasks)

  • url (str)

  • output_format (str)

  • sample_rate (int)

  • mono (bool)

  • frame_ms (int)

  • speed (float)

Return type:

fastapi.responses.FileResponse

podcast_helper.api.root()

Redirect the bare root to the GUI so opening the server just works.

Return type:

fastapi.responses.RedirectResponse

podcast_helper.api.stream(url=fastapi.Form, sample_rate=fastapi.Form, mono=fastapi.Form, frame_ms=fastapi.Form, speed=fastapi.Form)

Stream raw f32le PCM for any audio-bearing URL.

Clients: pipe the response body into ffplay / a VAD / an ASR frontend. The Content-Type is application/octet-stream; sample rate / channels / format are conveyed via headers below.

Parameters:
Return type:

fastapi.responses.StreamingResponse