<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on maciejb.me</title><link>http://maciejb.me/posts/</link><description>Recent content in Posts on maciejb.me</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Fri, 05 Jun 2026 22:57:00 +0200</lastBuildDate><atom:link href="http://maciejb.me/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Gemma 4 12B and Polish audio input</title><link>http://maciejb.me/posts/gemma4-12b-asr-polish/</link><pubDate>Fri, 05 Jun 2026 22:57:00 +0200</pubDate><guid>http://maciejb.me/posts/gemma4-12b-asr-polish/</guid><description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; Polish is not supported as audio input for Gemma 4 12B&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Google has released Gemma 4 12B, a new variant of its open-weight LLM family.
It&amp;rsquo;s a medium-sized model advertised to run locally on laptop-sized devices using just 16 GB of VRAM.
It also features native audio input.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Audio&lt;/strong&gt;: We simplified audio processing even further. We removed the audio encoder entirely and projected the raw audio signal into the same dimensional space as text tokens.&lt;/em&gt;&lt;/p&gt;</description><content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR</strong> Polish is not supported as audio input for Gemma 4 12B</p>
</blockquote>
<p>Google has released Gemma 4 12B, a new variant of its open-weight LLM family.
It&rsquo;s a medium-sized model advertised to run locally on laptop-sized devices using just 16 GB of VRAM.
It also features native audio input.</p>
<blockquote>
<p><em><strong>Audio</strong>: We simplified audio processing even further. We removed the audio encoder entirely and projected the raw audio signal into the same dimensional space as text tokens.</em></p>
</blockquote>
<p>Source: <a href="https://blog.google/innovation-and-ai/technology/developers-tools/introducing-gemma-4-12b/">Gemma 4 12B Announcement</a></p>
<p>I decided to dig deeper into the model&rsquo;s automatic speech recognition capabilities.
I wanted to know if it supports Polish, my native tongue.</p>
<p>First, I checked the model card:</p>
<blockquote>
<p><em>Automatic speech recognition (ASR) and speech-to-translated-text translation across multiple languages.</em></p>
</blockquote>
<p>Source: <a href="https://ai.google.dev/gemma/docs/core/model_card_4">Gemma 4 model card</a></p>
<p><em>Multiple languages</em>, aha! That&rsquo;s not very revealing. Without that information, the only way forward is to check myself.</p>
<p>I started by upgrading to <a href="https://github.com/ollama/ollama/releases/tag/v0.30.5">Ollama 0.30.5</a>, the first version
advertised to work with Gemma 4 12B.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ollama pull gemma4:12b
</span></span><span class="line"><span class="cl">ollama ps
</span></span><span class="line"><span class="cl"><span class="c1"># Prints:</span>
</span></span><span class="line"><span class="cl"><span class="c1"># NAME          ID              SIZE      PROCESSOR    CONTEXT    UNTIL</span>
</span></span><span class="line"><span class="cl"><span class="c1"># gemma4:12b    4eb23ef187e2    8.2 GB    100% GPU     131072     4 minutes from now</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Let&#39;s do a text smoke test first</span>
</span></span><span class="line"><span class="cl">&gt; curl http://127.0.0.1:11434/api/chat <span class="se">\
</span></span></span><span class="line"><span class="cl">      -H <span class="s1">&#39;Content-Type: application/json&#39;</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">      -d <span class="s1">&#39;{
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#34;model&#34;: &#34;gemma4:12b&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#34;stream&#34;: false,
</span></span></span><span class="line"><span class="cl"><span class="s1">    &#34;messages&#34;: [
</span></span></span><span class="line"><span class="cl"><span class="s1">      {
</span></span></span><span class="line"><span class="cl"><span class="s1">        &#34;role&#34;: &#34;user&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">        &#34;content&#34;: &#34;Hello!&#34;
</span></span></span><span class="line"><span class="cl"><span class="s1">      }
</span></span></span><span class="line"><span class="cl"><span class="s1">    ]
</span></span></span><span class="line"><span class="cl"><span class="s1">  }&#39;</span> -s <span class="p">|</span> jq .message.content
</span></span><span class="line"><span class="cl"><span class="c1"># &gt; &#34;Hello! How can I help you today?&#34;</span>
</span></span></code></pre></div><p>Text generation works; let&rsquo;s move to voice.</p>
<p>For voice, I like to use <a href="https://github.com/steipete/sag/">sag</a>, which is a CLI for ElevenLabs inspired by macOS&rsquo;s <code>say</code>.</p>
<p>Before checking Polish, let&rsquo;s smoke-test ASR with English audio.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">ELEVENLABS_API_KEY</span><span class="o">=</span><span class="s2">&#34;...&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Listen to the clip before generating a version for the ASR</span>
</span></span><span class="line"><span class="cl">sag speak <span class="s2">&#34;The quick brown fox jumps over the lazy dog.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ... and let&#39;s get the version for the model:</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sag speak --no-play --no-stream <span class="se">\
</span></span></span><span class="line"><span class="cl">    -o /tmp/gemma4-12b-asr-polish/english-smoke.mp3 <span class="se">\
</span></span></span><span class="line"><span class="cl">    <span class="s2">&#34;The quick brown fox jumps over the lazy dog.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Convert it to a format Gemma4 expects</span>
</span></span><span class="line"><span class="cl">ffmpeg -y -hide_banner  <span class="se">\
</span></span></span><span class="line"><span class="cl">    -i /tmp/gemma4-12b-asr-polish/english-smoke.mp3 <span class="se">\
</span></span></span><span class="line"><span class="cl">    -ar <span class="m">16000</span> -ac <span class="m">1</span> <span class="se">\
</span></span></span><span class="line"><span class="cl">    /tmp/gemma4-12b-asr-polish/english-smoke-16k-mono.wav
</span></span></code></pre></div><p>Time to send it to the model:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">AUDIO_B64</span><span class="o">=</span><span class="k">$(</span>base64 -i /tmp/gemma4-12b-asr-polish/english-smoke-16k-mono.wav <span class="p">|</span> tr -d <span class="s1">&#39;\n&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">jq -n --arg audio <span class="s2">&#34;</span><span class="nv">$AUDIO_B64</span><span class="s2">&#34;</span> <span class="s1">&#39;{
</span></span></span><span class="line"><span class="cl"><span class="s1">  model: &#34;gemma4:12b&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">  stream: false,
</span></span></span><span class="line"><span class="cl"><span class="s1">  messages: [{
</span></span></span><span class="line"><span class="cl"><span class="s1">    role: &#34;user&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">    content: &#34;Listen to the attached audio and write the exact English words spoken. Do not translate. Return only the English transcript.&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">    images: [$audio]
</span></span></span><span class="line"><span class="cl"><span class="s1">  }]
</span></span></span><span class="line"><span class="cl"><span class="s1">}&#39;</span> <span class="p">|</span> curl -sS http://127.0.0.1:11434/api/chat -H <span class="s1">&#39;Content-Type: application/json&#39;</span> -d @- <span class="p">|</span> jq <span class="s1">&#39;.message.content&#39;</span>
</span></span></code></pre></div><p>It printed the expected <em>The quick brown fox jumps over the lazy dog.</em>.</p>
<p>Notice we&rsquo;re using the <code>images</code> field to send the base64-encoded audio. As of the time of writing this,
this is the only way to use multimodal inputs with Ollama. Neither <code>audio</code> nor <code>input_audio</code> is supported.</p>
<p>Now it&rsquo;s time for the final test. This time, the fixture is the famous opening lines by Adam Mickiewicz:</p>
<blockquote>
<p>Litwo, Ojczyzno moja! ty jesteś jak zdrowie;<br>
Ile cię trzeba cenić, ten tylko się dowie,<br>
Kto cię stracił. Dziś piękność twą w całej ozdobie<br>
Widzę i opisuję, bo tęsknię po tobie.</p>
</blockquote>
<p><code>sag</code> produces a ~15-second clip out of it.</p>
<p>I had to disable <em>thinking</em> for this clip because the model could not stop after several minutes
on my M2 MacBook Air.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">AUDIO_B64</span><span class="o">=</span><span class="k">$(</span>base64 -i /tmp/gemma4-12b-asr-polish/litwo-ojczyzno-moja-16k-mono.wav <span class="p">|</span> tr -d <span class="s1">&#39;\n&#39;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">jq -n --arg audio <span class="s2">&#34;</span><span class="nv">$AUDIO_B64</span><span class="s2">&#34;</span> <span class="s1">&#39;{
</span></span></span><span class="line"><span class="cl"><span class="s1">  model: &#34;gemma4:12b&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">  stream: false,
</span></span></span><span class="line"><span class="cl"><span class="s1">  think: false,
</span></span></span><span class="line"><span class="cl"><span class="s1">  options: {
</span></span></span><span class="line"><span class="cl"><span class="s1">    num_ctx: 8192,
</span></span></span><span class="line"><span class="cl"><span class="s1">    num_predict: 1024
</span></span></span><span class="line"><span class="cl"><span class="s1">  },
</span></span></span><span class="line"><span class="cl"><span class="s1">  messages: [{
</span></span></span><span class="line"><span class="cl"><span class="s1">    role: &#34;user&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">    content: &#34;Listen to the attached audio and write the exact Polish words spoken. Do not translate. Preserve Polish spelling, diacritics, capitalization, and punctuation. Return only the Polish transcript.&#34;,
</span></span></span><span class="line"><span class="cl"><span class="s1">    images: [$audio]
</span></span></span><span class="line"><span class="cl"><span class="s1">  }]
</span></span></span><span class="line"><span class="cl"><span class="s1">}&#39;</span> <span class="p">|</span> curl -sS http://127.0.0.1:11434/api/chat -H <span class="s1">&#39;Content-Type: application/json&#39;</span> -d @- <span class="p">|</span> jq -r .message.content
</span></span></code></pre></div><p>Prints:</p>
<blockquote>
<p>Litfoj czs no ma, ty jests jak zdrowie, i lecz trzeba cenić, ten tylko se dowje kto cz straciu. Dżisz pęngnost dwonw czalej ozdobie widze i opisuje. Bo tenskne potens nie potolisz.</p>
</blockquote>
<p>:sadpanda:</p>
<p>I&rsquo;m not even going to compute standard ASR metrics like WER/CER here because the output is plainly unusable.</p>
<p>Let me just leave <a href="https://github.com/openai/whisper">Whisper</a> here for comparison:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">&gt; whisper /tmp/gemma4-12b-asr-polish/litwo-ojczyzno-moja-16k-mono.wav <span class="se">\
</span></span></span><span class="line"><span class="cl">    --model large-v3-turbo <span class="se">\
</span></span></span><span class="line"><span class="cl">    --language Polish <span class="se">\
</span></span></span><span class="line"><span class="cl">    --task transcribe <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output_format txt <span class="se">\
</span></span></span><span class="line"><span class="cl">    --output_dir /tmp/gemma4-12b-asr-polish <span class="se">\
</span></span></span><span class="line"><span class="cl">    2&gt;/dev/null
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>00:00.000 --&gt; 00:03.660<span class="o">]</span>  Litwo, ojczyzno moja, Ty jesteś jak zdrowie.
</span></span><span class="line"><span class="cl"><span class="o">[</span>00:04.340 --&gt; 00:08.240<span class="o">]</span>  Ile Cię trzeba cenić, ten tylko się dowie, kto Cię stracił.
</span></span><span class="line"><span class="cl"><span class="o">[</span>00:09.480 --&gt; 00:14.960<span class="o">]</span>  Dziś piękność Twą w całej ozdobie widzę i opisuję, bo tęsknię po Tobie.
</span></span></code></pre></div>]]></content:encoded></item><item><title>Greenish warbler</title><link>http://maciejb.me/posts/greenish-warbler/</link><pubDate>Wed, 27 May 2026 16:17:00 +0200</pubDate><guid>http://maciejb.me/posts/greenish-warbler/</guid><description>I am told, via an ornithologist I know, that my &lt;a href="http://maciejb.me/posts/birdnet-go-setup/"&gt;BirdNET-Go setup&lt;/a&gt; may have recorded what could be the first Greenish Warbler (&lt;em&gt;Phylloscopus trochiloides&lt;/em&gt;) detection in Poland this year.</description><content:encoded><![CDATA[<p>I am told, via an ornithologist I know, that my <a href="http://maciejb.me/posts/birdnet-go-setup/">BirdNET-Go setup</a> may have recorded what could be the first Greenish Warbler (<em>Phylloscopus trochiloides</em>) detection in Poland this year.</p>
<p>If you want to hear what it sounds like, there is a <a href="https://youtu.be/0UREs7tVvko">recording published on YouTube</a>.</p>
<figure>
    <img loading="lazy" src="spectrogram-xl-labeled.png"
         alt="Spectrogram from the BirdNET-Go clip that triggered the Greenish Warbler detection."/> <figcaption>
            <p>Spectrogram from the BirdNET-Go clip that triggered the Greenish Warbler detection.</p>
        </figcaption>
