I Built a Voice Notebook That Runs Entirely on My Own Computer

Build log  ·  October and November 2026

I Built a Voice Notebook That Runs Entirely on My Own Computer

Dictate notes, ask questions about months of them, proofread them, and talk to it through your speakers. Everything stays on your machine, unless you ask it to search the web.

No cloud  ·  No subscription  ·  No account  ·  RTX 4070 SUPER · CachyOS Linux

I wanted one thing: talk, and have my words end up as tidy notes that I can question later. No account, no monthly fee, and nothing I say leaving my computer. A PhD supervisor meeting, a lecture, a stand-up: all of it is private by default if it never leaves the machine.

So I built it. It's called narrastack. This post is the story of what it does, how it works, and the eight problems that took the longest to solve. If you want to build something similar, the problems are the useful part.


What it does

You open a page in your browser and press Start listening.

Start popup

The start popup — browsers require a click before microphone access is granted.

There are two modes, and one optional extra.

Dictate

Whatever you say becomes notes. Words appear as you speak, settle, and are saved. Notes are grouped into sessions with an automatic title and a short summary with action items.

Ask

Say the assistant's name first and ask a question. It answers out loud, through your speakers, while you keep working.

Search (optional)

Off by default. When you say "search the web for…", only the search words leave the computer, and the answer names the page it came from.

Notes grouped into sessions

Sessions with automatic titles and summaries, and the note you are dictating into pinned above them.

The active note

The note you are dictating into is pinned above the list, so it never scrolls away while you look through older ones. A dot beside its title pulses with your voice, and a chip says whether it is listening, paused or idle. Whatever you dictate, and commands like "proofread that", act on it.

The active note pinned above the notes list

The active note, pinned above the saved notes. The dot pulses with your voice.

Any saved note can be made active again, and new dictation is added to it. Click Continue on a note, press Enter on it from the keyboard, drag it up into the active area, or say "Skywalker, continue the supervisor meeting note". A "continued" divider marks where you picked it up, every line keeps its real time, and a toast offers Undo.

Dragging a note towards the active note area

Dragging a note up: the active area turns into a drop zone.

A continued note in the active area

Continued: the older note moved up, the stand-up dropped into the list, and a divider shows where it was picked up.

A note you choose to continue stays open past the usual ten-minute quiet rule, because you picked it on purpose. Dragging is only one way in: the button, the keyboard and your voice all do the same thing, so nothing depends on a mouse.

Notes keep the original words you said. You can ask it to proofread or enhance a session, and it shows every changed line for you to accept or reject one at a time. Nothing is overwritten without your say-so.

Proofread review interface

Line-by-line review — accept or reject each change individually.

Dropped word warning

If the proofreader deletes words that carried meaning, the line is unticked and flagged.

Question across notes

Asking questions that need all your notes — "what action items came out of my meetings last month?"

Searching the web, only when you ask

This is the one feature that sends anything off the computer, so it is off by default and only runs when you say something like "Skywalker, search the web for the capital of Australia". The search words go out through a search service running on my own machine, never my notes and never my voice. The answer names the page it came from, and the pages are listed under it so you can check.

A spoken question answered from the web, with its sources listed

The answer begins with its source, and the pages it used are listed underneath.

Taking notes out

Export follows what you are looking at. Tick some notes, or search, or look at a group, or choose "last 7 days", and the Export panel starts from that. One note downloads as a plain file named after it; several share one file, or become a zip with one file per note (offered only when there are at least two, because a zip of one note is just in the way). It can be Markdown or plain text, with or without dates, summaries and the original wording, and a Copy button puts the same text on the clipboard to paste into an email or a document. The note you are still dictating into is included and marked "(in progress)", because the file is a snapshot.

The Export panel with two notes selected

Two notes ticked, and the panel offering Markdown, text or a zip, with Copy and Download.

Meetings, and who said what

