Build tl;dv
KINDAreplaces $18/mosaves $216/yrback to the verdict
A local recorder whose hard problems are capturing hours of audio without losing any of it, presenting a transcript that invents text as something the reader is expected to verify, and keeping a growing pile of recordings of other people under control.
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 recorder, the library and the workers.
Get it nodejs.org, or your version manager. open ↗
Verify
node --version prints v22 or higher - installfree
Why Segment recording, clip cutting and format conversion all go through it, and the clip boundary work depends on its behaviour.
Get it Your package manager, or the official builds. open ↗
Verify
ffmpeg -version prints a version and the build lists your audio input device - installfree, plus disk for the model
Why The default path keeps audio of other people on your machine, and the model size you choose decides both accuracy and how long a meeting takes to process.
Get it Download a runtime and one model file, and note which model you used.
Verify
A two minute recording transcribes with timestamps in a time you are willing to wait - have readyfree, or the price of a virtual device
Why Recording the other side of a call is the part that differs most between operating systems and versions, and it decides whether this tool is useful or just records you.
Get it Check the current documentation for your operating system version, then either use its supported capture interface or install a virtual audio device.
Verify
A test recording contains both your voice and audio played by another application - decidefree
Why The rule here is that you announce it, and deciding the wording once means you actually do it rather than deciding in the moment.
Get it Write the sentence you will say and the retention period you will offer, and put both in the README.
Verify
The consent prompt in the application matches what the README promises
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, folder, consent_note, state) · consent_note records who was told and how - segments(id, meeting_id, ordinal, path, started_at, seconds, bytes) · the recording is a sequence of short files, not one buffer - lines(id, meeting_id, start_ms, end_ms, text, no_speech_prob, avg_logprob, model_id, chunk_ordinal) - markers(id, meeting_id, at_ms, label, created_at) · dropped live with a hotkey while the meeting runs - clips(id, meeting_id, marker_id, start_ms, end_ms, path, created_at) - summaries(id, meeting_id, model_id, prompt_version, created_at, bullets_json) · each bullet holds its text and the line ids it cites - retention(meeting_id, audio_delete_after, audio_deleted_at) · the transcript survives the audio - There is no column anywhere holding a summary sentence without a list of line ids beside it. A bullet that cannot cite is a bug.
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 |
|---|---|---|---|
MEETINGS_DIR | required | ~/Meetings | One folder per meeting holding segments, transcript, notes and clips. |
DATABASE_PATH | required | ./data/meetings.db | The index over the meeting folders. Rebuildable from them. |
SEGMENT_SECONDS | required | 60 | Segment length. This is how much a crash can cost you. |
ASR_MODEL_PATH | required | ./models/speech-medium.bin | The local speech model. Its identifier is stored with every transcript line. |
SUMMARY_API_KEYsecret | optional | sk-...redacted | Optional hosted model for summaries. Without it the transcript and clips still work. |
AUDIO_RETENTION_DAYS | required | 30 | Audio is deleted after this. Transcripts, notes and clips survive. |
CLIP_LEAD_SECONDS | required | 30 | Lead-in and lead-out either side of a marker when cutting a clip. |
The build, in order
Capture that survives a three hour call
Recording writes continuously to disk in short segments and a mid-meeting failure costs seconds, not hours.
The meeting is the folder; the file is only the last few seconds at risk.
Files
src/capture/recorder.tstests/segment-crash.test.tsCapturing another application's audio is an operating system question with a different answer on each one, so check the current documentation for your version before designing around it.
Files
docs/audio-capture.mdAfterwards it is a form nobody fills in.
Files
src/capture/start.ts
done when · tick each as it passeswatch out- Recording into one file that is only finalised on stop means a crash, a full disk or an unplugged interface leaves a file with no usable header and the whole meeting is gone, which is exactly when you most needed it. Write short segments, close each one properly, and treat the meeting as the folder rather than the file.
A transcript the reader can check
Every transcript line carries its timestamps and its confidence signals, and the audio behind it plays on a click.
A boundary in the middle of a sentence is where transcripts go wrong.
Files
src/transcribe/chunks.tstests/overlap.test.tsSilence is where invented sentences come from.
Files
src/transcribe/vad.tsThe reader deciding whether to trust a line needs the number.
Files
src/transcribe/store.ts
done when · tick each as it passeswatch out- Feeding a long silence or a stretch of hold music to a speech model produces confident, grammatical sentences that nobody said, and they look identical to real transcript lines in a text file. Cut non-speech spans before transcription, keep the no-speech probability on every line, and mark low-confidence lines in the interface rather than hiding the number.
A summary that cites or says nothing
Notes and action items are generated only with the transcript lines they came from attached.
A claim without a source is not a note, it is a guess.
Files
src/summary/prompt.tsThe model will cite lines that do not exist.
Files
src/summary/verify.tstests/citations.test.tsSo a strange bullet can be traced rather than argued about.
Files
src/summary/store.ts
done when · tick each as it passeswatch out- A clean five bullet summary with no links is the most dangerous artefact this application can produce, because it is exactly the thing people forward, and neither the sender nor the receiver can tell which sentence came from a hallucinated transcript line. Require citations, verify them mechanically, and drop the bullets that fail rather than showing them unmarked.
Markers while it happens, clips afterwards
A hotkey during the meeting marks a moment, and each marker becomes a clip you can play or hand over.
The moment worth clipping happens while you are looking at the call.
Files
src/capture/hotkey.tsSegment start and duration are the only reliable clock here.
Files
src/clips/cut.tstests/clip-boundary.test.tsA silent clip is a bug report you will never receive.
Files
src/clips/cut.ts
done when · tick each as it passeswatch out- Cutting a clip by seeking into a single concatenated file falls apart the moment a segment is missing or a device changed sample rate mid-meeting, and you get silence or a clip from the wrong minute. Build the clip from the segment timeline, using each segment's recorded start and duration, and fail loudly if the requested range crosses a gap.
A library that forgets on purposeproduct builder
Meetings are searchable, the audio expires on a schedule, and deleting a meeting really removes it.
The notes were the point; the recording was the means.
Files
src/retention/sweep.tstests/retention.test.tsAnything left behind makes your deletion claim untrue.
Files
src/meetings/delete.tsThis tool should not be needed to read your own meetings.
Files
src/export/folder.tsterminalnpm run export -- --meeting=2026-09-15-standup
done when · tick each as it passeswatch out- Keeping every recording forever because disk is cheap leaves you holding hours of other people talking, indexed and searchable, long after the reason for recording them ended, and the first time that matters is the worst possible time. Set a retention period on day one, delete the audio on schedule, and keep the notes that were the point.
That is the whole plan for tl;dv. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- A bot that joins calls on your behalf.
- Speaker identification and stored voice profiles.
- Customer record synchronisation.
- A shared team library.
- meeting bot upkeep
- team/shared library
- CRM integrations
- admin controls
- polished clip sharing
- A per-meeting cost and time report, so you know what a three hour recording actually costs to process
- Transcript correction that feeds back into the summary, since the corrections are the only ground truth you will have
- A weekly digest of your own action items, generated locally and never sent to anybody else
Need the files? The project pack on the verdict page hands your agent the whole brief · more meeting notes.