</figure>

]]></content:encoded></item><item><title>Math, Diagrams, Charts, Sketches, …</title><link>http://maciejb.me/posts/math-diagrams-charts-sketches/</link><pubDate>Mon, 25 May 2026 10:30:00 +0200</pubDate><guid>http://maciejb.me/posts/math-diagrams-charts-sketches/</guid><description>&lt;p&gt;I want to make posts more capable. Some ideas are easier to explain with an
equation, a diagram, or a chart.&lt;/p&gt;
&lt;p&gt;The baseline post is still Markdown. The blog still uses Hugo.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I want to make posts more capable. Some ideas are easier to explain with an
equation, a diagram, or a chart.</p>
<p>The baseline post is still Markdown. The blog still uses Hugo.</p>
<h2 id="math">Math</h2>
<p>KaTeX is now enabled for posts that need formulas embedded. A useful test is
the scaled dot-product attention equation from the Transformer paper:</p>
<p>$$
\operatorname{Attention}(Q, K, V) =
\operatorname{softmax}\left(\frac{QK^\mathsf{T}}{\sqrt{d_k}}\right)V
$$</p>
<h2 id="diagrams">Diagrams</h2>
<p>Mermaid is now enabled and rendered.</p>
<pre class="mermaid">
flowchart LR
  tokens[Tokens] --> embed[Embeddings]
  embed --> attention[Self-attention]
  attention --> norm1[Add + norm]
  norm1 --> ffn[Feed-forward]
  ffn --> norm2[Add + norm]
  norm2 --> output[Output states]
