Talk sessions
A talk session is a recording window: the speaker starts one before presenting and stops it afterward. It’s a longer-lived concept than a single emoji tap, with its own lifecycle, so it earns its own chapter rather than folding into Emoji journey.
Reactions tapped while a session is active get persisted with a slide number, ready for Analytics later. Reactions tapped with no active session still broadcast live on the spot, they just don’t get saved.
The lifecycle functions
All session logic lives in Speechwave.Talks.
| Function | Idempotent? | What it does |
|---|---|---|
| start_session/1 | Yes | Returns the existing active session if one's already open, otherwise creates a new one labeled "Session N" |
| stop_session/1 | Yes | If ended_at is already set, returns the session unchanged instead of erroring |
| get_active_session/1 | - | Finds the session with ended_at IS NULL |
| list_sessions/1 | - | All sessions for a talk with reaction counts, newest first |
| rename_session/2 | - | Dashboard-only |
| delete_session/1 | - | Dashboard-only |
Idempotency matters here because sessions get started and stopped from a Chrome extension popup, where a flaky connection or an eager double-click shouldn’t create two sessions or throw an error on a second stop.
Controlled from the extension
ReactionChannel exposes start_session and stop_session as channel messages, so the speaker’s extension controls sessions directly, without needing to alt-tab to a browser tab mid-talk.
Before creating a session, the channel checks the talk owner's plan against how many full sessions they've already recorded this month. Free-tier accounts have a participant cap and a monthly session cap; paid tiers don't. See Plans and limits for how that's enforced, and the pricing page for current numbers. If the cap is hit, the channel replies with session_limit_reached and no session is created. The dashboard also reads the count at page load, so a speaker can see their usage before they run into the wall.
A “full” session, for the purposes of that monthly count, is one that runs past a short minimum length, so a session ended almost immediately doesn’t count against the cap.
The channel also tracks each connected participant through SpeechwaveWeb.Presence, which feeds the participant-capacity check on join (see WebSockets), and it subscribes to a per-user disconnect topic, so a server-side logout or an API key regeneration force-disconnects the extension’s channel right away.