Inspiration
Every stream has moments that light chat up — a clutch play, a fail, a plot twist — but by the time anyone notices, the moment is already gone, buried in a VOD nobody has time to scrub through. Every "auto-clipper" I found works after the fact on a recording. I wanted something that catches the moment while it's happening, so a highlight is ready to share almost as soon as it occurs.
What it does
Paste in a live Twitch channel name and StreamPulse connects anonymously to its chat over IRC — no API key or OAuth needed. It tracks chat message velocity in a rolling window and flags statistically significant spikes using an adaptive z-score, tuned to work whether a channel has 3 viewers or 20,000. When a spike fires, it scans the burst of messages for emotes and keywords to classify the reaction — Hype 🔥, Funny 😂, Shocked 😱, Confused ❓, Sad/RIP 💀, or generic Reaction ⚡. Meanwhile, it continuously buffers the live video stream in the background, so when a moment is detected it can instantly cut a 30-second clip (15s before/after) and save it as a downloadable .mp4 — typically ready within ~20 seconds. Every moment, its chat context, reaction tag, and clip are archived per channel and browsable later, with CSV export for handing timestamps to an editor.
How I built it
The backend is a FastAPI app that orchestrates everything, with a WebSocket pushing live updates to a dashboard showing a chat-velocity chart and moment feed. A custom asyncio-based IRC client connects to Twitch chat with zero external dependencies. A rolling-baseline z-score detector watches chat rate for anomalies, and a keyword/emote pattern matcher classifies the mood of each spike. In parallel, a video buffer module runs ffmpeg in the background to keep a rolling ~3-minute recording of the live HLS stream, ready to extract clips from. SQLite handles persistence for moments, reactions, and clip paths. I bundled ffmpeg via imageio-ffmpeg so there's no system-level install required — just pip install and go.
Challenges I ran into
Getting clip extraction fast enough to feel "live" was the biggest one — an early version re-encoded clips with libx264, which took 35+ seconds per clip and occasionally failed under load. Switching to stream-copy (no re-encoding) made extraction near-instant and far more reliable. I also had to rework spike detection: the first version used a fixed threshold that effectively required ~4 simultaneous chatters to ever trigger, which silently excluded small streamers entirely. Making the threshold adaptive, and testing it against both large and tiny synthetic and real channels, fixed that.
Accomplishments that I'm proud of
Getting the full pipeline — chat detection, classification, buffering, and clipping — to work end-to-end in real time, with clips ready roughly 20 seconds after the moment happens. I'm also proud that it works honestly at small scale: a 3-viewer stream gets the same real detection as a 20,000-viewer one, not a diluted version.
What I learned
A lot about the tradeoffs in live video pipelines — how re-encoding cost compounds under load, and how "simpler and dumber" (stream-copy, keyword matching instead of an LLM) can beat a fancier approach on speed, cost, and transparency. I also learned how much detection logic needs to be validated against edge cases like tiny channels, not just the happy path of a big, active stream.
Log in or sign up for Devpost to join the conversation.