# 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
