Renames the repo directory and every podpuddle/PODPUDDLE reference across code, config, and docs to podsteadr/PODSTEADR (package names, Docker Compose project/service/volume names, env var names, UI/RSS strings). Existing Docker volume data (uploaded blobs, mediamtx recordings, the server's sqlite DB and its nostr identity key) was migrated to new podsteadr_-prefixed volumes with matching filenames so it isn't orphaned by the rename.
73 lines
2.5 KiB
Markdown
73 lines
2.5 KiB
Markdown
# podsteadr
|
|
|
|
Self-hosted, nostr-native podcast publishing and livestreaming.
|
|
|
|
- **Log in with nostr** — NIP-07 browser extension (Alby, nos2x, …); the server verifies
|
|
NIP-98 signed requests. No passwords, no email.
|
|
- **Upload an mp4** → it is stored on a [Blossom](https://github.com/hzrd149/blossom) server
|
|
(bundled, or point at any external one) and published in an RSS 2.0 podcast feed with
|
|
Podcasting 2.0 `<podcast:value>` lightning-address payment info.
|
|
- **Go live** — stream from OBS (RTMP) or straight from the browser (WebRTC/WHIP) through
|
|
MediaMTX; viewers watch via HLS and the stream is announced on nostr as a NIP-53
|
|
(kind 30311) live event.
|
|
- **Publish recordings** — live streams are recorded; one click remuxes and publishes a
|
|
recording as a podcast episode.
|
|
|
|
## Quick start
|
|
|
|
```sh
|
|
cp .env.example .env # edit PUBLIC_HOST if not localhost
|
|
docker compose up --build -d
|
|
```
|
|
|
|
Then open http://localhost:8095, log in with a NIP-07 extension, and follow the wizard.
|
|
|
|
## Services / ports
|
|
|
|
| Service | Host port | Purpose |
|
|
|---|---|---|
|
|
| podsteadr | 8095 | Web UI + API + RSS feeds |
|
|
| MediaMTX | 1935 | RTMP ingest (OBS) |
|
|
| MediaMTX | 8889 (+8189/udp) | WebRTC/WHIP ingest (browser) |
|
|
| MediaMTX | 8890 | HLS playback |
|
|
| blossom-server | 8098 | Media blob storage (sha256-addressed) |
|
|
|
|
## Streaming with OBS
|
|
|
|
Create a stream in the UI; it gives you:
|
|
|
|
- Server: `rtmp://<host>:1935/live`
|
|
- Stream key: `<streamId>?key=<secret>`
|
|
|
|
The HLS playback URL (`http://<host>:8890/live/<streamId>/index.m3u8`) is public and never
|
|
contains the secret.
|
|
|
|
## Development
|
|
|
|
```sh
|
|
docker compose up mediamtx blossom -d # backends
|
|
cd server && npm install && npm run dev # API on :8095
|
|
cd frontend && npm install && npm run dev # Vite on :5173, proxies /api + /feeds
|
|
```
|
|
|
|
Tests: `cd server && npm test`.
|
|
|
|
## Data
|
|
|
|
Everything lives in named docker volumes: `podsteadr-data` (SQLite, server nostr key,
|
|
covers), `mediamtx-recordings` (stream recordings, 7-day retention), `blossom-data`
|
|
(media blobs). `docker compose down` keeps them; `down -v` wipes them.
|
|
|
|
## Verification
|
|
|
|
- Unit tests: `cd server && npm test` (35 tests).
|
|
- Against a running stack: `node scripts/e2e.mjs` (14 checks: login, blossom
|
|
upload, feed, stream keys, MediaMTX auth webhook).
|
|
|
|
## Status & internals
|
|
|
|
See **[docs/STATUS.md](docs/STATUS.md)** for the architecture, the full
|
|
verification record, known gotchas (blossom v4 config nesting, no range
|
|
requests, split-horizon blossom URL, MediaMTX polling rationale), and the
|
|
remaining-work list (Archipelago packaging, git remote).
|