Guides
Async video messages and standups
Async video is mostly replay. Create one session per standup, let the team watch on their own time through expiring links, and export only what must be kept.
Most video meetings are watched live by a few people and never again. Async video inverts that: one person records a standup, a walkthrough or an update, and everyone else watches later — at double speed, skipping around, in the gaps between their own work. The product is the replay, and the live call is just how the replay gets made.
Running that on a live-first platform means paying for two products: the call minutes to record, and the recording minutes to keep, plus a processing delay before anyone can watch. On a stream-native platform the same session serves both audiences. The standup is a session while it happens and a recording the moment it ends, with no second integration and no second bill.
This guide builds the pattern: one idempotent session per standup, replay links that expire on their own, composed playback in the browser, and exports only for what must outlive retention.
1. One session per standup, created idempotently
A standup is a scheduled thing, and scheduled things get retried — the cron fires twice, the deploy restarts mid-create, someone double-clicks. Key the creation on the date so retries return the existing session instead of forking the standup in two. The date is the idempotency key; the name keeps the dashboard readable.
# The date is the idempotency key: retrying creates nothing twice.
curl -s -X POST https://api.synento.com/v1/sessions \
-H "Authorization: Bearer $SYNENTO_API_KEY" \
-H "Idempotency-Key: standup-2026-10-21" \
-H "Content-Type: application/json" \
-d '{"name": "Standup 2026-10-21"}' | jq -r .data.id
# After the standup, hand the team a link that expires on its own.
curl -s -X POST https://api.synento.com/v1/sessions/$SESSION_ID/replay-links \
-H "Authorization: Bearer $SYNENTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ttl_minutes": 10080}' | jq -r .data.link2. Record once, casually
The recording experience should feel like leaving a voice note, not joining a meeting. One participant publishes camera and mic for three minutes and leaves; teammates who are around join live, everyone else does not have to. Because there is no recording to start, there is no host, no waiting room ceremony, and no way to forget the step that mattered.
Verify the way you always do: after the standup, read the manifest and confirm each speaker's cam and mic tracks carry a non-null start_ts. A standup nobody can hear is worse than no standup — it pretends information moved.
3. Replay links that expire on their own
Nobody should need an account to watch the standup. createReplayLink mints a URL with its own expiry — a week in the sample above — that plays the session without any credential of yours attached. When the link dies, access dies with it; there is no permission to revoke and no token to rotate.
For viewers inside your product, mint replay tokens instead: same playback, but inside your player, your layout, your access control. Tokens take from_ts and speed, so deep-link the moment that matters and let skimmers watch at double speed.
4. Compose playback, don't ship files
Resist exporting every standup to a file. Files pile up, cost storage, and freeze one layout forever. Compose in the browser from the separated tracks instead: the layout engine resolves a descriptor — grid for the full team, active-speaker for the update, presenter for the walkthrough — deterministically, so previews and exports always agree.
import {
resolveLayout,
type AvailableTrack,
type LayoutDescriptor,
type SessionState,
} from '@synento/player'
// Tracks and playhead state come from the playback API. The layout engine is
// pure and deterministic, so the browser preview and the MP4 export resolve
// the same descriptor identically.
const tracks: AvailableTrack[] = [
{ active: true, kind: 'cam', userId: 'alice' },
{ active: true, kind: 'cam', userId: 'bob' },
]
const state: SessionState = {
activeSpeaker: 'alice',
participants: ['alice', 'bob'],
screenSharers: [],
}
// grid, presenter and active-speaker are the same options the MP4 export takes.
const layout: LayoutDescriptor = { type: 'active-speaker' }
const regions = resolveLayout(layout, tracks, state)
for (const region of regions) {
// { track: { userId, kind }, x, y, width, height, z } in normalized 0..1
// space: position each participant's <canvas> where its region says.
placeTile(region.track.userId, region)
}5. Keep a month, export the exceptions
Standups age fast: last month's are archaeology. Set project retention to cover the useful window — 30 days on Free, up to 90 on Pro — and export an MP4 only for the few worth keeping: the launch walkthrough, the incident review, the decision. Everything else expires on its own, which is also the correct privacy posture for recordings of people's faces.
6. Tell the team when it is ready
A standup nobody watches is a standup that stops happening. Subscribe to recording.ready and post the replay link to the team's channel the moment it fires, with the speaker's name and the duration in the message. People click links that arrive; they do not browse archives. The signed webhooks guide shows the subscription and the signature verification this needs.
Keep the notification dumb and the link smart. The message says who recorded and how long it runs; the link carries the expiry and the deep-link to the moment. If a standup regularly runs past five minutes, that is feedback about the standup, and the durations in your notifications are the data that proves it.
7. Walkthroughs are standups with screen
The same pattern carries demos and walkthroughs: publish screen alongside camera and mic, and the recording keeps all three on one clock. Viewers get the presenter's face in the corner and the screen large — the active-speaker and screen-share layouts exist for exactly this — and reviewers can jump to the moment in question with windowed playback instead of scrubbing a two-hour file.
Verify screen the same way as everything else: the manifest's screen track with a non-null start_ts is proof the reviewer's most important pixels arrived. For walkthroughs worth keeping past retention, export with the screen-share layout so the file leads with the screen, not the faces.
8. Size it from the cadence
Standup economics are delightfully predictable. Five people, three minutes, twenty working days: 300 participant-minutes a month, a fifth of the Free allowance, with storage in the low gigabytes — weeks of standups inside 10 GiB. The pattern scales linearly, so the question is never whether it fits but at what headcount it outgrows Free: multiply people by minutes by days and compare with the plan numbers.
The durations are also management data. Median standup length, who records versus who only watches, which days go long — the session list already holds all of it. When standups bloat, show the trend instead of arguing about it.
Common questions
Can teammates still join live?
Yes. A standup session is a normal session while it happens: anyone with a connection token joins live. The async pattern just means nobody has to.
Can viewers watch at double speed or skip around?
Yes. Replay tokens take speed and from_ts, and windowed playback jumps to any timestamp — the two features async viewing is built from.
Does keeping every standup cost much?
A stored participant-minute at the default 720p takes roughly a few megabytes of camera and mic. Free includes 10 GiB and Pro 100 GiB; the pricing estimator turns your standup cadence into a number.
How does the team know a standup is ready?
Subscribe to session.ended or recording.ready and post the replay link to chat when it fires. The signed webhooks guide shows the verification and fan-out.
More guides
- Record a video call without a recording serverThe live streams are the recording. Create a session, publish from the browser, then replay or export — with no recording pipeline to run or pay for separately.
- Verify media actually arrivedGreen dashboards lie: a participant can join while publishing nothing. The session manifest is the ground truth — a track with a non-null start_ts carried real media.
- Add live video to an AI agent via the MCP serverA remote MCP server at api.synento.com/mcp takes your agent from nothing to a verified integration: projects, keys, sessions, tokens, and manifest proof.
- WebCodecs vs WebRTC for recorded callsIf the call is the product, use WebRTC. If the recording of the call is the product, the WebCodecs relay trade is worth understanding.
- Signed webhooks for recording-ready workflowsWebhooks tell your pipeline when the recording is ready. Verify the HMAC signature on every delivery, then fan out to transcription, review or delivery.
- Restricted keys and short-lived connection tokensTwo credentials, two jobs. A restricted key identifies your server to the API; a connection token admits one participant to one session for about an hour.
Give your agent a video platform it can verify.
Sign up, point your agent at llms.txt, and have a recorded call running before lunch.