Build Sembly AI
KINDAreplaces $17/mosaves $204/yrback to the verdict
A local meeting notebook whose hard problems are capturing the far side of a call at all and proving you did, keeping two independently clocked audio tracks aligned over an hour, and producing tasks that never invent an owner or a deadline nobody said.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the capture service and the interface.
Get it python.org or your version manager. open ↗
Verify
python3 --version prints 3.12 or higher - decidefree, or the price of a virtual audio device
Why This is the whole product and it differs by operating system and version, so confirm it with a ten second test recording before writing anything else.
Get it Read your platform's current documentation for capturing what the speakers are playing, grant the permission, and record ten seconds of music.
Verify
A test recording of the remote track contains audible sound, not silence - have readyfree, plus disk for the weights
Why These are recordings of other people talking, and sending them to a service is a decision that should be deliberate rather than a default.
Get it Download a local speech recognition model suitable for your machine.
Verify
A one minute recording transcribes locally in an acceptable time - installfree
Why Imports the recordings other tools produce and converts anything you were sent.
Get it Your package manager, or ffmpeg.org. open ↗
Verify
ffmpeg -version prints a version - have readyfree
Why Hours of two-track audio adds up faster than people expect and the notebook becomes a liability before it becomes a space problem.
Get it Decide the retention period in days and check you have room for that many hours.
Verify
The configured retention and the available disk are both written in the README
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- meetings(id, title, started_at, ended_at, consent_note, state) · the consent note is required before recording starts - tracks(id, meeting_id, kind, file_path, started_at_wall, sample_rate, frames_written, rms_summary) · kind is microphone or remote - segments(id, meeting_id, track_id, start_ms, end_ms, text, model_id, confidence) · times are on the shared timeline, not the track's own - speakers(id, meeting_id, label, display_name, source) · source is track for your own voice, cluster for a guess, manual for a correction - segment_speakers(segment_id, speaker_id, assigned_by) · assigned_by is diarisation or human - items(id, meeting_id, kind, text, owner_speaker_id, due_text, segment_ids_json, state) · kind is decision, action or question, and owner may be null forever - topics(id, meeting_id, label, segment_ids_json) · derived, rebuildable, never the only copy of anything - Every generated sentence in this schema carries the segment identifiers it came from. There is no summary row without them.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
DATA_DIR | required | ./data | Recordings, transcripts and the database. Everything the notebook is. |
MIC_DEVICE | required | Built-in Microphone | Chosen by name, because device indexes move between reboots. |
REMOTE_DEVICE | required | System Audio Capture | The call audio device. Getting this wrong records you twice. |
SILENCE_ABORT_SECONDS | required | 45 | How long a silent remote track is tolerated before the recording stops. |
ALIGNMENT_TOLERANCE_MS | required | 250 | The drift the alignment test is allowed at the end of an hour. |
AUDIO_RETENTION_DAYS | required | 60 | Recordings are deleted after this; transcripts and items are kept. |
SPEECH_MODEL_PATH | required | ./models/speech | Stored with every segment, because two models give two transcripts. |
The build, in order
Two tracks, or an honest refusal
A recording captures microphone and call audio separately, and a silent far side stops the recording rather than being discovered later.
Guessing which device is the call is how you get two microphones.
Files
capture.pydevices.pyThe start times are what lets you align the tracks later.
Files
capture.pyThis is the failure that ruins a notebook quietly.
Files
capture.pytests/test_silence.py
done when · tick each as it passeswatch out- Requesting system audio and getting a stream with no audio track, or a track of digital silence because a permission was refused without an error, produces a recording that looks complete and contains only you. Measure both tracks during capture, not afterwards, and make a silent remote track an error the user sees within the first minute rather than a discovery in the transcript.
One timeline, two clocks
Segments from both tracks line up at the end of an hour, not just at the start.
The difference is invisible for a minute and fatal for an hour.
Files
timeline.pytests/test_drift.pyTwo sets of times in one table is how alignment bugs hide.
Files
transcribe.pyThe display is a view; the tracks are the record.
Files
views/transcript.html
done when · tick each as it passeswatch out- Assuming both devices produce exactly their nominal sample rate means a small constant error accumulates, and by the end of a sixty minute recording your reply sits several seconds before the question it answered, which makes the interleaved transcript read as nonsense and quietly ruins every note built on it. Measure frames against wall time per track, store the correction, and test alignment at the end of a long recording rather than the start.
Your voice is known, everyone else is a guess
Speaker labels distinguish what is certain from what was clustered, and corrections stick.
It is the only speaker label in this build that is not a guess.
Files
speakers.pyShow the user which labels are evidence and which are inference.
Files
diarise.pyviews/transcript.htmlThe corrections are the most expensive data in the notebook.
Files
speakers.pytests/test_corrections.py
done when · tick each as it passeswatch out- Running diarisation across a premixed file, or across both tracks together, throws away the one piece of ground truth you actually have and then asks you to trust a guess about it, so your own sentences start being attributed to the client. Cluster the remote track only, and mark your own track by construction.
Tasks that nobody invented
Decisions, actions and questions each point at the seconds of audio they came from, and an unassigned action stays unassigned.
An unresolvable citation means the item was invented.
Files
items.pytests/test_citations.pyFilling the blank is the moment this product starts lying.
Files
items.pyviews/items.html'Early next week' is information; a parsed Tuesday is a fabrication.
Files
items.py
done when · tick each as it passeswatch out- Asking a model for action items with owners produces a tidy table in which the quietest person in the meeting has been assigned three tasks they never accepted, and because the table looks authoritative nobody checks it against the recording. Require citations, resolve them, and make an unowned action a first class state rather than a gap to be filled.
A notebook rather than a pileproduct builder
Search works across meetings, storage stays bounded, and everything can be taken elsewhere.
A paragraph with no timestamp is not checkable.
Files
search.pyviews/search.htmlThe recording is the liability; the notes are the asset.
Files
retention.pytests/test_retention.pyMarkdown and a timed transcript outlive this application.
Files
export.py
done when · tick each as it passeswatch out- Keeping every recording forever turns a notebook into tens of gigabytes of other people's voices on a laptop that travels, and the day it is lost the problem is not your notes. Set a retention period on audio from the first release, delete on schedule, and keep the transcripts and items which are what you actually reread.
That is the whole plan for Sembly AI. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- A meeting bot that joins calls for you.
- Calendar auto-join.
- Team workspaces and shared retention.
- Mobile capture.
- meeting bots, team collaboration, automations, and broad integrations
- calendar auto-join
- reliable speaker diarization
- mobile capture
- team search and sharing
- Importing a recording the meeting platform made itself, which sidesteps the capture problem entirely when the platform offers one
- A weekly review that lists every unassigned action older than a fortnight, which is the honest output of refusing to invent owners
- Per-speaker voice profiles kept locally, so a regular participant is named across meetings rather than per meeting
Need the files? The project pack on the verdict page hands your agent the whole brief · more meeting notes.