A meeting is a note made for a room of people talking, started with the New meeting button or by saying "Skywalker, start a meeting about the roadmap". Four things change. Everyone in the room is noted, because the quiet-sound gate that ignores other voices is off. It never closes itself after a quiet spell. A long run-on turn is saved as several lines of about thirty words, cut at sentence ends. And every few minutes the new lines are turned into three to seven bullet points of minutes: what was discussed, what was decided, who owns which action. When the meeting ends, the summary, main points and actions are made from the note itself, a part at a time, with each one tied to the lines it came from (next section).

An open meeting in the notes column: a Minutes section with four bullet points, then the lines, each tagged with a coloured speaker name.

A meeting in progress. The minutes sit above the lines, and each line carries the name of who said it.

Telling people apart is optional and happens afterwards. A switch in Settings, Record meeting audio, is off by default. When it is on, the sound of a meeting is saved on the computer while the meeting is open, and never otherwise. After the meeting, Label speakers works out who spoke when, on the processor, with a progress bar, and tags every line. You click a tag to give that person a name, and the name is used everywhere, including in exports. Only the labels and the names you typed are kept, no voiceprints, and the recording can be deleted from the same menu.

A meeting card with a progress bar reading Telling the voices apart, 62 percent.

Labelling a meeting. The bar moves while it finds where people speak, then shows a percentage.

Two smaller additions came from using it on long notes. A note can be given the whole notes column with Focus on this note, and proofreading an hour of notes now opens a review that scrolls, with filters for changed lines and lines that need a look, next and previous buttons, and the Accept button always in reach. My first version of that review had no scroll bar at all, which I only found on a real hour-long meeting.

One finished meeting filling the whole notes column, with a back link to all notes, its summary, actions, minutes and named lines.

A finished meeting in focus: its summary, actions and minutes above the named lines. Esc goes back.

A proofread review of a 120-line note: a header reading 40 of 120 lines changed, filter tabs, and the changed lines with Accept 39 at the bottom.

Reviewing 120 lines: only the changes are shown by default, and the buttons stay at the bottom.

Summaries you can check

Every note can have a Summary, Main points, and Actions and decisions, made when the note closes or whenever you ask. The trouble with an assistant's summary is that you cannot tell where it came from, so every sentence and point carries a tag such as "3 lines". Click it, or the item, and the lines it was written from light up in the transcript, scrolled into view, with a bar to step between them. It works the other way too: a small dot beside a line means it was used, and clicking it flashes the items that came from it. Your lines are never touched. The summary is a separate layer, and you can edit, remove or add items; your edits are kept when it is updated.

A finished meeting with a Summary whose sentences carry tags such as 2 lines and 3 lines, Main points, and a bar reading 1 line with the source line highlighted in the transcript below.

Click a tag or an item and its source lines are highlighted. The bar steps between them, and Esc clears it.

The model is asked to cite line numbers, and the program does not take its word for it. A number that does not exist is thrown away. An item whose cited lines do not contain its numbers, its names or most of its words is marked check, and one with no usable source is marked no source. And because speech-to-text mistakes in names and terms would otherwise be copied into the summary, asking to summarise a note that has not been proofread first offers to proofread it: Proofread first, Summarise now, or Cancel. A summary made from the wording as dictated says so, and offers Proofread, then update.

A note with the question: This note has not been proofread. Buttons: Proofread first, Summarise now, Cancel.

The question asked before summarising a note that has not been proofread. The original wording is kept either way.

Getting notes ready while you are away

Several of those jobs take a while, and nobody wants to wait for them. So when nobody has spoken for twenty seconds, the app uses the quiet: it writes minutes, labels the speakers of a recorded meeting, prepares proofread suggestions, and summarises notes that need it, newest first. It never edits your text. The proofread suggestions are kept ready ("Proofread suggestions are ready: 3 changes to review") and nothing is applied until you accept. A small chip in the status bar says what it is doing, with a Pause, and one switch in Settings turns it off.

The whole window: the notes list with a note offering Proofread suggestions are ready, and the status bar showing Preparing notes: Summarising: Planning session with a Pause button.

Quiet-time work: a note with proofread suggestions already prepared, and the status-bar chip while the next job runs.

