<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Darren</title>
    <description>The latest articles on DEV Community by Darren (@darrenmakes).</description>
    <link>https://dev.to/darrenmakes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4169877%2Fe9bf43ec-49a6-444b-bcc5-00fcd259201b.png</url>
      <title>DEV Community: Darren</title>
      <link>https://dev.to/darrenmakes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/darrenmakes"/>
    <language>en</language>
    <item>
      <title>fieldmemo: keep the phone in your pocket, talk to it, get a field journal at home</title>
      <dc:creator>Darren</dc:creator>
      <pubDate>Wed, 07 Oct 2026 22:06:52 +0000</pubDate>
      <link>https://dev.to/darrenmakes/fieldmemo-keep-the-phone-in-your-pocket-talk-to-it-get-a-field-journal-at-home-32bo</link>
      <guid>https://dev.to/darrenmakes/fieldmemo-keep-the-phone-in-your-pocket-talk-to-it-get-a-field-journal-at-home-32bo</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI disclosure:&lt;/strong&gt; I built this with an AI coding agent, which wrote most of the code and the first draft of this post. I read it, watched the demo and approved the text. Everything below about what worked and what broke comes from the build log in the repo, not from memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;fieldmemo&lt;/strong&gt; turns the voice memos you record on a walk into a field journal, on your own machine, with no internet.&lt;/p&gt;

&lt;p&gt;The idea is that the phone stays in your pocket. When you see something, you press record and say it: "two buzzards circling over the ridge", "the stile after the second field has a broken step, report it to the council", "come back for the blackberries next September". No app to open, no form to fill in, no typing with cold fingers. Then you put the phone away and keep walking.&lt;/p&gt;

&lt;p&gt;At home you run one command on the folder of memos, plus the GPX track from your phone or watch if you recorded one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fieldmemo walks/2026-10-08/memos &lt;span class="nt"&gt;--gpx&lt;/span&gt; walks/2026-10-08/track.gpx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and get three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;journal.md&lt;/code&gt;: what you saw, what you heard but didn't see, path problems with a map link for each, a to-do list, and a timeline with every memo's transcript.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;walk.geojson&lt;/code&gt;: the track and a pin for each memo, for QGIS, uMap or geojson.io.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notes.csv&lt;/code&gt;: one row per sighting, hazard or to-do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's for walkers, birders and ramblers who want a record of a walk without spending the walk looking at a screen, and for anyone who reports broken stiles and flooded paths to their council and wants the time and position written down for them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvd3gvm73be3zcnehbgd0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvd3gvm73be3zcnehbgd0.gif" alt="fieldmemo processing the sample walk in a terminal" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the full run on the sample walk in the repo: seven memos in, journal out, about 48 seconds on an 8-core CPU with no GPU. This is the "At a glance" block it wrote, with only the map links shortened:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**Seen:** buzzard, fly agaric x12, blackberry

**Heard (not seen):** green woodpecker

**Path problems**
- 10:02 ground: soaked from last night (map)
- 10:02 path: by the first gate is basically a pond (map)

**To do**
- 10:41 stile: note to self the style after the second field has a broken step; report it to the council rights of way team when i get home (map)
- 11:37 tub: come back with a tub in early September next year (map)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;One thing to be upfront about: &lt;strong&gt;the sample walk is synthetic.&lt;/strong&gt; The memos are spoken by Piper, an open-source text-to-speech engine, with brown noise mixed in to imitate wind, and the GPX track is a made-up loop. I did that so anyone can rerun the exact demo, but a TTS voice is much cleaner than a real person on a windy hill, so treat the accuracy here as a best case.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/darrenmakes" rel="noopener noreferrer"&gt;
        darrenmakes
      &lt;/a&gt; / &lt;a href="https://github.com/darrenmakes/fieldmemo" rel="noopener noreferrer"&gt;
        fieldmemo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Voice memos + GPX track -&amp;gt; offline field journal, map layer and CSV (Whisper + Gemma 4 via Ollama). AI-assisted build.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;fieldmemo&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Talk on the trail, read it at home.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep your phone in your pocket on a walk. When you see something, press record and say it
