Hold a key, speak, and the words are typed
Super+D holds the microphone open, releasing it transcribes on the GPU and types the result wherever the cursor is. Roughly 150ms for a normal utterance once the model is resident, measured rather than hoped for. Getting there meant discarding two approaches. Fedora 44 cannot install any GPU-capable Whisper for Python -- openai-whisper needs a numba that needs an llvmlite that does not exist for 3.14, and faster-whisper needs a ctranslate2 nobody packaged. The whisper-cpp package IS built with HIP but ships libraries with no binary and no bindings, and hand-writing ctypes for a large by-value struct is a segfault waiting for a version bump. So a container, as suggested. Vulkan rather than ROCm, and upstream's image rather than one built here. ROCm is seven gigabytes and serves AMD alone; Vulkan compute runs on the AMD, Intel and NVIDIA machines this config is used on, in a twentieth of the space. The Vulkan tag already contains whisper-server, so there is no Containerfile to keep working -- an earlier draft of this commit had one, and it was strictly worse. Two bugs found by using it rather than by reading it. Whisper describes silence as the literal text "[BLANK_AUDIO]", and the first working version pasted that string into the clipboard; a transcription that is nothing but such markers is now discarded. And the server answers with a line per segment, which typed into a window is an Enter press -- sending the half-written message, submitting the form. Whitespace is collapsed to one line. Neither the image nor the model is installed by ./install. Together they are over two gigabytes that want the network, and Settings offers both as one action instead. Nothing starts at login either: whisper-server holds the model from the moment it starts, so the first press of the key is what brings it up. The contract pins both text bugs, that the server stays on loopback, and that it does not start at login. Reverting the [BLANK_AUDIO] guard did not fail it at first -- the check was still correct, it had simply stopped being called -- so it now checks the call site too. Claude-Session: https://claude.ai/code/session_01Q84axqUE5inJhf5Jz9CFy1
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
# Dictation's speech-to-text server, as a Quadlet.
|
||||
#
|
||||
# Quadlet rather than a hand-written unit wrapping `podman run`: systemd
|
||||
# generates the unit from this at boot, so there is one description of the
|
||||
# container rather than a unit and a command line drifting apart.
|
||||
#
|
||||
# Upstream's own Vulkan image, not one built here. whisper.cpp publishes it, it
|
||||
# already contains whisper-server, and it is maintained by the people who write
|
||||
# the thing -- a Containerfile in this repository would be a compile step on
|
||||
# every machine and a build to keep working, in exchange for nothing.
|
||||
#
|
||||
# Vulkan rather than ROCm, which is the reason this tag and not another. ROCm's
|
||||
# runtime is seven gigabytes and serves AMD alone; Vulkan compute runs on AMD,
|
||||
# Intel and NVIDIA through whatever Mesa driver a machine already has. These
|
||||
# machines are a mix of all three, and this image works on every one of them.
|
||||
#
|
||||
# Deliberately no [Install] section. whisper-server loads the model when it
|
||||
# starts and holds it, so a container started at login costs half a gigabyte of
|
||||
# memory in every session where nobody dictates. panama-dictate starts it on the
|
||||
# first press of the key, and it stays up for the rest of the session.
|
||||
|
||||
[Unit]
|
||||
Description=Panama dictation speech-to-text server
|
||||
Documentation=https://github.com/ggml-org/whisper.cpp
|
||||
|
||||
[Container]
|
||||
Image=ghcr.io/ggml-org/whisper.cpp:main-vulkan
|
||||
|
||||
# The image's own entrypoint is a shell; the server is what is wanted.
|
||||
Entrypoint=/app/build/bin/whisper-server
|
||||
Exec=--host 0.0.0.0 --port 8791 --model /models/ggml-small.bin --inference-path /inference
|
||||
|
||||
# The whole directory rather than a renderD node: the number differs between
|
||||
# machines, and this file is meant to be identical on all of them.
|
||||
AddDevice=/dev/dri
|
||||
|
||||
# The model is host state -- fetched once, kept across image updates, and shared
|
||||
# with nothing else. Read-only because the server never writes to it, and :z
|
||||
# relabels for SELinux, which is enforcing on Fedora.
|
||||
Volume=%h/.local/share/panama/whisper:/models:ro,z
|
||||
|
||||
# Loopback only. This transcribes whatever it is sent, with no authentication,
|
||||
# and has no business being reachable from the network.
|
||||
PublishPort=127.0.0.1:8791:8791
|
||||
|
||||
NoNewPrivileges=true
|
||||
|
||||
[Service]
|
||||
# Loading the model takes a few seconds on a cold start; systemd should wait for
|
||||
# it rather than give up, and should bring the server back if it dies mid-session.
|
||||
TimeoutStartSec=180
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
Reference in New Issue
Block a user