The people who take a real break get a real button. Break starts a timed break of 5, 10 or 15 minutes (or any length). Listening stops, so the room does not turn into notes, and the work starts at once instead of waiting for the quiet. A countdown replaces the button's label, and the panel shows each note's steps as done, now or to do, with a rough time. When time is up the panel opens with what is ready, such as "112 proofread suggestions to review" and "Summary ready", and each entry jumps to its note. The microphone stays off until you press Resume listening. The same timer is meant to carry a Pomodoro-style rhythm and tasks later, so each break is logged as an interval.

The Break panel during a break: a countdown of 7:12, a progress bar, and a checklist where minutes and speakers are done and proofread suggestions are in progress.

During a break: the countdown and what is being prepared.

The Break over panel listing 112 proofread suggestions to review and Summary ready with 41 items, then Resume listening and 5 more minutes.

When the time is up: what is ready, and the microphone still off.


Key takeaways

  • 01 A fully local voice assistant is realistic today on one consumer graphics card (mine has 12 GB).
  • 02 The hard part is not the models. It is turn-taking: knowing when you have finished, when it is being talked over, and when a cough is just a cough.
  • 03 Choosing the wake word needs measuring in the real app. A name that scored 5/5 in a script was heard only 3 times in 7 in daily use.
  • 04 Answering questions over months of notes needs a different approach from simple search.
  • 05 Browser audio gives you echo cancellation for free, which is what makes talking over speakers work.
  • 06 Never let the language model say it did something. Do it in code, and let the model only talk.
  • 07 Dictation waits for you to pause. A meeting never does, so a meeting needs its own rules for when a turn ends, and telling the speakers apart needs the audio, not the transcript.
  • 08 A small local model can summarise a note of any length if you read it a part at a time and make every claim point back to the text. Without the pointer you cannot tell a summary from an invention.

How the pieces fit

Four parts, all running locally (and an optional fifth, a small search service, if you turn on web search):

1. Speech recognition: faster-whisper (the small.en model) on the GPU.
2. A language model served locally, for answers, titles, summaries and proofreading.
3. A voice (a local text-to-speech server) that speaks the replies.
4. A small web app that ties them together and stores notes in SQLite.
System pipeline diagram

The full pipeline — browser ↔ local WebSocket server ↔ GPU models.

Your browser captures the microphone and plays the voice. A tiny server handles the rest. The audio travels over a local WebSocket: about 32 KB/s up and 48 KB/s down, which costs essentially nothing. Transport measured at 0.004 ms per 100 ms frame.


The eight problems

These are the useful part. Each one has a concrete cause and a concrete fix.

01

Showing words live without them flickering

Speech recognition models want whole sentences. I wanted words as you speak. The trick is to re-decode the recent audio every 0.8 seconds and only commit a word once two consecutive decodes agree on it. Unsettled words stay greyed; settled words stay put. Text no longer jumps around.

02

Not hearing things that were never said

Whisper has a well-known habit: given silence or noise, it writes "Thank you." It also produces "Ahem" for coughs. Fixes that worked:

  • An adaptive noise gate. A frame only counts as speech if it is about 8 dB above the room's measured noise floor.
  • Filters for the known phantom phrases, applied only when the model itself reports low confidence in speech.
03

A microphone that was far too loud

My noise was constant and strange. It turned out the gain was stacked: +30 dB in one place and another +30 dB in another, +60 dB in total. Room noise measured -32 dBFS. After dropping the boost to +10 dB, it measured -52 dBFS; a quiet room is around -60.

Mic gain measurements

Before and after fixing stacked gain: -32 dBFS → -52 dBFS.

The lesson: fix the signal at the source before writing software to compensate.

04

Knowing when you have finished talking

Respond too early and it cuts you off mid-thought. Too late and it feels sluggish. The app waits for a pause whose length depends on what you said:

Question ending on ?0.6 s
Finished-looking sentence0.9 s
Sentence trailing off ("and…")2.2 s
Latency diagram

About 1 s end-to-end; median first spoken audio at 0.4 s after decision.

05

Choosing the wake word

My first choice, "Quill", was bad. Whisper did not recognise it unless I told it to expect the word, and telling it made Whisper invent "Quill" out of pure noise. I tested eight candidates with synthetic voices, then the best ones in my own voice with a test script.

