son las 05:39 y 14°C
TLATOL _
BAJO MI CONTEXTO · MI EXPERIENCIA · SIN CORTES · SIN PELOS · EN EL TECLADO ~/tanker · desde 1999
~/p/f8-dictado-voz-local-arch-3-instalacion · PUB 2026-04-30 (hace 5 horas) ~ 4 min de lectura

F8 y a chambear: el script, instalación, y repo para clonar

> El script completo de 49 líneas, la instalación paso a paso en Arch + KDE Wayland, mis stats reales después de varias semanas, y el repo público para clonar. Cierre de la serie de dictado por voz local.

En la parte 2 hablé de las decisiones técnicas y los gotchas. Ahora el cierre: el script entero, cómo replicarlo paso a paso, mis stats reales, y el repo para que lo clones y lo adaptes a tu mundo.

El script completo

#!/bin/bash
# whisper-dictate.sh -- STT dictation toggle using whisper.cpp
# Press once to record, press again to stop, transcribe, and paste.

RECORDING_DIR="/projects/vrecordings"
PIDFILE="/tmp/whisper-dictate.pid"
MODEL="/usr/share/whisper.cpp-model-large-v3-turbo/ggml-large-v3-turbo.bin"
WAVFILE="$RECORDING_DIR/dictation_$(date +%Y%m%d_%H%M%S).wav"

if [ -f "$PIDFILE" ]; then
    # Stop recording
    PID=$(cat "$PIDFILE")
    WAVFILE_SAVED=$(cat /tmp/whisper-dictate-wav)
    kill "$PID" 2>/dev/null
    rm -f "$PIDFILE"

    notify-send -t 2000 "Dictation" "Transcribing..."

    # Transcribe
    TEXT=$(whisper-cli -m "$MODEL" -f "$WAVFILE_SAVED" -l auto --no-timestamps -np 2>/dev/null | sed '/^$/d' | sed 's/^ *//')

    if [ -n "$TEXT" ]; then
        # Copy to clipboard
        echo -n "$TEXT" | wl-copy
        sleep 0.3

        # Detect terminal vs other window
        ACTIVE_CLASS=$(kdotool getactivewindow getwindowclassname 2>/dev/null)
        TERMINALS="kitty|konsole|alacritty|xterm|foot|wezterm|gnome-terminal"

        if echo "$ACTIVE_CLASS" | grep -qiE "$TERMINALS"; then
            ydotool key 29:1 42:1 47:1 47:0 42:0 29:0  # Ctrl+Shift+V
        else
            ydotool key 29:1 47:1 47:0 29:0  # Ctrl+V
        fi
        notify-send -t 3000 "Dictation" "$TEXT"
    else
        notify-send -t 3000 "Dictation" "No speech detected"
    fi
else
    # Start recording
    notify-send -t 2000 "Dictation" "Recording... Press again to stop."
    pw-record --format=s16 --rate=16000 --channels=1 "$WAVFILE" &
    echo $! > "$PIDFILE"
    echo "$WAVFILE" > /tmp/whisper-dictate-wav
fi

49 líneas. Eso es todo.

Los flags importantes de whisper-cli:

  • -l auto: autodetecta idioma (clave para Spanglish).
  • --no-timestamps: no mete [00:00.000 --> 00:05.000] al texto.
  • -np: sin filtros de profanity ni normalización (preserva mi voz literal).

Cómo replicarlo (Arch + KDE Wayland)

# Core packages
sudo pacman -S whisper.cpp ydotool wl-clipboard
yay -S whisper.cpp-model-large-v3-turbo kdotool-bin

# ydotool necesita acceso a uinput
echo 'KERNEL=="uinput", MODE="0660", GROUP="input"' | sudo tee /etc/udev/rules.d/80-uinput.rules
echo "uinput" | sudo tee /etc/modules-load.d/uinput.conf
sudo usermod -aG input $USER

# Reboot pa' que tome los permisos de uinput
sudo reboot

# Despues del reboot
systemctl --user enable --now ydotool

Guardas el script donde quieras (yo lo tengo en ~/scripts/whisper-dictate.sh), le das chmod +x, y luego en KDE:

System Settings, Shortcuts, Custom Shortcuts, Edit, New, Global Shortcut, Command/URL

  • Trigger: F8
  • Action: ruta absoluta al script

Listo. Ya cargas dictado en F8.

Stats personales

Llevo 39 grabaciones acumuladas en /projects/vrecordings/. Latencia típica:

  • Frase corta (5 segundos de audio): ~2 segundos de transcripción.
  • Frase larga (20 segundos): ~5 segundos.
  • Párrafo (1 minuto): ~12-15 segundos.

Eso con RTX 3060 12GB en Vulkan. La GPU pega 60-80% durante la transcripción, idle el resto del tiempo.

Total de espacio en /projects/vrecordings/: 1.6 GB acumulado en unas semanas. Cada wav es entre 300KB y 6MB dependiendo de la duración. Si te incomoda, le pones un cron a borrar grabaciones de más de 30 días.

El repo

El script vive en GitHub para que lo clones, lo modifiques, y reportes bugs si encuentras alguno:

github.com/Sepremex/whisper_dictate_recording

Estructura mínima del repo: el script, README con la guía condensada, LICENSE (MIT), y un install.sh opcional que automatiza la parte de udev + ydotool service.

Cierre

Hoy casi cualquier app que usas para chambear trae su propio dictado integrado. Teams lo tiene. Claude Code recientemente sumó un comando /voice. Cada IDE, cada suite ofimática, cada cliente de mensajería trae su variante. Funcionan, pero todas comparten dos limitaciones:

  1. Viven dentro de la app. Solo dictas si estás parado en esa ventana. Cambias a otra y se acabó: hay que volver a la app que sí lo soporta para dictar la siguiente frase.
  2. Tu voz sale a un servidor. Aunque sea encriptada, aunque sea "anonimizada", tu audio viaja a un tercero para transcribirse. Eso aplica para Teams, para Claude Code, y para cualquier servicio que dependa de la nube.

Mi setup invierte las dos:

  1. Vive en el OS, no en una app. F8 funciona en Konsole, en Kate, en el browser, en Teams si quiero, en el editor que sea. Es un atajo global del sistema, no un feature de aplicación.
  2. Mi voz se queda en mi PC. Los wavs en mi disco, el modelo en mi GPU, cero paquetes saliendo a internet en el pipeline. Lo opuesto de cualquier servicio cloud-based, sin excepciones.

Si te animas a montarlo y se atora algo, escríbeme a hola@tlatol.com o métele issue al repo.

Esta es la última parte de la serie. Si llegaste directo a aquí: parte 1 (la idea) y parte 2 (la parte técnica) explican por qué cada decisión.