Artifacts¶
Everything about a meeting lives in one folder under [general] meetingsRoot:
~/Meetings/2026-08-18 1030 Weekly sync/
├── meeting.json metadata (schemaVersion 4)
├── recording.m4a track 0 mic (raw), track 1 system (raw); AAC 48 kHz mono each
├── transcript.json schemaVersion 2 - the public API
├── transcript.md rendered, chronological
├── pipeline.log per-run timings, model ids, parameters, warnings
├── summary.md written by an automation; shown in the app when present
├── exports/ <slug>.md / .srt / …
└── automations/ <name>-<yyyyMMdd-HHmmss>.log + .result.json per run
Renaming a meeting renames the folder; meeting.json.id is the stable key. Plain files, no
database required - the SQLite index is a cache (rex reindex rebuilds it).
meeting.json (v4)¶
{
"schemaVersion": 4,
"id": "uuid",
"title": "Weekly sync",
"titleSource": "windowTitle | calendar | manual | default",
"startedAt": "2026-08-18T10:30:02-05:00",
"endedAt": "2026-08-18T11:01:40-05:00",
"durationSec": 1898.0,
"source": { "kind": "detected | manual | import", "app": "com.microsoft.teams2", "appName": "Microsoft Teams" },
"recording": { "file": "recording.m4a", "sampleRate": 48000,
"tracks": [ {"index":0,"role":"mic","device":"Elgato Wave:3"}, {"index":1,"role":"system","device":"MacBook Pro Speakers"} ],
"complete": true, "recovered": false },
"speakers": { "you": "Phill", "map": { "S1": { "label": "Alice Jones", "email": "alice@example.com", "speakerId": "uuid" }, "S2": { } } },
"transcript": { "file": "transcript.json", "status": "ready | pending | failed", "lastRun": "…", "model": "parakeet-tdt-0.6b-v2", "aec": true },
"attendance": { "source": "teamsSnapshot", "resolvedAt": "…", "iCalUid": "…", "exchangeId": "…",
"organizer": { "name": "Rosaria Bach", "email": "rbach@example.com" },
"invited": [ { "name": "Alice", "email": "alice@example.com" } ],
"match": { "subject": "Weekly sync", "start": "…", "end": "…",
"reason": "subjectAndTime | timeOverlap | subject | manual" } },
"app": { "version": "0.1.0", "build": 1 }
}
attendance is optional (schemaVersion 2, additive): present only when Teams enrichment resolves
organizer + invited emails from the local Teams app. Readers that predate it ignore the field.
attendance.match (schemaVersion 4, additive) records which Teams meeting the attendees came from
and why it was picked - subjectAndTime, timeOverlap, subject, or manual when you chose it
from the attendees menu. Files written before v4 have no match.
speakers.map values are objects since schemaVersion 3: label is the speaker's full name as
entered (absent while unnamed), email is optional, and speakerId links to the global speaker
record once assigned. Keeping name and email here means the speaker database can be rebuilt from
the meeting folders. Rex still reads the v2 shape ("S1": "Alice", "S2": null).
recording stays even after retention trashed the audio; the app checks whether the file exists.
transcript.json (v2)¶
{
"schemaVersion": 2,
"meetingId": "uuid",
"generatedAt": "…",
"engine": { "asr": "fluidaudio/parakeet-tdt-0.6b-v2", "vad": "fluidaudio/silero",
"diarization": "fluidaudio/pyannote-community-1", "aec": "webrtc-apm/aec3",
"params": { "micDelayMs": 150, "aec": true, "beam": false, "secondPassRetry": true,
"diarization": true, "maxSpeakers": 8, "speakerThreshold": 70 } },
"speakers": [ { "id": "you", "label": "Phill", "track": "mic" },
{ "id": "S1", "label": "Speaker 1", "track": "system", "speechSec": 412.5,
"voiceprint": "<base64 float32[256]>",
"speakerId": "uuid", "assignment": { "source": "manual | automatic | voice", "confidence": 0.91, "at": "…" } } ],
"segments": [
{ "id": 0, "speaker": "you", "track": "mic", "start": 12.34, "end": 15.90, "text": "…",
"confidence": 0.93, "words": [ { "w": "Let's", "s": 12.34, "e": 12.51, "c": 0.98 } ] }
]
}
Segments are sorted by start; track is always present; words and confidence depend on the
engine. Exporters consume only this file. Renaming a speaker rewrites speakers[].label (and
meeting.json.speakers.map), never segment text. Changing the shape of either file bumps
schemaVersion.
Since schemaVersion 2 each system-track speaker carries its voiceprint (the mean diarizer
embedding for that voice in this meeting, base64 little-endian float32) and speechSec;
speakerId and assignment appear once the voice is linked to a speaker record. The
voiceprint is biometric data: it stays in this file and never reaches transcript.md or any
export, including the JSON export.