Oberon won that test, with 5 out of 5. Then I used it. Through the real app and the browser's audio, Whisper wrote "Omoran", "All born on", and "Vinny?". In one session it heard the name 3 times in 7.

Wake word results: test script versus daily use

Test scripts said Oberon was fine. The running app disagreed. Skywalker: 46 of 47.

The app can save the last 30 seconds of audio when I flag a mistake, so I replayed four of the misses offline with different settings. The obvious fix, telling Whisper to expect the name, made it drop the name entirely (0 of 4). Showing it a short example sentence that contains the name, such as "Skywalker, proofread that.", got all four right, and did not invent the name out of silence or noise. It is only shown while the first words of a turn are being decoded, never mid-sentence.

I switched to Skywalker, a word Whisper already knows and one I almost never dictate. Across two test sessions I addressed it 47 times, and it was heard 46 times.

I also made the app only treat a sentence as addressed to it if the name starts it, so "I should start dictating" never switches modes by accident. I did not add loose "close enough" matching: mishearings like "Omeran" scored about the same as ordinary words like "Oregon", so dictation starting with those would have turned into commands.

06

Talking over speakers

This is the one that surprised me. If the assistant speaks through speakers, its own voice goes back into the microphone and it hears itself. Headphones solve it, but I wanted speakers.

Running the audio in the browser fixes most of it, because browsers ship echo cancellation. On top of that, the app remembers what it said recently and ignores text that matches its own speech.

07

Letting you interrupt, but not a cough

Real conversation means you can interrupt. But a cough, a tap on the desk, or a chair creak should not stop a story halfway through. The design is two steps:

  • After 0.3 s of voice, the volume ducks instantly to 12%.
  • It only stops if it hears confident words, or a long stretch of voice that has a pitch (like a vowel). A cough or tap has almost no pitch. If nothing confirms within 1.8 s, the volume returns.
Interruption logic diagram

Tap: ~0.24 s, no pitch. Cough: up to 0.6 s, almost no pitch. Speech stops it in about 1 s.

A real cough still occasionally stops it. I consider that acceptable, not perfect.

08

Questions that need all your notes

"What did my supervisor say about chapter two?" is easy: search finds it. "List every action item from last month" is not — the answer is spread over dozens of notes and plain search finds the wrong ones.

So the app detects questions that need broad context, works out any date range you mentioned, and uses the stored summaries. If they fit, they are used directly. If not, it reads the notes group by group and combines the results.

Broad question results

On 102 synthetic notes: 5/5 action items found vs 1/5 with plain search.


Added after the first version

A few days of actually using it found things no test had.

A

Web search that does not trust itself

The search service is SearXNG in a container, which asks several public search engines at once. The community warns that engines block it, and it is true: DuckDuckGo showed a CAPTCHA on every search I ran. Google and Brave carried the results, and an optional paid API, Serper, can take over if the local one fails. In my 16-question comparison the two gave about the same quality.

Timeline of a web question

A web question: the slowest step is waiting for web pages, so any page not loaded after 4 seconds is replaced by its snippet.

The real problems were not the search. The small local model sometimes misreads a page: it told me to sort SQLite results in what I believe is the wrong direction, and gave two different sets of tide times from two sites. So the answer names its source, says so when pages disagree, and refuses to answer at all if none of the distinctive words in my question appear in the pages. That last check exists because Google quietly "corrected" a nonsense query into a real one, and the model then made up a confident answer about it.

Follow-up questions work too: "how many people live there?" after a question about Canberra searches for Canberra's population.

B

Commands that survive a messy transcript

I told the assistant "dictate mode" in Ask mode, and it replied "Dictate mode activated. Please proceed with your notes." Nothing had changed. The command needs the name, so my words went to the language model as a question, and it simply played along. Two fixes: in Ask mode everything is already addressed to the assistant, so mode and note commands now work without the name; and the model is told it cannot change modes or notes and must never say it did.

Whisper also writes "new note for the stand-up" as "move out for the stand up" or "new mode for…". Those are accepted now, but only with a short title, so ordinary sentences are not mistaken for commands.

C

Starting it like a real app

