Record meetings in the browser, transcribe them locally, and save the audio + transcript to your archive.
Meetings are captured and transcribed entirely in your browser. Relink records your microphone (and optionally your system / tab audio), transcribes it on-device while you talk, and saves both the audio recording and a timestamped transcript as a regular item in your archive. The same AI pipeline that powers bookmarks then generates a summary, tags, key sections, and a detected language — so a meeting becomes searchable, chat-able knowledge just like any saved link.
Because transcription happens locally (no audio is streamed to a third-party speech service), the recording itself only leaves your device when it is uploaded to your own private storage at the end.
Start a recording from the Omnibar / record action. Before recording, you can set a title, pick the spoken language (or Auto-detect), and choose whether to include system audio (useful for capturing the other side of a video call). The first recording downloads the on-device speech model; subsequent recordings reuse the cached model and start instantly.
Audio is streamed through a local speech-to-text model (via transformers.js) that runs on WebGPU when available and falls back to WASM. You pick the model before recording, and the picker shows each model’s approximate size and whether it’s already downloaded:
The Whisper models support ~99 languages including Indonesian; for those you can pick the spoken language for the most accurate transcript or leave it on Auto-detect. Each model is downloaded and cached in your browser on first use; Settings → Transcription lists every model with its size and downloaded state and lets you Remove any of them to free local storage. The recorder downsamples to 16 kHz mono and transcribes in short rolling windows, so the transcript fills in live as the meeting progresses. Each line is stamped with its offset in the recording ([M:SS]), which later powers click-to-seek playback.
On save, the meeting is inserted immediately with the transcript already in place, so it is always viewable even if AI enrichment later fails. The original recording is uploaded to your private object storage (R2) as a webm/opus file. Then the background pipeline adds the summary, tags, sections, language, and embeddings.
audio — marks the item as a meeting and drives the player UI.recordings/{id}.webm).Open a meeting to play it back with a built-in audio player that supports seeking across the full recording, plus current/total time. Below it, the transcript renders as a timeline — click any timestamp to jump the player to that exact moment. The recording is streamed from storage with HTTP range requests so seeking is instant and does not require downloading the whole file first.
ready (never failed) so the recording and transcript remain fully usable.The browser uploads the finished recording and transcript as multipart form data. Extraction is skipped because the transcript is produced client-side.
const form = new FormData();
form.append("audio", audioBlob, "recording.webm");
form.append("transcript", transcript); // timestamped [M:SS] lines
form.append("title", title);
form.append("durationMs", String(durationMs));
// optional: form.append("collectionId", collectionId);
await fetch("/api/links/meeting", { method: "POST", body: form });