</pre>

<h2 id="charts">Charts</h2>
<p>I will be using Chart.js to render charts; that should work better than screenshots because the charts can reflow across screen sizes and support tooltips.</p>
<figure>
  <p><strong>BirdNET detections</strong></p>
  <p>Bar chart of seven completed Warsaw-local days ending 2026-05-24: May 18: 619, May 19: 468, May 20: 641, May 21: 926, May 22: 590, May 23: 967, May 24: 909. Peak: May 23 with 967 detections.</p>
</figure>
<p>The BirdNET detections are sourced from <a href="http://maciejb.me/posts/birdnet-go-setup/">my BirdNET setup</a>.</p>
<h2 id="sketches">Sketches</h2>
<p>p5.js can be used for small interactive sketches.</p>
<figure>
  <p><strong>p5.js orbit sketch</strong></p>
  <p>Animated p5.js sketch showing a blue point orbiting an orange center point.</p>
</figure>
<h2 id="typst-to-svg">Typst to SVG</h2>
<p>I have enabled Typst to SVG experimentally. I will figure out if I need it going
forward.</p>
<figure class="feature-typst-figure">
  <img loading="lazy" src="http://maciejb.me/images/hugo-feature-stack.svg" alt="A small diagram showing front matter, shortcodes, and static SVG output">
  <figcaption><p>Static SVG output is just an image to the browser. No per-page JavaScript flag is needed.</p></figcaption>