One script now checks the language model, the voice and (if enabled) the search service, starts whichever is missing, in order, and opens the page. It adds a start-menu entry with an icon. Ctrl+C stops everything it started. When I tested closing the terminal window, the app stopped but the model and voice servers kept running on the GPU, so that is fixed too: closing the window stops the lot.

D

Ignoring other voices

Whisper will happily turn a TV, a video or someone in the next room into text. I found three notes I had never said: "And that's all for now.", "I'm sorry." and "We will". Measuring the saved audio showed why they got through. My own speech peaked at about -4 dB in every utterance I measured, because the browser levels it. Those stray voices were 20 to 50 dB quieter, and two of them contained real pitched voice, so this was not just noise.

So an utterance that is not addressed to the assistant, and is far quieter than I normally speak, is now shown dimmed as "ignored" with a Keep as a note button, instead of being saved. The limit follows two things: how loud I usually speak (remembered between runs) and the room's noise, never nearer than 25 dB to it. A small meter in the live box shows it: a grey tick for the room, a teal one for my usual level, and an amber line for the limit. Saying the assistant's name always works, however quietly.

An ignored quiet voice and the level meter

A voice well under the amber limit: the meter turns amber, the box says it is too quiet to count, and the line is kept out of my notes unless I click Keep.

It has limits, and I would rather say so. It cannot reject a TV that is right next to the microphone, because that is as loud as I am. Recognising my voice itself would, and is a possible later step. And the numbers come from one voice in one room.

E

A sound check that tells the truth

I wanted a tuner for the microphone level, so first I tested whether it could help. I took six of my real utterances, turned them down by 6, 12 and 18 dB, and counted how often Whisper heard the assistant's name: 2 of 6 at every level. Level is not what makes Whisper miss a word, so a tuner would not improve recognition.

What it can do is check the set-up and explain it. Settings has a 15-second Sound check: four seconds of quiet, then a sentence read aloud. It reports the room noise, my voice, and the gap between them, in plain words, and names causes. A room reading near -32 dB means two microphone boosts are stacked, which is exactly the problem from earlier. It also saves how loud I speak, so the assistant is calibrated from the first sentence after a restart instead of learning it again.

A finished sound check

A finished check: three rows in plain words, and the note that it has been saved.

It does not change any volume for me. It tells me what to change, and then I can check that it worked.

F

When the browser goes silent

One afternoon the app simply stopped hearing me, and nothing showed it. The server was fine, and the system microphone worked: recorded directly it had a real signal. Firefox was connected to the right input. But the page had nearly stopped sending audio, about 0.5 KB/s instead of the 32 KB/s a live stream needs.

I never pinned down what made Firefox stop. The stacked microphone gain had also crept back to +60 dB, and I suspect the browser's noise filtering reacts badly to that, but I cannot prove it. What I could fix is the silence. The page now counts the audio it sends. After 3 seconds without any it restarts the microphone, after 8 it rebuilds the audio, and after 14 it asks me to press a button (a click is what lets a browser start audio). It says so in plain words, and it logs what the browser reported, so next time I will know why.

The lesson is not about Firefox. It is that an app which silently hears nothing is worse than one that says it has a problem.

G

A meeting never pauses

To test meeting mode I played a recorded panel discussion into the microphone. The first real run produced three turns in two minutes, one of them 544 words long, and the live box on the page filled up and looked frozen. Nothing was broken: a turn only ends after a pause, and people talking to each other, or a video, barely pause. Everything piled up unsaved until the next gap.

The transcriber keeps the words it has agreed on in one growing block. The fix was to let the turn manager ask it, in a meeting only, to hand over what has been agreed so far once there are about 40 words, cut at the last sentence end, or after 70 words when there is no sentence end. The audio is not touched, so nothing is lost, and the next words carry on from where the cut was. The live box shows only the latest 60 words. On the next run the same video gave 12 hand-overs and 16 lines in about three minutes.

The same test found a smaller problem: "Skywalker, start a meeting" was twice heard with an extra word in it ("Skywalker, Girl, start a new meeting") and went to the assistant as a question. Start and end commands now tolerate one stray word after the name, but a question never loses its first word.

