DEV Community

Cover image for I don't listen to meetings anymore. My sloth does.
Breno Gomes Cardoso
Breno Gomes Cardoso

Posted on

I don't listen to meetings anymore. My sloth does.

Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady Submission 🦥

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

Taking notes in a meeting is expensive. While you're writing down what someone just said, you're already missing what they're saying now, so you end up doing two things badly. And most transcription and note-taking tools send the audio to someone else's server. In a lot of workplaces, mine included, that alone rules them out.

Durmain fixes that for me. It's a sloth that sleeps in the corner of the screen and listens to the call locally. When the call ends, it writes the minutes: a summary, the decisions, the tasks and who they belong to, and a score for how much the whole thing could have been an email.

And if I'm feeling too lazy to pay attention at all, that's fine too. The sloth wakes up and starts taking notes whenever someone says my name, so I know when I'm being pulled in.

Everything runs on my laptop. No audio and no text ever leave it.

Demo

The whole video was recorded with Wi-Fi off. The voice is a friend reading a fake meeting about a barbecue.

Code

GitHub logo breno-concrete / durmain

A sloth that sleeps in the corner of your screen during calls and wakes up when someone says your name. 100% local: faster-whisper + Ollama.

Durmain sleeping     Durmain taking notes

Durmain

A sloth that sleeps in the corner of your screen during calls and lectures,
wakes up when someone says your name, and writes the minutes when it's over.
Everything runs on your machine. No audio or text ever leaves it.


Why

Some meetings only need you for the thirty seconds when someone asks you something. The rest of the time you're half listening, and that's exactly when your name gets called.

Durmain listens to your computer's audio, transcribes it locally, and stays asleep until your name comes up. Then it wakes up, shows what was just said, and starts taking notes. When the call ends, a local LLM turns the transcript into minutes: a summary, decisions, tasks, every time you were mentioned, and an honest score for "this could have been an email".

Meeting audio is other people's voices and other people's words. It shouldn't go to a third-party…




How I Built It

The open-source AI here is Whisper (open weights, through faster-whisper) for speech-to-text and Qwen2.5 7B (open weights, Apache 2.0) running locally through Ollama for the minutes.

The pipeline is simple:

system audio ─► 5 s blocks ─► faster-whisper + VAD ─► transcript
                                      │                    │
                                      â–¼                    â–¼ when the call ends
                              name detector ─► sloth   Ollama (qwen2.5:7b) ─► minutes
Enter fullscreen mode Exit fullscreen mode
  • Capture: pyaudiowpatch records what the PC is playing (WASAPI loopback), in 5 second blocks.
  • Transcription: faster-whisper, model small, on CPU with int8. It runs on its own thread, with a queue between recording and transcribing, so recording never waits.
  • Name detection: rapidfuzz, word by word, because Whisper almost never writes my name the same way twice.
  • The sloth: a borderless tkinter window, always on top, with 20 animation frames.
  • Minutes: Ollama running qwen2.5:7b, only after the call ends. Never at the same time as the transcription.

That's the plan. Here's what actually happened.

Whisper makes things up when nobody is talking

The first time I paused a video, the transcript said "Legendas pela comunidade Amara.org" ("Subtitles by the Amara.org community"). Whisper learned from subtitled videos, so silence turns into subtitle credits. vad_filter=True wasn't enough on its own. I also drop segments with low confidence and filter a short list of known phantom phrases. After that: zero invented sentences during silence.

Ctrl+C stopped working

WASAPI loopback doesn't deliver any audio while nothing is playing. So stream.read() just sits there, blocked inside C code, and Python can't handle Ctrl+C until it returns. I moved the read to another thread. Ctrl+C worked, but closing the stream with that thread still stuck in read() gave me a segmentation fault. The fix was callback mode: PortAudio calls my function when there's audio, and nobody is ever stuck waiting.

Whisper can't spell my name

In my first scripted test, Whisper wrote "Brenna", "Brena", "Bruno" and "branco". The fuzzy match was fine. It just never got the right word.

Lowering the similarity threshold from 85 to 80 would catch "Bruno". But then every real Bruno in the meeting would wake the sloth, and my test script had Bruno and Brenda in it on purpose. Instead, I passed my name to Whisper as a hotword, which makes it more likely to pick that word when the audio is ambiguous.

Same recording, 20 mentions of my name and 6 decoy sentences: 15/20 became 16/20, still with 0 false alarms. It fixed the misspellings without turning the real Bruno into Breno.

The model copied my example

The prompt for the minutes took more rounds than any piece of code. A 7B model takes everything literally:

  • I put an example task in the prompt. The model listed that exact sentence as something that was said in the meeting.
  • I wrote "if the score is below 5, write 'not applicable'". It gave a 10/10 and wrote "not applicable".
  • I added a list of phrases that usually mean a task. It started marking everything as a task, including a compliment.

What worked: a template with no real-looking examples, no conditional rules, quotes copied from a single line of the transcript, and one rule I like a lot: when in doubt, don't list it. A missing item is better than an invented one.

The model thought I was talking

The early minutes said things like "Breno mentioned that...". But loopback only captures what comes out of the speakers, not my microphone. Every word in the transcript is someone else's. That limitation became a rule in the prompt: the user only listens.

Don't ask the LLM what code can do

I asked the model to list every time my name was mentioned. It found 6 out of 14. The name detector already had all 14, so now that section is built by code and the LLM never touches it. Use the LLM only where you actually need one.

The context window that cuts silently

A 20-minute lecture turned into 5,091 tokens. That's more than Ollama's default context window, and when that happens it doesn't throw an error. It just reads the beginning. Setting num_ctx to 16384 fixed it, but I only found out because I printed the token count.

The GPU crash

Once, right after a session, Ollama failed to load the model on my GPU with a CUDA error. Since the transcript is written to disk line by line during the call, nothing was lost. I ran the minutes script again and it worked.

This is what the CPU looks like during a live session. Every spike is one 5 second block going through Whisper:

CPU usage during transcription

Why Does Open Innovation Matter?

Meeting audio is other people's voices. They agreed to join a meeting, not to have their voice sent to a server I don't control. With open models running locally, that question doesn't even come up.

It also means it works offline (the demo was recorded with Wi-Fi off), it costs nothing per minute, and switching to another model is changing one string.

To be honest about the trade-off: a big closed model would probably do a better job on the minutes. In my test it would likely have caught the task Whisper half cut off, and it wouldn't file a decision as a task. That's what I give up. What I get is that nothing leaves my laptop, and I can read every line of what the tool does with the data. For meetings, I'll take that trade.

My Agent Session

I built this with an AI coding assistant acting as a mentor: it explained concepts and reviewed my code, and wrote some of the glue code (the Ollama call, the overlay) so I could make the deadline.

The Lazy Payoff

This week I used it on a 20-minute public lecture and on a test call with a friend. Writing those minutes by hand would take me 15 minutes; Durmain did it in under a minute.

What Result
Name detection, live call 8/10 mentions, 0 false alarms
Name detection, scripted recording 16/20, 0 false alarms
Alert latency 2.5 s on average (worst case ~7 s)
Minutes 8/10 decisions and tasks captured, 0 invented
20-minute lecture 5,091 tokens, minutes in ~36 s
Silence 0 invented sentences
Resources 583 MB of RAM, CPU spikes to ~40-50% for 1-2 s per block

It's not perfect. Blocks don't overlap, so a word spoken right at the edge of a block can get cut, and that caused most of the missed mentions. The 7B model sometimes puts things in the wrong section. Those are the next things I'd fix.

But for the meetings where I only need to hear my name, the sloth is already doing the listening.

Top comments (0)