</figure>

<h2 id="implementation-details">Implementation details</h2>
<p>The post opts into browser-side features from front matter:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">features</span><span class="p">]</span>
</span></span><span class="line"><span class="cl"><span class="nx">math</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="nx">mermaid</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="nx">chartjs</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="nx">p5</span> <span class="p">=</span> <span class="kc">true</span>
</span></span></code></pre></div><p>The theme partials read those flags and only load the libraries the page asks
for. The body uses shortcodes for the parts that need structure. Ordinary posts
do not load KaTeX, Mermaid, Chart.js, or p5.js by default.</p>
<p>Typst is handled differently. I keep the <code>.typ</code> source in <code>assets/typst/</code>,
compile it to SVG, and reference the generated file from <code>static/images/</code>. That
makes the figure version-controlled without adding runtime JavaScript to the
page.</p>
<p>The idea was inspired by Maxime Guerreiro&rsquo;s post about his agent workflow:
<a href="https://punkeel.com/posts/agent-workflow/">How I use agents to write this blog</a>.</p>]]></content:encoded></item><item><title>My BirdNET-Go setup</title><link>http://maciejb.me/posts/birdnet-go-setup/</link><pubDate>Sat, 18 Apr 2026 20:00:00 +0200</pubDate><guid>http://maciejb.me/posts/birdnet-go-setup/</guid><description>A few people have asked me to document my DIY BirdNET setup. Here it is. The software stack I use is based on BirdNET-Go, which is a bird vocalization classifier and dashboard. Under the hood it uses BirdNET-Analyzer and the BirdNET 2.4 model.</description><content:encoded><![CDATA[<p>A few people have asked me to document my DIY BirdNET setup. Here it is.</p>
<p>The software stack I use is based on <a href="https://github.com/tphakala/birdnet-go">BirdNET-Go</a>, which is a bird vocalization classifier and dashboard. Under the hood it uses <a href="https://birdnet.cornell.edu/analyzer/">BirdNET-Analyzer</a> and the BirdNET 2.4 model. In broad strokes, BirdNET splits <code>48 kHz</code> audio into three-second segments, converts them into log-mel spectrograms, and runs a convolutional neural network over those images to estimate species probabilities, with location and date used as extra context for filtering the results.</p>
<p>My setup is split across two Raspberry Pis. The outdoor Raspberry Pi 3 A+ captures audio from a Clippy EM272Z1 microphone through a <a href="https://www.ugreen.pl/pl/products/inne-produkty/karty-dzwiekowe/zewnetrzna-karta-dzwiekowa-usb-ugreen-15cm-czarny-us205-143396">Ugreen US205</a> USB sound card and publishes a <code>48 kHz</code> mono LPCM stream over <a href="https://en.wikipedia.org/wiki/Real-Time_Streaming_Protocol">RTSP</a>. An indoor Raspberry Pi 4 runs BirdNET-Go, pulls that stream over RTSP/TCP, exports clips, and serves the web dashboard.</p>
<h2 id="hardware">Hardware</h2>
<p>Before building a BirdNET station yourself, I strongly recommend reading the <a href="https://github.com/tphakala/birdnet-go/blob/main/doc/wiki/hardware.md">BirdNET-Go hardware recommendations from the project authors</a>. I followed that page when choosing the microphone, and it is a much better starting point than guessing your way through Raspberry Pi models, sound cards, and microphones.</p>
<p>The outdoor half lives in an <code>IP54</code> weatherproof box on the balcony, powered through an <code>IP44</code> extension lead. It is still a practical build rather than a polished one: the Raspberry Pi, power, sensor, and cable routing all share the same enclosure, because getting a reliable microphone outdoors mattered more to me than making the first version elegant.</p>
<figure>
    <img loading="lazy" src="enclosure-on-balcony.jpg"
         alt="The current outdoor enclosure on the balcony."/> <figcaption>
            <p>The current outdoor enclosure on the balcony.</p>
        </figcaption>