H

Who said that?

A transcript cannot tell speakers apart, and loudness is not a reliable clue, so this needs the sound. I record the meeting (only if you switch that on) and, afterwards, run a speaker-separation model on the processor: one model finds where each person speaks, another turns each stretch into a fingerprint of the voice, and similar fingerprints are grouped. Each line of the note then goes to whoever spoke for most of the time it was being said.

The first speaker model I tried found two voices in a four-person panel recording, and one of them held 160 of the 194 seconds of speech. Another model, TitaNet, found four voices of 67, 62, 39 and 26 seconds, with a scatter of one-second fragments. I fold fragments under four seconds into whoever is speaking next to them. I do not know the true answer for that recording, only that four is what I counted when I listened, so I show the lines to check by eye. A synthetic three-voice test, made with the text-to-speech voices, was separated correctly by both models. Separating the 4.4-minute recording took 16 seconds.

The limit that remains is that a line gets one speaker, and in fast back-and-forth a line can hold two people. Splitting lines where the speaker changes is the next thing to build.

I

A note that does not fit

The old summary of my longest meeting read only the first 6,000 characters, about a fifth of it, and nobody could tell. The language model I run takes about 5,000 tokens in one request, and a 4,561-word meeting is about 6,400. So the new summary reads a note in windows, with every line numbered so the model can cite it, and merges what it finds.

The first version quietly lost things. I tested it the way I should have at the start: synthetic notes of different sizes with eight known actions and decisions hidden at spread-out places, and a score for how many came back with the right source line. As the note grew it fell from 5 of 8 to 1 of 8 to 0 of 8. Three causes. The merge step asked the model to condense the actions of all the windows, and it simply dropped most of them. Some replies came back on one line, which my line-by-line reader could not see. And windows of about 3,000 tokens were too big for a small model to scan reliably; at 1,800 tokens it found everything.

Now actions and decisions are collected from every window and only de-duplicated, the reader copes with any layout, and windows are about forty lines. It found 8 of 8 at 1,500 and 4,500 words, 7 of 8 at 20,000 words (3.4 minutes), and 8 of 8 at 60,000 words (9.8 minutes), always with the right source line. The window size is capped by that measurement, not by what the server allows, so giving it more memory would not change the answer.

J

The name it made up

On my real 223-line meeting the first sourced summary included an action, "Marcus will share performance numbers". No one called Marcus is in that transcript. The name was in my own prompt: I had written an example of the format using it, and a small model copies what it is shown. The example now contains no names, and the program checks every capitalised name in an item against the lines it cites, marking the item check if it is not there.

That is the whole argument for the source tags. The tag is how you catch it: a summary you cannot check is one more thing to trust blindly, and a small model will sometimes invent. In the size test it invented no names, but only because the check and the example were fixed first.

K

Working while you are away

Before letting background work run, I measured what it costs. A summary running in the background did not slow live answers: first token 0.25 seconds idle against 0.21 during. But speech recognition shares the graphics card, and decoding 12 seconds of audio went from 0.12 to 0.35 seconds while a summary ran. That is why the work waits for twenty seconds of quiet, never runs while it is answering or speaking, and stops between its steps whenever you start talking again.

Two bugs showed up only when I ran it on a copy of my real notes. A one-line note that produced no summary would have been retried every few seconds for ever; now a job that finishes without producing anything is left alone for ten minutes. And Pause on the status-bar chip stopped a proofread but not a summary, because the summary's wait ignored it; I only found that when I asked what Pause actually stops. Run on a copy of my 223-line meeting reset to look freshly closed, it prepared 112 proofread suggestions in 91 seconds and a draft summary of 41 items in 22 seconds, within two minutes of quiet, and none of its lines changed.

The Break button came from a different thought. People tend to take a break after a meeting, so the app should not guess when they have stepped away: it should be told. The break turns off listening, starts the work immediately, and says what is ready when it ends. It never turns the microphone back on by itself.


Results