"two buzzards over the ridge", "stile after the second field is broken", "come back for the
blackberries next September". Afterwards, point &lt;code&gt;fieldmemo&lt;/code&gt; at the folder of voice memos (and the
GPX track from your watch or phone, if you have one) and it writes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;journal.md&lt;/code&gt;: a readable field journal. What you saw, what you heard, path problems with map links, a to-do list, and a timeline with every memo's transcript.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;walk.geojson&lt;/code&gt;: your track plus a pin per memo. Opens in QGIS, uMap, geojson.io or any GIS tool.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notes.csv&lt;/code&gt;: one row per sighting, hazard or to-do, ready for a spreadsheet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything runs on your own machine: speech-to-text with &lt;a href="https://github.com/openai/whisper" rel="noopener noreferrer"&gt;Whisper&lt;/a&gt;
(through &lt;a href="https://github.com/SYSTRAN/faster-whisper" rel="noopener noreferrer"&gt;faster-whisper&lt;/a&gt;) and note-taking with
Google's open-weight &lt;a href="https://ai.google.dev/gemma" rel="nofollow noopener noreferrer"&gt;Gemma&lt;/a&gt; served by &lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt;…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/darrenmakes/fieldmemo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Python, MIT licensed, about 640 lines plus tests. The repo includes the sample walk, the script that generates it, and &lt;code&gt;docs/BUILD-LOG.md&lt;/code&gt;, which records every problem below as it happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Four open pieces do the work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Whisper&lt;/strong&gt; (&lt;code&gt;small.en&lt;/code&gt;) through &lt;strong&gt;faster-whisper&lt;/strong&gt;, for speech-to-text on the CPU.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 E2B&lt;/strong&gt;, Google's open-weight model, in a 4-bit GGUF (3.1 GB), served by &lt;strong&gt;Ollama&lt;/strong&gt;. It reads each transcript and returns JSON in a fixed schema: &lt;code&gt;seen&lt;/code&gt;, &lt;code&gt;heard&lt;/code&gt;, &lt;code&gt;hazard&lt;/code&gt;, &lt;code&gt;todo&lt;/code&gt; or &lt;code&gt;note&lt;/code&gt;, each with a subject, a count and a few words of detail.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;GPX track&lt;/strong&gt; for position, and plain Python for timing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting part was everything that went wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whisper heard "buzzers".&lt;/strong&gt; On the first pass &lt;code&gt;base.en&lt;/code&gt; turned buzzards into "buzzers", fly agaric into "fly are gariconder", the council rights of way team into the "cancel rights of Wei Team", and a green woodpecker into a "green whoop cat". Whisper takes an &lt;code&gt;initial_prompt&lt;/code&gt;, so fieldmemo passes in a glossary of about 55 countryside words (birds, fungi, stiles, kissing gates, bridleways). That fixed all four. It's a plain text file you can edit for wherever you walk. The test is flattering, because those words are in the glossary and the voice is synthetic, but the effect was immediate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Whisper heard "You" in the wind.&lt;/strong&gt; One sample memo is nine seconds of wind and nobody talking, the kind of recording you make by accident in a pocket. Without help, Whisper transcribed it as "You". Turning on its voice-activity filter made it return nothing, and the journal now lists that memo as "no speech, skipped" instead of inventing a note.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The small model made things up.&lt;/strong&gt; I started with Gemma 3 1B because it fits in about 1.2 GB of RAM. It labelled a woodpecker "seen" when the memo says "didn't see it though", turned "two buzzards, maybe three, they keep dropping behind the trees" into buzzards plus &lt;em&gt;three trees&lt;/em&gt;, and in one run added "fly agaric: a small, pale mushroom growing on a stone" to the car-park memo, which doesn't mention a single fungus. My guess is that it picked "fly agaric" up from the examples in my own prompt.&lt;/p&gt;

