DEV Community

Cover image for Ofrenda: keeping a family story in their own voice, offline
Dipti Choubey
Dipti Choubey

Posted on

Ofrenda: keeping a family story in their own voice, offline

Hacktoberfest Open-Source AI Challenge: Ghost in the Machine Submission πŸ‘»πŸŒΌ

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

What I Built

An ofrenda is a place where you keep the people you remember. I took that idea and built a small tool for something most families never write down: the stories that only exist in one person's voice.

With Ofrenda, I record someone telling a story, or add a voice memo. It writes down what was said, then makes a short remembrance card: a title, a paragraph about the person, a list of things they loved (foods, songs, places), and one line in their own words. I read it, fix anything that isn't true, and save it. The card goes on a shelf, and the recording sits next to it, so I can press play and hear them again.

That is how I read the theme. The ghost in the machine is a voice that outlasts the moment it was spoken.

Demo

Code

Ofrenda

Keep a family story before it fades. Record someone telling it (or add a voice memo), and Ofrenda writes it down, then turns it into a short remembrance card using only what was said Everything runs on your laptop: Whisper (speech to text) and an open-weight model through Ollama. No account, no API key, no cloud. Stories are saved as plain files (text, JSON and the original audio) in a memories/ folder, so they never depend on a service that might disappear.

Run (Windows)

  1. Install Python 3.11+ (tick Add python.exe to PATH).
  2. Install Ollama, then in PowerShell: ollama pull gemma3:4b
  3. Double-click run.bat. Your browser opens at http://localhost:5003. The first start downloads the voice model (a few hundred MB, needs internet once).

Good to know

  • Ask permission before recording someone.
  • The card may only use words from the story. A quoted line is checked against the…

To run it on Windows: install Python and Ollama, run ollama pull gemma3:4b, then double-click run.bat. The first start downloads the speech model, so it needs internet once.

How I Built It

I wrote the first version with an AI coding assistant (Claude). It is a small Flask server with one page, and two open models that both run on my laptop.

Whisper does the listening. The browser records audio (or I upload a voice memo) and sends it to Flask. faster-whisper runs the small model on the CPU and writes down the speech. I choose the language first (English, Hindi, Bengali or Spanish), or let it work it out. The recording waits aside until I press Save.

Gemma 3 (4B) does the writing, through Ollama. I send the transcript and ask for a JSON answer with four fields: title, remembrance, loved and quote. The temperature is low (0.3) so it stays close to the text.

The part I worried about most is the model making things up. For a memorial, an invented detail is worse than a boring one. I used three guardrails:

  1. The prompt says to use only what is in the transcript, and never to invent names, dates, places, relatives or feelings.
  2. The quote is checked by code. After removing punctuation and capital letters, it has to appear in the transcript. If it doesn't, it is thrown away.
  3. Nothing is saved until I have read the card. The title, the paragraph and the list are all editable.

What this doesn't cover: the paragraph and the list of things they loved are not checked by code. They rely on the prompt and on me reading them.

Plain files, not an app database. Each saved story is a folder in memories/, with a story.json (transcript and card) and the original audio. That folder is in .gitignore, so family stories can't be uploaded to GitHub by accident.

One thing broke. On a fresh install, transcription failed with open() got an unexpected keyword argument 'metadata_errors'. A new version of PyAV, the library faster-whisper uses to open audio, removed an argument that faster-whisper still passes. Pinning av<19 in requirements.txt fixed it.

Limits I know about:

  • Speech recognition mishears names and places, especially in Hindi and Bengali. That is why the transcript is an editable text box before the card is made.
  • The card is written in English. The quote stays in the original language.
  • For a long story, the model reads only the first 7,000 characters, and the page tells you when that happens.

Why Does Open Innovation Matter?

A family's voices and stories are about as private as data gets. Because Whisper and Gemma run on my own laptop, the audio and the transcript never go to anyone's server.

The theme asks about making sure what you build isn't locked inside a service that might disappear. That was the main reason I chose plain files. Everything Ofrenda saves is a JSON file and an audio file that any program can open. If Ofrenda disappeared tomorrow, the stories would still be there, and the models I downloaded would still run.

It also costs nothing to run. I could test a recording again and again without a bill or a limit. The Whisper size, the model and the writing instructions are each one line or paragraph I can change.

A bigger hosted model would probably write a smoother remembrance, and recognise Hindi and Bengali better. For a story like this, I would still choose privacy and plain files.

The Spirit of It

I recorded my aunt telling the story of her first job, for about three
minutes. She didn't want to be recorded at first, so I told her it was
just a test.

When I played it back she was quiet for a moment, then said: "I sound
exactly like my mother."

What surprised me: she corrected the transcript herself, and fixed a
street name I never would have known was wrong.

What the card got wrong: it said she "loved the city", which she never
said. I deleted that line before saving.

I haven't shown the card to anyone yet. But her voice is in a folder
now, and that's the part I'm keeping.

Top comments (0)