What Result
End of sentence to first word heard ~1 s
Median first spoken audio after decision 0.4 s
Wake word, test script, real voice (5 lines each) Oberon 5/5 · Orion 5/5 · Octavia 3/5 · Vesper 1/5
Wake word, daily use through the browser Oberon 3 of 7 · Skywalker 46 of 47
Stray voices (TV, next room) compared with my speech 20 to 50 dB quieter
Turning my voice down 6, 12 or 18 dB: name heard 2 of 6 every time
Web question, end of sentence to finished answer median 5.4 s (first word at 4.9 s)
Room noise after fixing mic gain -52 dBFS (from -32)
Broad questions, 102 practice notes 5/5 action items vs 1/5 plain search
A talking video played into a meeting, 3 minutes before: one 544-word turn · after: 12 hand-overs, 16 lines, 510 words
Four-person panel recording, 4.4 minutes, speaker separation first model: 2 voices · TitaNet: 4 voices (67, 62, 39, 26 s) · 16 s on the processor
Summary of a 4,561-word meeting: part of it read before: first fifth · after: all of it, 27 s
Eight hidden actions found, with the right source line (1,500 / 4,500 / 20,000 / 60,000 words) 8 of 8 · 8 of 8 · 7 of 8 · 8 of 8
Time to summarise 4,500 / 20,000 / 60,000 words 49 s · 3.4 min · 9.8 min
Same test at 3,000-token windows, 4,500 words 0 to 1 of 8 found
Live answer, first token, with and without a summary running 0.25 s idle · 0.21 s during
Speech recognition of 12 s of audio, with and without a summary running 0.12 s idle · 0.35 s during
A 223-line meeting reset to look fresh, prepared in quiet time 112 suggestions in 91 s · summary of 41 items in 22 s · no line changed

All practice notes in these tests were synthetic, made for testing. Wake-word results are from one speaker (me) in one room, so treat them as a guide and not a guarantee. Web timings are medians of 21 searches.


What you need to run it

  • A computer with a recent NVIDIA graphics card. I use an RTX 4070 SUPER with 12 GB; this runs Linux.
  • Python, a local language model server, and a local text-to-speech server.
  • A browser: Brave or Chrome work best. Firefox works too, but cannot choose the speakers, and it is the one that once stopped sending microphone audio (see card F).
  • Optional: Docker, only if you want web search.

Setup is a handful of steps, and then a single script (or a start-menu icon) starts everything. The page opens in your browser and the start popup appears.

Settings panel

Settings, in sections: Sound is shown, with Assistant (quiet sounds, web search) and Notes beside it.

Focus mode

Focus mode — notes only, everything else hidden.

Dark mode

Dark mode.

Microphone blocked message

If the browser blocks the mic, the app says so and tells you how to allow it.


Limits, honestly

  • It needs a decent GPU. On a laptop with no GPU it would be slow.
  • Whisper is good but not perfect, especially with unusual names. The "Names and terms" list helps with proofreading, not with live recognition.
  • A real cough can still stop it from speaking.
  • Interruption thresholds are tuned on my voice and my room. Yours may need adjusting.
  • English only for now.
  • Web search depends on Whisper hearing the word "web" or "google". It sometimes writes "red" or "lab", and then the question just goes to the model, which answers from memory.
  • The small model can misread a web page, which is why every web answer lists its pages.
  • Drag and drop is for a mouse. On a touch screen use the Continue button.
  • The wake-word numbers are one voice in one room, and so are the figures for ignoring other voices.
  • A loud voice right next to the microphone, such as a TV close to it, still looks like me.
  • Firefox once stopped delivering microphone audio and I never found the trigger. The app now notices, restarts the microphone and logs why, but I cannot promise it will not happen.
  • Speaker labels are best effort. A line gets one speaker, so a line holding two people is wrong for one of them. Similar voices can be merged, and someone far from the microphone can be missed. I have checked it on one four-person recording and one synthetic test, so treat it as a guide to check by eye.
  • The minutes are written from the text, so they cannot say who spoke. They name the owner of an action only when someone said the name aloud.
  • A video played through speakers into the microphone is harder for Whisper than a person in the room, and there is no echo cancellation for audio the app did not play.
  • A very short note is read in one pass and can miss things (2 of 3 in my test at 300 words). The small model also sometimes treats a general remark, such as "we should keep notes short", as an action. Both are visible, because every item shows its source.
  • Speech-to-text mistakes carry into summaries. Names it cannot place in the cited lines are marked check, and proofreading first helps, but neither makes the wording right.
  • Quiet-time work waits for twenty seconds of silence, so an open meeting, which is never quiet, gets none until it ends. A speaker-labelling run cannot be interrupted once it has started.
  • A break stops listening and leaves it stopped until you resume; I chose that over resuming for you, but it means forgetting to press Resume loses what you say afterwards.
  • It was built with the help of an AI coding assistant, which wrote and tested a lot of the code under my direction. The design decisions and the testing in my own voice were mine.