</figure>

<p>The microphone itself is mounted under the balcony ceiling and connected back to the enclosure with a <code>3.5 mm</code> extension cable. This is still a temporary setup, with electrical tape standing in for a more elegant fixture, because part of the exercise was simply to test microphone placement before committing to something cleaner. There is still work to be done there.</p>
<p>The windshield matters a lot. It improves outdoor audio quality tremendously. Pro tip: use double-sided adhesive tape to attach it to the microphone. The first time I skipped that, the wind carried it off.</p>
<figure>
    <img loading="lazy" src="microphone-placement.jpg"
         alt="The microphone mounted under the balcony ceiling."/> <figcaption>
            <p>The microphone mounted under the balcony ceiling.</p>
        </figcaption>
</figure>

<p>Inside the box, besides the Raspberry Pi and audio hardware, I also keep a Govee H5179 thermo-hygrometer. I already had it at home and it had very little use before, so it became enclosure telemetry. One of the obvious risks of keeping electronics outdoors is condensation, so I export the Govee readings into a local <a href="https://prometheus.io/">Prometheus</a> and watch the relative humidity metrics in my local <a href="https://grafana.com/">Grafana</a> instead of guessing.</p>
<p>I also keep about <code>300 g</code> of silica gel sachets inside. In practice they pretty much saturate after one heavier rainfall, so I treat them as temporary help rather than a long-term answer. A more permanent fix would be a small heating element, but I decided against that because I did not want to run extra wiring into the enclosure.</p>
<p>Another upgrade I want to make before summer is better cooling for the outdoor Raspberry Pi. Right now it only has the small heatsink that came in the <a href="https://botland.store/raspberry-pi-3a/13834-set-of-raspberry-pi-3a-wifi-original-case-power-supply-5v-25a-5903351241526.html">Botland kit</a>, but my early estimates suggest I may not be able to keep the CPU below <code>70 °C</code> in summer without switching to a larger heatsink or adding a fan. On the Raspberry Pi 3 A+, that is also the maximum configurable <a href="https://www.raspberrypi.com/documentation/computers/config_txt.html"><code>temp_soft_limit</code></a>, beyond which the CPU is throttled down to <code>1.2 GHz</code>.</p>
<figure>
    <img loading="lazy" src="inside-enclosure.jpg"
         alt="Inside the box: Raspberry Pi, Govee sensor and silica gel."/> <figcaption>
            <p>Inside the box: Raspberry Pi, Govee sensor and silica gel.</p>
        </figcaption>
