Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Omavoice

Version License: MIT Arch Linux GTK4 + libadwaita whisper.cpp On device

A voice recorder for Omarchy that writes the transcript while you talk.

Pick a microphone, a playing app, or the system output. Press the red button.
Watch the words land as you speak. Stop, and there is an audio file in ~/Recordings
with a .txt of the same name beside it. Nothing ever leaves the machine.


Omavoice recording with live transcript
Recording. Live captions arrive every few seconds, the meter shows what the input hears.
Omavoice idle with recent recordings
Ready. Input, format, optional title, and the recent takes with play, copy, open, rename, trash.

Recording saved notification
Every save posts a notification. Click it to open the folder.


✨ What it does

🎙️ Any input

Microphones, every app that is currently playing audio, and the system output monitor. Choose a browser tab's stream and nothing else on the system ends up in the file. The list refreshes itself as apps start and stop.

📝 Transcript as you go

Live captions from a warm whisper-server, toggleable with one switch. Every chunk clears a Silero voice activity check first, so a pause stays a pause instead of becoming invented text. When you stop, the whole take is transcribed again and the sidecar is replaced with the accurate version.

💾 Five formats

Opus, MP3, M4A/AAC, FLAC, WAV. Audio is captured losslessly and encoded on stop, so the format never touches the transcript. Opus at 48 kbps is the default and a one hour talk is about 20 MB.

⏯️ Pause, level, silence

Pause and resume without stitching. A live level meter, and a banner within seconds if the chosen input goes quiet, before you lose a whole take to a muted mic.

🏷️ Titles and tidy files

2026-09-05_14-32-10-Weekly-sync.opus next to 2026-09-05_14-32-10-Weekly-sync.txt. Rename or trash from the app and both files move together.

⌨️ Hotkey friendly

omavoice --toggle starts a take, or stops the one in progress, from any keybinding. Media players are paused for mic takes and left alone for app captures.

🚀 Install

On Arch or Omarchy:

git clone https://github.com/nixfred/omavoice.git
cd omavoice
makepkg -si

Omavoice then shows up in the Omarchy menu: press Super+Space and type its name.

Everything it needs is in the official repositories:

Dependency Why
python-gobject gtk4 libadwaita The window
pipewire-audio pipewire-pulse libpulse Capture and input enumeration
ffmpeg Resampling and encoding
whisper-cpp ggml-cpu Speech recognition, on the CPU, on this machine

To run straight from a checkout without installing:

python -m omavoice

🧠 Models

Omavoice looks for whisper.cpp ggml-*.bin models in ~/.local/share/omavoice/models and, if you use Voxtype, in ~/.local/share/voxtype/models. With no model present, open Preferences and download one.

Model Size Use it for
base.en 142 MB Live captions on a laptop CPU. The default choice.
small.en 466 MB A stronger final pass. Set it as the final transcript model.
medium.en 1.5 GB Final pass when accuracy matters more than waiting.
silero-v5.1.2 1 MB Voice activity detection. Fetched automatically, and required for live captions.

From the shell:

scripts/download-model.sh small.en

⌨️ Global hotkey

omavoice --toggle starts a recording, or stops the one in progress, in the running instance. In Omarchy add a binding to ~/.config/hypr/bindings.lua:

o.bind("SUPER SHIFT, R", "exec", "omavoice --toggle", "Toggle voice recording")

Inside the window Ctrl+R does the same, Ctrl+, opens Preferences.


⚙️ How it works

flowchart LR
    subgraph Input
        MIC[🎙️ Microphone]
        APP[🌐 App stream]
        MON[🔊 System output]
    end
    MIC & APP & MON --> PW[pw-record<br/>raw 48 kHz PCM]
    PW --> MASTER[(master.raw)]
    PW -. every few seconds .-> CUT[cut at the<br/>quietest point]
    CUT --> RS[ffmpeg → 16 kHz]
    RS --> WS[whisper-server<br/>model stays loaded]
    WS --> LIVE[📝 Live transcript]
    MASTER -- on stop --> ENC[ffmpeg encode]
    ENC --> AUDIO[🎵 2026-09-05_14-32-10.opus]
    MASTER -- on stop --> CLI[whisper-cli + VAD]
    CLI --> TXT[📄 2026-09-05_14-32-10.txt]
Loading
  1. Capture. pw-record streams raw 48 kHz mono PCM into a master file under ~/Recordings/.omavoice-tmp/. Pausing drops incoming blocks, so resume needs no stitching, and a crash leaves the raw audio intact. Microphones are targeted by node name. A sink monitor or a single application's stream is captured with stream.capture.sink = true, which is how PipeWire isolates one app's audio. Explicit targets carry node.dont-fallback and node.dont-reconnect, so a stream that vanishes ends the take with an error instead of quietly recording something else.
  2. Live captions. Every few seconds the newest audio is cut at its quietest point and resampled by ffmpeg. Before whisper sees it, the chunk is put to the Silero voice activity detector, and it is only sent on if there is real speech in it. This matters more than it sounds: handed audio with no voice in it, whisper does not return nothing, it returns fluent invented text. Loudness alone cannot tell the difference, because room tone, music and keystrokes all clear a volume threshold. The chunk is sent with no prompt. Carrying the previous chunk forward as context makes whisper replay that text verbatim over a pause, and makes it delete real words at a boundary it mistakes for a repeat. Live captions refuse to start without the detector rather than run unguarded.
  3. Finish. ffmpeg encodes the master into the chosen format, the live text is written as a provisional transcript, and whisper-cli produces the final transcript in the background with Silero voice activity detection. The app holds itself alive until that is done, even if you close the window.

Settings live in ~/.config/omavoice/config.json. The whisper server log is in ~/.cache/omavoice/whisper-server.log.


🧪 Development

python -m unittest discover -s tests

The PKGBUILD runs the test suite during the build. Pure logic (PCM analysis, chunk cut points, naming, source parsing, config validation, transcript rendering) is covered by unit tests. The recorder, encoder, and whisper integration are exercised by headless end-to-end runs against real PipeWire and whisper.cpp.


🙏 Built on

whisper.cpp by Georgi Gerganov and contributors. PipeWire and WirePlumber. GTK and libadwaita. Omarchy by DHH and the community.

📄 License

MIT

About

Voice recorder with live whisper.cpp transcription for Omarchy (GTK4, PipeWire)

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages