# Resolve the canonical real binary that /usr/bin/voxtype dispatches to, # regardless of whether /usr/bin/voxtype is a symlink (CPU variant) or a # wrapper script (GPU/ONNX variant whose binary lives next to companion # .so files). Echoes the real path or empty string if not present. _resolve_active_binary() { if [ -L /usr/bin/voxtype ]; then readlink -f /usr/bin/voxtype elif [ -f /usr/bin/voxtype ]; then # Wrapper script — extract the `exec /path` line. sed -n 's/^exec \([^ ]*\).*/\1/p' /usr/bin/voxtype | head -1 fi } # Install /usr/bin/voxtype dispatching to $1 (a path under /usr/lib/voxtype/). # Uses a thin shell wrapper when $1 lives in a GPU subdirectory next to its # companion ONNX Runtime provider .so files (cuda-12/, cuda-13/, migraphx/). # Without the wrapper, ORT's argv[0]-based provider lookup hits /usr/bin/ # which doesn't have the .so files and silently falls back to CPU. The # wrapper `exec`s the real path so argv[0] becomes the canonical location # and ORT finds the .so files alongside. _install_active_binary() { local target="$1" rm -f /usr/bin/voxtype local target_dir target_dir=$(dirname "$target") local subdir="${target_dir##*/}" case "$subdir" in cuda-12|cuda-13|migraphx) local migraphx_env="" if [ "$subdir" = "migraphx" ]; then # MIGraphX needs a writeable model-cache directory or its # runtime fails to save compiled graphs and inference # errors out. Default to $XDG_CACHE_HOME/voxtype/migraphx, # honoring user override. migraphx_env=': "${ORT_MIGRAPHX_MODEL_CACHE_PATH:=${XDG_CACHE_HOME:-$HOME/.cache}/voxtype/migraphx}"\nmkdir -p "$ORT_MIGRAPHX_MODEL_CACHE_PATH"\nexport ORT_MIGRAPHX_MODEL_CACHE_PATH\n' fi { printf '#!/bin/sh\n' printf '# voxtype dispatch wrapper.\n' printf '# Execs the GPU/ONNX binary by canonical path so ORT'\''s argv[0]\n' printf '# based provider .so lookup resolves to the right subdirectory.\n' printf '# Managed by `voxtype setup onnx --enable` and the AUR package'\''s\n' printf '# post_install / post_upgrade hooks; do not edit by hand.\n' printf '%b' "$migraphx_env" printf 'exec %s "$@"\n' "$target" } > /usr/bin/voxtype chmod 755 /usr/bin/voxtype ;; *) ln -sf "$target" /usr/bin/voxtype ;; esac } _set_default_backend() { # Set the default CPU backend based on CPU capabilities if grep -q avx512f /proc/cpuinfo 2>/dev/null; then _install_active_binary /usr/lib/voxtype/voxtype-avx512 echo "avx512" else _install_active_binary /usr/lib/voxtype/voxtype-avx2 echo "avx2" fi } _preserve_or_set_backend() { # Restore saved backend from pre_upgrade, or set default local saved="/tmp/.voxtype-backend-upgrade" if [ -f "$saved" ]; then target=$(cat "$saved") rm -f "$saved" # Compatibility map for 0.6.x → 0.7.x binary renames. Users who # had an ONNX engine selected on 0.6.x would otherwise fall back # to CPU Whisper after upgrade because the old binary names no # longer exist; the map preserves engine intent across the rename. case "$target" in */voxtype-parakeet-avx2) target="/usr/lib/voxtype/voxtype-onnx-avx2" ;; */voxtype-parakeet-avx512) target="/usr/lib/voxtype/voxtype-onnx-avx512" ;; */voxtype-onnx-rocm) target="/usr/lib/voxtype/migraphx/voxtype-onnx-migraphx" ;; */voxtype-onnx-cuda) # 0.7.0 split CUDA into 12/13. Pick the variant matching # the host's libcudart soname; fall back to cuda-13 if # neither is detected (modern default). local cuda_major cuda_major=$(_detect_cuda_major 2>/dev/null) if [ -z "$cuda_major" ]; then cuda_major=13 fi target="/usr/lib/voxtype/cuda-${cuda_major}/voxtype-onnx-cuda-${cuda_major}" ;; esac if [ -f "$target" ]; then _install_active_binary "$target" # Strip the /usr/lib/voxtype/[/]voxtype- prefix for the echo local short=${target##*/voxtype-} echo "${short%/*}" return fi fi # No saved state or target gone — set default _set_default_backend } # Detect the host's CUDA runtime major version by inspecting libcudart's SONAME. # Echoes 12, 13, or empty string if no CUDA runtime found. Used to point the # unversioned voxtype-onnx-cuda symlink at the matching variant — cu12 binary # needs libcudart.so.12, cu13 needs libcudart.so.13. Mismatched pairings # register the EP, then fail at first dlopen and silently fall back to CPU. _detect_cuda_major() { local lib for lib in libcudart.so.13 libcudart.so.12; do if /sbin/ldconfig -p 2>/dev/null | grep -q "\b$lib\b"; then echo "${lib##*.so.}" return fi done # Fallback: probe well-known paths if [ -e /usr/lib/libcudart.so.13 ] || [ -e /opt/cuda/lib64/libcudart.so.13 ]; then echo "13" elif [ -e /usr/lib/libcudart.so.12 ] || [ -e /opt/cuda/lib64/libcudart.so.12 ]; then echo "12" fi } _set_onnx_cuda_symlink() { # Point /usr/lib/voxtype/voxtype-onnx-cuda at the variant matching the # host's CUDA runtime. If no CUDA is installed, leave the unversioned # symlink dangling — users running `voxtype setup gpu --enable` later # will set it up after installing CUDA. local cuda_major target cuda_major=$(_detect_cuda_major) case "$cuda_major" in 13) target="cuda-13/voxtype-onnx-cuda-13" ;; 12) target="cuda-12/voxtype-onnx-cuda-12" ;; *) # No CUDA detected. Prefer cu13 if both binaries are present # (rolling-distro default); fall back to cu12 if only that exists. if [ -f /usr/lib/voxtype/cuda-13/voxtype-onnx-cuda-13 ]; then target="cuda-13/voxtype-onnx-cuda-13" elif [ -f /usr/lib/voxtype/cuda-12/voxtype-onnx-cuda-12 ]; then target="cuda-12/voxtype-onnx-cuda-12" else return fi ;; esac if [ -f "/usr/lib/voxtype/$target" ]; then ln -sf "$target" /usr/lib/voxtype/voxtype-onnx-cuda echo "$cuda_major" fi } _detect_gpu() { # Detect GPU for acceleration recommendation GPU_DETECTED="" GPU_VENDOR="" if [ -d /dev/dri ]; then if ls /dev/dri/renderD* >/dev/null 2>&1; then if command -v lspci >/dev/null 2>&1; then GPU_INFO=$(lspci 2>/dev/null | grep -i 'vga\|3d\|display' | head -1 | sed 's/.*: //') if [ -n "$GPU_INFO" ]; then GPU_DETECTED="$GPU_INFO" case "$GPU_INFO" in *NVIDIA*|*GeForce*|*RTX*|*GTX*) GPU_VENDOR="nvidia" ;; *AMD*|*Radeon*) GPU_VENDOR="amd" ;; *Intel*) GPU_VENDOR="intel" ;; esac fi fi if [ -z "$GPU_DETECTED" ]; then GPU_DETECTED="GPU detected (install pciutils for details)" fi fi fi if [ -n "$GPU_DETECTED" ]; then echo "" echo " GPU detected: $GPU_DETECTED" echo "" echo " For GPU acceleration, run:" echo " sudo voxtype setup gpu --enable" echo "" if [ "$GPU_VENDOR" = "nvidia" ]; then local cuda_major cuda_major=$(_detect_cuda_major) if [ "$cuda_major" = "13" ]; then echo " CUDA 13 runtime detected — voxtype-onnx-cuda points to cuda-13 binary" elif [ "$cuda_major" = "12" ]; then echo " CUDA 12 runtime detected — voxtype-onnx-cuda points to cuda-12 binary" else echo " Whisper: requires vulkan-icd-loader" echo " ONNX engines: requires cuda (CUDA 13) or cuda12.6 (CUDA 12) package" fi elif [ "$GPU_VENDOR" = "amd" ]; then echo " Whisper: requires vulkan-icd-loader" echo " ONNX engines: requires rocm-hip-runtime (AMD GPU EP is MIGraphX as of v0.7.0)" else echo " Requires: vulkan-icd-loader package" fi fi } post_install() { echo "" echo "==> Voxtype Post-installation Steps:" echo "" CPU_VARIANT=$(_set_default_backend) echo " CPU backend: $CPU_VARIANT (using voxtype-$CPU_VARIANT)" CUDA_PICK=$(_set_onnx_cuda_symlink) if [ -n "$CUDA_PICK" ]; then echo " CUDA runtime: $CUDA_PICK detected, voxtype-onnx-cuda → cuda-$CUDA_PICK variant" fi _detect_gpu echo "" echo " 1. Add your user to the 'input' group:" echo " sudo usermod -aG input \$USER" echo "" echo " 2. Log out and back in for group changes to take effect" echo "" echo " 3. Download a model:" echo " voxtype setup model" echo "" echo " 4. Start voxtype:" echo " systemctl --user enable --now voxtype" echo "" echo " Optional: Switch to an ONNX engine (Parakeet, SenseVoice, etc.):" echo " voxtype setup onnx --enable" echo "" } pre_upgrade() { # Save the current backend's canonical real path so post_upgrade can # re-install /usr/bin/voxtype pointing at the same binary. Handles # both the legacy symlink form (CPU variants, pre-0.7) and the # wrapper-script form (GPU/ONNX variants from 0.7+ that need argv[0] # to canonicalize for ORT's provider .so lookup). local target target=$(_resolve_active_binary) if [ -n "$target" ]; then echo "$target" > /tmp/.voxtype-backend-upgrade fi } post_upgrade() { echo "" echo "==> Voxtype upgraded to 0.7.5" echo "" BACKEND=$(_preserve_or_set_backend) echo " Backend: $BACKEND (using voxtype-$BACKEND)" # Re-pick the CUDA variant on every upgrade in case the host's CUDA # runtime changed (e.g., user upgraded from CUDA 12 to CUDA 13). CUDA_PICK=$(_set_onnx_cuda_symlink) if [ -n "$CUDA_PICK" ]; then echo " CUDA runtime: $CUDA_PICK detected, voxtype-onnx-cuda → cuda-$CUDA_PICK variant" fi echo "" echo " What's new in v0.7.5:" echo " * Quickshell OSD frontend ships in the package." echo " Opt in via [osd] frontend = \"quickshell\" in config.toml." echo " Brings a QML-native waveform, engine picker, and meeting" echo " controls. Install the 'quickshell' optdep to enable." echo " * Soniox cloud streaming backend for low-latency dictation" echo " (#411). Configure with [soniox] api_key and stream = true." echo " * Meeting mode: source diarization, audio-capture fixes," echo " per-meeting --diarization flag, tunable ECAPA threshold" echo " (#341, #418, #420)." echo " * Streaming Parakeet validator accepts bobNight model" echo " naming, closing the v0.7.4 known issue." echo " * Per-language XKB variants for eitype (#424); dotool" echo " daemon fast path (#410); wl-copy fallback under X11 (#346)." echo " * Release signing migrated to a dedicated CI primary key" echo " 9CCF7915... cross-signed by the offline maintainer key" echo " E79F5BAF... Both fingerprints are in validpgpkeys, so" echo " yay/makepkg auto-fetches the new key on first upgrade" echo " without any manual gpg --recv-keys step (closes #437)." echo "" echo " Known issue: the Quickshell overlay captures pointer events" echo " across the whole screen (#440). The default [osd] frontend =" echo " \"gtk4\" is unaffected; Quickshell remains opt-in. v0.7.6 will fix." echo "" echo " Restart the daemon to apply updates:" echo " systemctl --user restart voxtype" echo "" echo " Full release notes:" echo " https://github.com/peteonrails/voxtype/releases/tag/v0.7.5" echo "" } post_remove() { rm -f /usr/bin/voxtype rm -f /usr/lib/voxtype/voxtype-onnx-cuda }