Self-hosted Twitch VOD recorder.
Twitch deletes VODs after 14 days. ReplayVOD records the source stream to your disk so they don't disappear. One container, embedded SQLite, runs on a Pi 5.
What it does. Honest list.
Single Go binary, embedded SQLite by default, optional Postgres. Runs in one container next to whatever else is on your stack.
Event-driven, not polling
Subscribes to Twitch EventSub. First segment hits disk within ~4s of stream.online. No 30-second poll loop missing the start.
Source-quality, no re-encode
1080p60 at the original bitrate, written straight to MP4. CPU stays idle; ffmpeg only runs to remux.
Resumable
Network drops, host reboots, ISP blips. Segments resume from the last good point — no half-broken files.
Per-channel rules
Quality, category, tag filters, viewer floor, retention window. Configure once per channel and forget.
Indexed metadata
Title, category, stream ID, viewer count, language, thumbnails — stored next to each MP4 and queryable from the dashboard.
Local or S3
Mount any volume the kernel can see (NAS, ZFS pool, USB) or write to S3-compatible storage. Per-schedule retention rules clean up old recordings.
One container. Your hardware.
One Docker Compose file, one Twitch dev app, one volume mount. Single binary with embedded SQLite. Zero phone-home.
Read full installation docs →- ✓ Docker / Compose macOS, Linux, Windows, NAS, or homelab rack.
- ✓ Reverse-proxy ready Caddy, Nginx, or Traefik. Bring your own TLS.
- ✓ SQLite by default Switch to Postgres when you want it.
Why not just Streamlink/yt-dlp + cron?
Most of us got here from a streamlink twitch.tv/foo best -o vod.mp4 or a yt-dlp one-liner in a cron. ReplayVOD is what falls out the day you find yourself hand-rolling resume logic and a metadata sidecar.
ffmpeg restarts from byte 0 find -mtime +N -delete tail -f the journal and hope Streamlink or yt-dlp in a cron is fine for one channel. ReplayVOD pays off the second you want multiple channels, indexed recordings, or to sleep without checking on it.
Live status, not log diving.
The dashboard shows current channel status, active jobs with progress and ETA, and a tagged event log.
- → stream.status SSE feed Followed channels go live → row turns purple within a second of the EventSub callback.
- → Per-job progress Stage (downloading / remuxing / finalizing), bytes written, MB/s, ETA, percent complete.
- → Tagged event log recorder, eventsub, scheduler, remuxer, storage. Filterable. Persisted to the same DB.
The numbers, at a glance.
Live notifications without touching your router.
Twitch's EventSub needs a public HTTPS endpoint. Getting one at home means port forwarding, a static IP or dynamic DNS, and certificate management. Connect handles all of that through an outbound connection from your machine, so there's nothing to configure, and we never see your video files or your Twitch credentials.
- → Cloudflare Tunnel free, outbound, terminates TLS for you
- → Tailscale Funnel one command if you already run Tailscale
- → Caddy + DuckDNS classic if you have port 80/443 open
- → Reverse SSH to a VPS a $4 box and an autossh unit file
Webhook in. MP4 out.
Twitch tells your recorder when a stream goes live. The recorder fetches the source video and writes a finalized MP4 to your disk. Nothing else sits in the path.
Free to run. $5 if you don't want to fight your router.
Self-host
Your hardware. GPLv3.
- ✓ Unlimited channels & recordings
- ✓ Full feature set, no gates
- ✓ Source code on GitHub
Connect
Self-host the recorder. We handle the annoying parts. $4.17 / month, billed once a year.
- ✓ Public webhook URL. No port forwarding, no domain, no certs.
- ✓ Live notifications via EventSub (works behind CGNAT)
Webhook relay only. Videos stay on your hardware.
The honest questions first.
Is this affiliated with Twitch? +
What is Connect, exactly? +
Do I need a Twitch developer account? +
Where are my videos stored? +
What happens to my recordings if I cancel Connect? +
What if Twitch changes its API? +
How much storage do I need? +
Synology, TrueNAS, Unraid, Raspberry Pi? +
Why not just Streamlink/yt-dlp + cron? +
Plays nice with Jellyfin / Plex / the *arr stack? +
One container. Your hardware. Your archive.
Pull the image, mount a volume, paste your Twitch app credentials. Recording starts the next time a followed channel goes live.