FAQ

Does anything leave my computer?

No, with one optional exception. Recognition, the language model and the voice all run locally, and the page is served from your own machine. There is a web-search command, off by default, that sends only a short search query out, through a search service on your own machine. Your notes and your voice never go.

Does it record my meetings?

Only if you switch on Record meeting audio in Settings, and only while a meeting is open. The audio stays on your computer, about 115 MB an hour, and is used to tell the speakers apart afterwards. You can delete it from the meeting's menu, and deleting the meeting deletes its audio. The labels are kept, but no voiceprints.

Does it change my notes while I am away?

No. In quiet time it only prepares things: minutes, speaker labels, proofread suggestions that wait for you to accept them, and summaries kept in a separate layer. Your lines change only when you accept a suggestion or edit them, and the original wording is always kept.

Do I need headphones?

No. Running audio in the browser uses its echo cancellation so speakers work. Headphones are still the safest option in a noisy room.

Can I change the assistant's name?

Yes, in settings or with an environment variable. It is Skywalker by default. Pick a word Whisper already knows, that has three or more syllables and is not a name you dictate (I rejected "Sara" for that reason). Run the included name check script, then try it in the real app, because the script alone misled me.

Can I edit or delete notes?

Yes. Edit a line, delete it, or proofread it with line-by-line review. Original words are kept.

Can I go back to an old note and add to it?

Yes. Make it the active note with the Continue button, by dragging it up, or by saying "continue the supervisor meeting note". Whatever you dictate next is added to it, with a divider showing when you came back.

How do I get my notes out?

Press Export. It starts from what you have ticked, searched for or are looking at. Choose Markdown, plain text, or one file per note in a zip, and then Download, or Copy to paste into another app.

What if it saves something I did not say?

Quiet voices from a TV or another room are ignored and shown dimmed, with a button to keep one if it was really you. The Sound check in Settings shows how well your microphone and room are set up.

Is the code available?

Not publicly yet.


Lessons

1.
Measure before you tune. The mic gain, the wake word and the cough thresholds were all fixed by numbers, not guesses.
2.
Turn-taking is the product. The models are the easy part.
3.
Keep the original. People trust a proofreader that never overwrites.
4.
Test the real room. A synthetic voice and a real one disagreed more than once.
5.
Private by default is a feature. It changed what I was willing to dictate.
6.
Test the real app, not only the script. The name that won the test was heard 3 times in 7 once it ran through the browser. Saving the audio of mistakes let me replay them with different settings and find the fix.
7.
Actions belong in code. A language model will happily say "done" for something it never did.
8.
Make silent failures loud. A microphone that quietly stops is worse than one that says it has stopped.
9.
Check the knob matters before you build the dial. Turning my voice down 18 dB changed nothing Whisper heard, which told me what a tuner could and could not do.
10.
Test with the messiest input you can find. A tidy dictation never showed that a conversation has no pauses, and a long note never scrolled until I opened an hour of one.
11.
Measure at the size you will really use. A summary that found 5 of 8 actions at 300 words found 0 of 8 at 4,500, and nothing on screen said so.
12.
Make a claim carry its evidence. A name the model invented came from my own prompt. The source tag is how I found it, and the check is how the app now catches it.

If you have tried building something like this, I would like to hear which part gave you the most trouble. Leave a comment below.

Built on CachyOS Linux · RTX 4070 SUPER · faster-whisper · SQLite · sherpa-onnx · October and November 2026

Comments