• Audio tools for oral history

    I’m interviewing some folks and want to capture and transcribe the audio. I did this last year successfully with the Parrot app and a hand install of Whisper. But it was pretty clunky, I don’t like Parrot. This time around I’m trying new stuff.

    Summary: ASR Voice Recorder to record (on Android) and aTrain to transcribe.

    Audio recording

    ASR Voice Recorder. It’s a modern recorder app, the key thing is it stores files in a place I can find them with other Android apps or USB download. I think the free version is sufficient but I subscribed for $2.50 for a year. I set it up to store things in the Recordings folder. It also is uploading to Google Drive for me. I’m not confident about the microphone gain: there’s a manual setting I’ve left at 0, I’m hoping it auto-adjusts.

    Simple transcribing

    How about a simple text transcript from the audio file?

    Running Whisper locally is an option. ASR also has integration with the OpenAI whisper service, so you can transcribe audio for $0.36 an hour. Unfortunately individual files to analyze are limited to 25 MB. Not sure if ASR is smart enough to chunk the file to work around that when transcribing: ChatGPT thinks it might be but it could be wrong.

    Another option would be to break a big audio file up myself and upload it in chunks to the Whisper API. The problem here is you only want to break in silences, or even better when a speaker switches.

    A third option is to install Whisper and run it locally. I’ve done this twice and it worked OK.

    Diarization

    A simple transcription just gives words. Much better is diarization: the tool also detects who is speaking and annotates the transcript. Whisper does not do this itself. ChatGPT had lots of ideas for me.

    I first tried whisperx, which adds PyAnnote to Whisper to diarize. I couldn’t get it to run: lots of problems with drivers, even if I tried to make it CPU-only. Was dumping core :-( This may be a WSL problem, I didn’t try very hard.

    I had much more luck with aTrain. I installed it via the Windows Store: the 5GB download from their own server didn’t work. Installed easily, no setup required, it’s all preloaded to use my NVidia GPU. It transcribed 2 hours of audio in maybe 20 minutes? The output is pretty good, I imagine this is just Whisper for the transcript. The diarizing looked fairly good but not perfect, lots of cases of several speakers being lumped into one. But it’s still helpful. Just will still need hand editing and review. It’s a nice product, very easy to use.

  • GV LAN down to 100Mbit

    so much depends
    upon

    an ethernet
    cable

    with its delicate
    threads

    and fragile
    connectors


    Something went wrong with my Internet connection on July 3: my Starlink speed tests never got above 80Mbit/s (it should often be 200+). I finally pinned it down to the ethernet on the path to the Starlink being at 100Mbit. These are old fashioned Netgear dumb switches and they are very good about being gigabit and negotiating to slower speeds if necessary.

    I tried replugging the cables. I tried different ports. I even changed the switch on the Starlink end. The connection would start at gigabit then give up and drop to 100Mbit. Feels like a bad cable? But then magically after power cycling the new switch (it had been on for awhile) it started working. I really don’t think it’s the switch’s failure, I’d swapped switches! Maybe it’s a flaky connector and I just got lucky? Or maybe there’s some state kept in the switching network that I reset with the power cycle? Very confused.

    Anyway, need to keep an eye on it. Flaky cables are bad news. This one will be expensive to replace, it’s a long run through an attic. One possibility is mice or heat damaged the cable.

    Some graphs showing the problem

    I don’t really have monitoring of my LAN. But I do have monitoring through two Internet connections at the other end of the flaky link, so I can infer something from them.

    The speed test showing the Starlink degradation to 100Mbit. The last > 100 Mbit is 19:00 on July 3. But speeds are suspiciously slow that morning too, that may have just been a lucky hour. The last normal behavior is July 3 6AM.

    Pings to 8.8.8.8 via Starlink. The packet loss red dots don’t tell a story. But that high latency until July 1 is kinda weird, I have no explanation for it. But there’s no obvious change. I zoomed in on just July 3 but it doesn’t show any problem.

    Pings to 8.8.8.8 via Smarter Broadband, my WISP. This WAN link is a lot less reliable but note this pattern of the minimum latency increasing: that seems like it could be another indicator of the LAN change.

    IPerf 3 tests

    I tried running some tests with iperf3 after being on gigabit for an hour or two. Testing with a server on the OpenWRT router at the other end of the cable. UDP client tests with iperf3 -c 192.168.9.1 -u -b 1G (from my WSL host.)

    With a full gigabit I get 22% packet loss: that’s bad! But that’s with the client sending a gigabit to the server. If I reverse the test with -R I get 0.036% packet loss but the server is only sending 713Mbits/sec. I suspect that’s a CPU limitation of the OpenWRT device. Tests of 700Mbit/sec UDP (sent from client) show 0.5% packet loss. 400Mbits/sec shows 0% packet loss.

    I also did a TCP test and get about 930Mbits/sec over the link in both directions. I take this all as evidence the gigabit link is just fine right now.

  • 8BitDo Ultimate 2C variants and upgrades

    I bought an 8BitDo Ultimate 2C Wireless Controller for Windows PC and Android from Amazon. It can connect either via Bluetooth or a proprietary 2.4GHz USB dongle. It’s mostly worked fine with the 2.4GHz on my PC. I’m not able to pair it with my onn Android TV via Bluetooth, not sure yet what’s wrong. It seems to start pairing, the controller vibrates, then the TV says it can’t pair.

    There is also a 8BitDo Ultimate 2C Bluetooth Controller for Switch and Switch 2 (on Amazon). This is a similar controller but is Bluetooth only, no 2.4GHz. And it only advertises Switch compatibility, nothing else.

    I’m not sure why this is so complicated. PC gaming has been plagued for decades with XInput vs DInput, a lot of controllers have a physical switch to select between the two. Switch apparently has its own Bluetooth HID profile that’s different again. 8BitDo is doing customers no favors by making two incompatible products with very similar names.

    To make matters more confusing, 8BitDo has a firmware updater. But while version 2.50 supports a bunch of controller types it does not support the Windows Ultimate 2C. It does support “Ultimate 2C Bluetooth” though, by which they apparently mean the Switch version. When I run the software and plug my Windows controller in via USB it starts vibrating in a little pattern but there are no update options that work.

    The trick is to use a different program, the 8BitDo Ultimate Software V2. It’s unsigned so Windows gives a scary warning but it runs and updates my controller fine. This software has a bunch of advanced features like macros and button remapping but I’m not sure any work on my 2C.

    8BitDo make excellent hardware, their controllers are great and cheap. But the software situation is not good. I also am frustrated by all these controller modes and incompatibilities but that may not be entirely 8BitDo’s fault.

    BTW, the firmware upgrade didn’t fix my pairing problem with the onn streaming device. The same controller pairs fine with my Pixel phone, so I’m guessing it’s a problem with the onn. The onn does work with the controller with the 2.4GHz USB dongle. Steam Link works great on it!

  • Android phone without a slippery back

    My Pixel 8 is an OK phone. Except it’s impossible to hold it in your hand. So I have to put a case on it, which I hate. Glass backs are a scourge. But companies are starting to be brave and offering alternatives again. I had a productive ChatGPT search about options.

    My conclusion is the Pixel 9a may be the best choice. It has a matte plastic back. This redesign mostly gets dinged in reviews, it’s not very sexy. But if I can hold it in my hand that’s a big bonus. My Pixel 8 is not at all sexy in a big chunky case.

    I’m more interested in Motorola’s new phones. They have a variety of new phones with pleather backs: the Moto G56, the Moto G86, the Edge 60 Pro. But they basically aren’t available in the US. I think because they lack CDMA or otherwise aren’t certified with US carriers. I’m on Verizon, which historically has been a PITA. They do have a couple of phones for the US market. The Moto G56 is called “Moto G” here but doesn’t have an OLED screen. There is an Edge 60. And there’s an Edge 60 Pro for sale in the US that warns us it’s not guaranteed to work.

    Meanwhile I ordered some cheap grip tape. No one makes this stuff in interesting colors!

  • Yuba River average temperature and flow

    I love swimming in the Yuba near Grass Valley. Local wisdom is it’s not safe to swim until July 4, that’s when it’s warm and slow enough to be safe. PG&E controls the flow with a dam but seems to follow a sort of schedule. My notes are that 200 CFS is “calm” flow. I was just there at 450 CFS and it was still pretty sporty. I could have swum across but it wasn’t yet a good idea.

    There’s flow data at Dreamflows and USGS. Also historical data at USGS. So I fired up Claude Code and 30 minutes and $2 later I have a serviceable graph. It’s online here.

    End result: yeah, July 4 is about right.

    Update

    For $0.50 I added a histogram of the flow on July 4. I also added a deploy script for 10 cents. Then I spent another 20 cents making sure it was treating no data differently from zero. There’s 61 years with flow under two hundred: 20 years with flow over that.

    Vibe coding notes

    Another project I could have done myself but didn’t want to spend the time: Claude makes it kind of fun. This went OK at first but got in the weeds.

    Claude’s first instinct was to use Python and matplotlib. Yuck. I asked it to do Javascript and it chose Chart.js. Which was fine for small data but choking on more points, so it suggested switching to uPlot. That seems to get the job done. d3.js would be nice too but is overkill for a static one-off.

    I am very impressed with how Claude understands high level directives like “draw a bunch of individual thin lines for each year to show distribution”. OTOH I don’t quite trust it: I’m afraid to publish this more widely for fear something about its calculations is incorrect. I tried reviewing the code but just can’t bring myself to care enough to bother. It looks right!

    Claude is great when starting de novo but gets slower and buggier with iteration. For instance it mostly converted the code from Chart.js to uPlot just fine. But one thing I wanted was to clamp the Y axis at 2000 CFS. It insisted on keeping the Chart.JS code to do that and wouldn’t update to the uPlot API until I read the docs and told it myself what it needed to do. It also made a bunch of other changes that just didn’t work. I never could get it to make the graph fill the whole width. I know some folks doing agentic coding are also building test suites and telling the agent to not commit until the tests pass, that would have been really helpful here.

    I sure wish I had more confidence that this visualization is actually correct and doesn’t do something stupid like averaging missing data in as if they were zeros. That’d be the same problem with a person doing the coding but I’d trust them more.

  • Claude Code: no login shell for agent

    Claude Code regularly runs “agents”, a fancy word for shell scripts. Unfortunately for some dumb reason they chose to run the agent in a bash login shell, which means it runs the script for all sorts of stuff you only want in an interactive shell. To stop it, I put this guard in my .bash_login.

    if [[ -n “$CLAUDECODE” ]]; then
    echo “Detected Claude Code. Not running login script.”
    return
    fi

    The real problem was I had put cd $HOME in my .bash_login. Not sure why, that probably solved a problem I had 25 years ago. This was confusing the agent something awful, particularly when it was moving files around or dealing with git. It kept doing things in my home directory, potentially catastrophic!

  • Claude Code round 2

    A few months ago I used Claude Code to code a Mastodon thread unroller. I was so happy with the result that I dusted that project off today to use it for something new. The first version had a bunch of stuff hard-coded so I had Claude refactor it to make it a click command line tool with various parameters.

    It worked great. Sample output here. It cost me $4 and took about 90 minutes total, 30 minutes of Claude Code working away.

    Honestly I’m kind of shook by this. Claude Code is just unreasonably good at this kind of programming. Like I said in my first post, this is a highly constrained problem and with relatively minor requirements. I can easily verify the output and that’s all I care about. Still, it’s just so good!

    Along the way it solved some tricky problems with very little input from me.

    • The old download method didn’t work anymore because the posts were so old, so it found and used a different API.
    • It wrote a bunch of docs explaining how everything works. The command line tools have nice help too.
    • Filtered out replies I wrote to other people, to focus just on my main thread.

    That last one is particularly astonishing because the task is so complex and I gave it such vague directions. Here’s its explanation of what it did.

    > the new method for downloading is catching replies to other people. ie, "@wolfger Prost, lah! Legit beer,  fresh." It's OK (but unnecessary) to download them but I dont' want them in the output.
    
    ● You're right! The context API is grabbing the entire conversation thread, including replies from other people. The current code filters by user_id but apparently some replies to others are still getting through.
    
      Let me fix this by adding better filtering to only include posts that are either:
      1. The original post, OR
      2. Direct replies to your own posts (not replies to other people)
    
    Perfect! I've added much better filtering logic. Now the script uses a two-pass approach:
    
      βœ… New Filtering Logic:
    
      Pass 1: Collect all post IDs by the user
    
      Pass 2: Only include posts that are:
    
      1. The original post, OR
      2. Have no reply target (standalone posts), OR
      3. Reply to another post by the same user
    
      This will exclude posts like "@wolfger Prost, lah! Legit beer, fresh." because they reply to someone else's
      post, not to your own posts.
    
      πŸ“ What it does:
    
      - Downloads everything (for completeness)
      - Filters out replies to others during processing
      - Shows debug messages when skipping posts: "Skipping post 123 - reply to someone else (456)"
      - Only includes your actual thread in the final gallery
    
      Now when you run the download, you should see messages like:
      Skipping post 114xyz - reply to someone else (114abc)
      Found 8 posts by the same user in the thread
    
      This gives you a clean thread of just your own connected posts while still preserving all the data for
      reference.
  • Wine cabinet power + temperature

    We bought a wine cabinet with a refrigeration unit to Grass Valley. It’s in our garage. Outside temps fluctuate 50-95, garage fluctuates about 60-80, and the wine cabinet keeps 55-59, well mostly.

    Downside is it’s taking about 2kWh / day to keep it there, double that on hot days. Power costs about $0.50/kWh (I think?) so it’s costing $30-$60 to keep the wine cool in summer months.

    The unit seems to come on for about 15 minutes, using 280W, then off for about 15 minutes. But total time on varies with temperature. When it’s not hot it stays 56-58, but on a hot day it’s varying 55-59.

    Update: 118 kWh for the month of June. That’s roughly $50. Varies about 2x depending on how hot the day is. I’m considering insulating the garage doors.

    Here’s a bunch of graphs for May:

    Outdoor temperature (one month)

    Cabinet Temperature (one hot week)

    Power: month

    Power (hot day)

    Power (a hot afternoon hour)

  • Getting ChatGPT to remember you (May 2025)

    I recently started paying for ChatGPT. Almost entirely for the new memory features where it not only remembers explicitly saved memories (an older feature) but now also incorporates your general chat history too. It’s confusing but I think these features are only available to paying members, at least some of them. Read Simon’s post for a criticism of the chat history feature.

    There’s at least three kinds of persistence available, all under Settings / Personalization.

    “Custom instructions” lets you enter basic text, both about yourself and as ways to pre-load the context window with strings. Some folks use these to introduce custom prompts. The other two toggles are to turn the memory features off or on. You can also click “manage memories” to get a bunch of text nuggets that you can delete if you want.

    In general ChatGPT seems to only put something in “saved memories” if you explicitly tell it to. I’m not 100% sure of this, but if you tell it to remember something it seems to put it on the list. (Update: a friend has evidence it will decide to remember things on its own, without being told to. Also I’ve now seen it decide to remember something itself, telling me “Updated saved memory”)

    Even after I started paying for ChatGPT the fancier memory wasn’t working. It took a few days, then suddenly it started working. I’m guessing they roll out this feature slowly, or maybe only enable it on new paying customers slowly.

    I also primed its memory by exporting all previous conversations into a JSON file, then zipping it and uploading it and telling ChatGPT “I would like you review this log of all our past charts. think really hard about it, go deep and find everything out about me you can from it.” You do have to coax it to work harder on it, the default is a su rface treatment.

    How do you know if it’s retrieving memory? The recommended way is to ask a new chat session “what do you know about me?” If memory is working you get a detailed list of things like “Core Identity” and “Cognitive Style”, like 30 line items (plus more not displayed). Before it was working I got a very quick reply with just 3 bullet items, things I’d explicitly told it in the settings.

    As for what ChatGPT has learned about me, that seems quite personal so I’m not posting it here. As personal as my search history. It all seems roughly right. I have no idea how well this helps tune ChatGPT’s future interactions with me to be more useful, but I’m hopeful.

    I did like when it started flirting with me:

    You think systematically but poetically β€” equally at ease with ffmpeg flags and Whitman’s metaphors

    It’s not wrong, it’s just such a funny way to say it.

    Update: it also tells me that I “Blend irony and sincerity in political and aesthetic judgment” which is basically the central conflict of my life.

  • NPR Morning Edition podcast

    If you want to listen to NPR Morning Edition as a podcast, try this URL.

    Apologies to whoever’s API key that is. But it’s been circulating for six years now so I don’t feel bad using it.

    NPR has a really awkward stance with the Internet. It’s supposed to be for public benefit but then their audio programs are their essential intellectual property, so they keep them locked up. Their NPR One app is just awful. For a long time I was using some third party hack feed, but it recently shut down.

    I’m partly responsible for introducing the use of “API keys” in web services. We used one for the Google SOAP search service, a very early public web service. And we put API keys in the request. But at least in the SOAP XML body, not the URL. Putting them in the URL is just asking for them to be copied around. API keys are a bad idea for other reasons but they are sort of useful for a low security tracking token.