&lt;p&gt;Gemma 4 E2B got the kinds right on the same memos: heard vs seen, the flooded path as a hazard, the blackberries as a to-do. It needs about 3 GB of RAM and takes 4 to 8 seconds a memo on the CPU, so it's the default, and Gemma 3 1B is a flag away for smaller machines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So every answer gets checked.&lt;/strong&gt; A small model will invent things sooner or later, so fieldmemo doesn't trust the JSON. Every item's subject has to be made of words that are actually in the transcript, and a count has to be said ("two", "a dozen", "12"). Anything that fails is struck through in the journal with the reason, not quietly deleted. That's what caught the invented mushroom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then the check rejected a correct answer.&lt;/strong&gt; Whisper wrote "the &lt;em&gt;style&lt;/em&gt; after the second field". Gemma 4 read that as "stile", which is right, and my new check threw it out because "stile" isn't in the transcript. The fix: a word that isn't in the transcript is allowed only if it's in your glossary &lt;em&gt;and&lt;/em&gt; the transcript has a word within two letters of it. The journal shows it as &lt;code&gt;corrected: heard "style", read as "stile"&lt;/code&gt;, so you can see the model's fix and decide whether you agree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time zones.&lt;/strong&gt; Android recorders put the local time in the file name (&lt;code&gt;Recording_20261008_101940.m4a&lt;/code&gt;). An iPhone export is called &lt;code&gt;New Recording 4.m4a&lt;/code&gt; and keeps its time in a UTC metadata tag. GPX is always UTC. Get one of those wrong and every pin slides along the track by an hour. Run the sample with the wrong zone and the iPhone memo jumps to the top of the timeline, and the last two memos land "27 min after the track ends" and "53 min after the track ends". fieldmemo can't spot an hour's error that still lands somewhere on the track, but it won't guess beyond the track: a memo outside the track, or in a GPS gap longer than five minutes, gets no position rather than a wrong one, and you get a warning that points at &lt;code&gt;--tz&lt;/code&gt; and &lt;code&gt;--clock-offset&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smaller snags:&lt;/strong&gt; &lt;code&gt;ollama pull&lt;/code&gt; was blocked by the network I built on, so I downloaded the GGUF from Hugging Face and imported it with a one-line Modelfile, which the README now documents. faster-whisper 1.2.1 crashed with the newest PyAV (&lt;code&gt;unexpected keyword argument 'metadata_errors'&lt;/code&gt;), so fieldmemo decodes audio with the &lt;code&gt;ffmpeg&lt;/code&gt; binary instead. As a bonus, it now reads anything ffmpeg can.&lt;/p&gt;

&lt;p&gt;There are eight unit tests covering timing, interpolation and the grounding check, and the whole pipeline runs on CPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Look at what fieldmemo handles: a timestamped trace of where you walk, and recordings of your voice. That's a record of where you live, when you're out, and what you sound like. With open weights running locally, none of it goes anywhere. There's no account, no API key and no server I'd have to trust. Once the models are downloaded, nothing touches the network.&lt;/p&gt;

&lt;p&gt;It also costs nothing to run. The sample walk took about 48 seconds of CPU, with no per-minute transcription bill and no per-token bill for the notes.&lt;/p&gt;

&lt;p&gt;The bigger difference showed up while building it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I could swap the model in one flag.&lt;/strong&gt; Comparing Gemma 3 1B with Gemma 4 E2B on the same seven memos took minutes, and seeing the small model's mistakes side by side is why the grounding check exists. With the weights on disk, the choice comes down to how much RAM your machine has, not which plan you're on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I could steer the speech model.&lt;/strong&gt; The glossary works because a local Whisper lets you set its prompt. Someone walking in the Cairngorms can add "ptarmigan" and "bothy" and get better transcripts the same day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The results stay put.&lt;/strong&gt; The weights in the repo's instructions are fixed files. Run the sample next month and you should get the same answers I got, give or take small numerical differences between machines, so the README and the build log stay true. A hosted model can change underneath you without notice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I didn't benchmark a closed API against this, so I won't claim the open stack is more accurate. What I can say is that for a tool built around your location and your voice, local and open is the version I'd actually want to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;This was built with an AI coding agent. I don't have a DevRelay export, but &lt;a href="https://github.com/darrenmakes/fieldmemo/blob/main/docs/BUILD-LOG.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/BUILD-LOG.md&lt;/code&gt;&lt;/a&gt; in the repo is the step-by-step record of the session: what was tried, what broke, and what changed as a result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt;: Gemma 4 E2B runs locally through Ollama and does the core job of turning each transcript into structured field notes. The repo compares it with Gemma 3 1B on the same memos, and it's the default.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