</figure>

<h2 id="bird-detections">Bird Detections</h2>
<p>The variety is what it is. This is still a microphone on a ninth-floor balcony in a densely populated area, so I am not expecting spectacular species diversity. Even so, I think the results are great for this location, especially around dawn.</p>
<figure>
    <img loading="lazy" src="birdnet-go-dashboard.png"
         alt="BirdNET-Go daily activity view from a typical April day."/> <figcaption>
            <p>BirdNET-Go daily activity view from a typical April day.</p>
        </figcaption>
</figure>

<h2 id="bill-of-materials">Bill of Materials</h2>
<p>This is the BOM for the outdoor side. The Raspberry Pi 4 that runs BirdNET-Go also runs all my home automation.</p>
<ul>
<li>Raspberry Pi 3 A+ kit: <a href="https://botland.store/raspberry-pi-3a/13834-set-of-raspberry-pi-3a-wifi-original-case-power-supply-5v-25a-5903351241526.html">Set of Raspberry Pi 3A+, original case and 5 V / 2.5 A power supply</a></li>
<li>Outdoor extension lead: <a href="https://www.amazon.pl/dp/B0C7GZHK82">Brennenstuhl outdoor extension lead</a></li>
<li>Enclosure / outdoor cable box: <a href="https://www.amazon.pl/dp/B0DQPZCL6F">Outdoor cable box, IP54</a></li>
<li><code>3.5 mm</code> audio extension cable: <a href="https://www.amazon.pl/dp/B0827VWPNZ">UGREEN <code>3.5 mm</code> extension cable</a></li>
<li>USB sound card: <a href="https://www.ugreen.pl/pl/products/inne-produkty/karty-dzwiekowe/zewnetrzna-karta-dzwiekowa-usb-ugreen-15cm-czarny-us205-143396">Ugreen US205</a></li>
<li>Microphone: <a href="https://www.veldshop.nl/en/clippy-em272z1-mono-microphone.html">Clippy EM272Z1 Mono Microphone</a></li>
<li>Silica gel sachets: <a href="https://wisedry.net/products/wisedry-silica-gel-sachets">Wisedry silica gel sachets</a></li>
<li>Thermo-hygrometer: <a href="https://us.govee.com/products/wi-fi-temperature-humidity-sensor">Govee Wi-Fi Thermo-Hygrometer, model H5179</a></li>
</ul>
<p>At current prices, that outdoor-side BOM comes to roughly <code>739 PLN</code> before shipping.</p>
]]></content:encoded></item><item><title>xz attack</title><link>http://maciejb.me/posts/xz/</link><pubDate>Wed, 03 Apr 2024 11:51:37 +0200</pubDate><guid>http://maciejb.me/posts/xz/</guid><description>This is a collection of links and quotes from the many articles published on the topic of the recent XZ Utils attack. There is no original research here.</description><content:encoded><![CDATA[<p>This is a collection of links and quotes from the many articles
published on the topic of the recent <a href="https://en.wikipedia.org/wiki/XZ_Utils">XZ Utils</a> attack.
There is no original research here.</p>
<ul>
<li><a href="https://www.openwall.com/lists/oss-security/2024/03/29/4">Andres Freund&rsquo;s email</a> to Openwall mail list,
that publicly disclosed the vulnerability</li>
<li><a href="https://gynvael.coldwind.pl/?lang=en&amp;id=782">Bash Obfuscation Explained</a> from gynvael.coldwind.pl</li>
<li>two pieces by Russ Cox: <a href="https://research.swtch.com/xz-timeline">Timeline of the xz open source attack</a> and
<a href="https://research.swtch.com/xz-script">The xz attack shell script</a></li>
<li>Filippo Valsorda&rsquo;s <a href="https://bsky.app/profile/filippo.abyssdomain.expert/post/3kowjkx2njy2b">thread on Bluesky</a></li>
</ul>
<p>I found Russ Cox&rsquo;s <a href="https://research.swtch.com/xz-timeline">Timeline of the xz open source attack</a> to be particularly
informative on the social / human aspects of the operation. Here is an excerpt:</p>
<blockquote>
<p>2022-05-27: Jigar Kumar sends pressure email to patch thread. “Over 1 month and no closer to being merged. Not a surprise.”</p>
<p>2022-06-07: Jigar Kumar sends pressure email to Java thread. “Progress will not happen until there is new maintainer. XZ for C has sparse commit log too. Dennis you are better off waiting until new maintainer happens or fork yourself. Submitting patches here has no purpose these days. The current maintainer lost interest or doesn&rsquo;t care to maintain anymore. It is sad to see for a repo like this.”</p>
</blockquote>
<p>There were also pieces published explaining the problem to the general audience
like <a href="https://www.economist.com/science-and-technology/2024/04/02/a-stealth-attack-came-close-to-compromising-the-worlds-computers">this one by The Economist</a>.</p>
]]></content:encoded></item></channel></rss>