Skip to content

About

Fcitx5 voice input addon — PulseAudio/PipeWire capture, Silero VAD, OpenAI-compatible & Volcengine Doubao streaming ASR, AsrSession architecture

Topics

Resources

Stars

14 stars

Watchers

2 watching

Forks

Repository files navigation

Banner

fcitx5-voice-input

Build License Platform Fcitx5 C++20

中文


fcitx5-voice-input is a Fcitx5 addon for voice input. Captures audio via PulseAudio (or PipeWire fallback), detects speech segments with Silero ONNX VAD, and transcribes via OpenAI-compatible API, Volcengine Doubao streaming ASR, or Mistral Realtime streaming transcription.

Features

  • Voice input (OpenAI Whisper API / compatible services, Volcengine Doubao streaming ASR, or Mistral Realtime streaming)
  • Silero ONNX VAD for automatic speech segmentation (no push-to-talk required)
  • Real-time partial transcript update during speech (Volcengine / Mistral Realtime / OpenAI Realtime backends)
  • Queue-based pipeline: Audio Capture → VAD → ASR → EventDispatcher → commit
  • Graphical configuration via fcitx5-configtool
  • Smart delayed stop on window switching

Demo

Usage

1. Installation

AUR (Arch Linux)

yay -S fcitx5-voice-input
# or
paru -S fcitx5-voice-input
# or build manually
git clone https://aur.archlinux.org/fcitx5-voice-input.git
cd fcitx5-voice-input
makepkg -si

Build from source

See Build below.

2. Configuration

After installation, open fcitx5-configtool, find Voice Input in the Input Method list and add it.

Then open the Addon config for VoiceInput:

Main Config

Option Description Default
ActiveBackend ASR backend openai
VADThreshold VAD sensitivity (0-100), higher = less sensitive 20
SilenceThresholdMs Silence duration to end utterance (ms) 800
StartFrames Consecutive speech frames to trigger onset 2
PreRollMs Audio before onset to include (ms) 300
MinSpeechMs Minimum utterance duration (ms) 300
MaxSpeechMs Maximum utterance duration (ms) 30000

Select your backend from the ActiveBackend dropdown, then click the gear button ⚙ to open that backend's config page.

OpenAI Backend (sub-config)

Option Description Default
BaseUrl API base URL https://api.openai.com/v1
ApiKey API Key (required)
Model Model name whisper-1
Language Output language auto (English/中文)
ApiMode API mode: whisper (standard Whisper API), chat (OpenAI-compatible Chat Completions audio, e.g. DashScope/Xiaomi MiMo) or realtime (GPT Realtime streaming transcription) whisper
EnableItn Send DashScope-specific asr_options.enable_itn; recommended off for Xiaomi MiMo (its API only defines language; true was also accepted in testing, but relies on undocumented behavior) true
CommitIntervalMs Periodic commit interval (ms) in realtime mode; keeps emitting partials for long speech with no pauses 5000
LLMEnabled LLM post-processing false
LLMModel Post-processing LLM model (empty)
LLMSystemPrompt Post-processing system prompt (empty)
LLMStream LLM streaming output true
AutoCommit Auto-commit when no LLM true

Set ActiveBackend=openai, click the gear button, and fill in your API Key. Compatible with any OpenAI-format service:

  • OpenAI — https://api.openai.com/v1

  • Groq — https://api.groq.com/openai/v1

  • SiliconFlow — https://api.siliconflow.com/v1

  • Xiaomi MiMo — https://api.xiaomimimo.com/v1

  • Alibaba Cloud DashScope — https://dashscope.aliyuncs.com/compatible-mode/v1

    Chat mode (OpenAI-compatible Chat Completions): DashScope's qwen3-asr-flash and Xiaomi MiMo's mimo-v2.5-asr are batch endpoints that use the Chat Completions API instead of the standard Whisper API: the addon uploads one WAV segment per utterance and gets the transcript back in a single response (no realtime streaming). Set ApiMode=chat for both; for MiMo also set EnableItn=false (its asr_options only defines language; true was also accepted in testing, but relies on undocumented behavior).

    # DashScope
    BaseUrl=https://dashscope.aliyuncs.com/compatible-mode/v1
    ApiKey=your_dashscope_api_key
    Model=qwen3-asr-flash
    ApiMode=chat
    Language=zh
    
    # Xiaomi MiMo
    BaseUrl=https://api.xiaomimimo.com/v1
    ApiKey=your_mimo_api_key
    Model=mimo-v2.5-asr
    ApiMode=chat
    Language=zh
    EnableItn=false
    

    GPT Realtime streaming (optional): Set ApiMode=realtime to transcribe incrementally (partials update the preedit live, final commits on speech end) via the OpenAI Realtime transcription session. With an OpenAI account, use gpt-live-transcribe (recommended, true continuous deltas) or gpt-realtime-whisper (compatible alternative).

    BaseUrl=https://api.openai.com/v1
    ApiKey=your_openai_api_key
    Model=gpt-live-transcribe
    ApiMode=realtime
    Language=zh
    

    Note: Realtime mode requires a WebSocket-capable endpoint, and gpt-live-transcribe / gpt-realtime-whisper need a paid-tier account (Free is not supported). Audio is sent at 24kHz (the addon automatically upsamples the captured 16kHz).

Volcengine Doubao Backend (sub-config)

Set ActiveBackend=volcengine, click the gear button to open the Volcengine config page.

Option Description Default
Endpoint WebSocket endpoint wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_async
AuthMode Auth mode: api_key or app_access_key api_key
ApiKey API Key (new console) (required for api_key mode)
AppKey App Key (legacy console) (required for app_access_key mode)
AccessKey Access Token (legacy console) (required for app_access_key mode)
ResourceId Resource ID volc.seedasr.sauc.duration
ChunkMs Audio chunk size per packet (ms) 200
EnableITN Enable ITN text normalization true
EnablePunc Enable punctuation true
EnableDDC Enable DDC smoothing false
EnableNonstream Enable second-pass recognition true
EndWindowMs Server-side end-of-speech window (ms) 800

Volcengine authentication requires a resource purchased from the Volcengine console. The Resource ID depends on your model and purchase plan:

  • Model 2.0 hourly: volc.seedasr.sauc.duration
  • Model 2.0 concurrency: volc.seedasr.sauc.concurrent
  • Model 1.0 hourly: volc.bigasr.sauc.duration
  • Model 1.0 concurrency: volc.bigasr.sauc.concurrent

Troubleshooting: If recognition fails, check the addon log for X-Tt-Logid and provide it to Volcengine support.

Mistral Realtime Backend (sub-config)

Set ActiveBackend=mistral, click the gear button to open the Mistral config page.

Option Description Default
BaseUrl API base URL https://api.mistral.ai/v1
ApiKey API Key (required)
Model Model name voxtral-mini-transcribe-realtime-2602
CommitIntervalMs Periodic commit interval (ms); keeps emitting partials for long speech 5000
TargetStreamingDelayMs Target streaming delay (ms, 0-1000); higher = lower latency but more aggressive partials 0

This backend uses the Mistral Realtime transcription API over WebSocket. Audio is sent as 16kHz PCM directly (no resampling needed). Partial transcription.text.delta events update the preedit live; the final transcription.done commits on speech end. Connection drops are handled with automatic reconnection keeping the same session.

3. How to Use

  1. Switch to Voice Input IME
  2. Start speaking — VAD automatically detects speech and records
  3. With the Volcengine, Mistral Realtime or OpenAI Realtime backend, partial recognition text appears in the preedit area in real-time as you speak
  4. Stop speaking (default 800ms silence timeout) — final recognition result is committed
  5. Stay in Voice Input mode and continue speaking for consecutive recognition

When switching windows, the plugin delays stop by 200ms. Quick switch-back cancels the stop, avoiding unnecessary restarts.

Build

Dependencies

  • fcitx5 — Input method framework
  • libpulse-simple — PulseAudio capture (preferred)
  • libpipewire-0.3 — PipeWire capture (fallback)
  • jsoncpp — JSON parsing
  • libcurl — HTTP/WebSocket client (>= 7.86.0, required for ASR)
  • zlib — Gzip compression (required for Volcengine backend)
  • onnxruntime — Silero VAD ONNX Runtime

Arch Linux: sudo pacman -S fcitx5 pulseaudio pipewire jsoncpp curl onnxruntime-cpu zlib

Debian/Ubuntu: sudo apt install fcitx5 libpulse-dev libpipewire-0.3-dev libjsoncpp-dev libcurl4-openssl-dev libonnxruntime-dev zlib1g-dev

Build Steps

# Clone and init submodules (for Silero VAD model)
git clone https://github.com/devcxl/fcitx5-voice-input.git
cd fcitx5-voice-input
git submodule update --init --recursive

# Configure
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr

# Build
cmake --build build -j"$(nproc)"

# Install
sudo cmake --install build --prefix /usr

CMake Options

Option Default Description
BUILD_TESTS OFF Build tests
ONNXRUNTIME_ROOT — Custom ONNX Runtime install path

Notes

  • API Key Security: API keys are stored in plain text in ~/.config/fcitx5/conf/voiceinput-openai.conf, voiceinput-volcengine.conf and voiceinput-mistral.conf. Ensure proper file permissions
  • Network Required: OpenAI / Volcengine / Mistral backends require internet. Local ASR can be added via the AsrEngine / AsrSession interfaces
  • Audio Device: The input device is auto-selected at startup (prefers alsa_input.* microphones; Monitor and echo-cancel sources are skipped). Manual device selection is not supported yet
  • VAD Model: The Silero VAD model is distributed via git submodule (third_party/silero-vad/) and copied to the install directory at build time. Run git submodule update --init --recursive before building
  • PipeWire Users: The PulseAudio backend works fine under pipewire-pulse. Native PipeWire is only used as fallback when PulseAudio is completely unavailable
  • Local ASR: Not yet implemented. The codebase provides AsrEngine (session factory) / AsrSession abstract interfaces for future local ASR integration
  • Window Switching: A 200ms delayed stop prevents unnecessary restarts on quick window switches. Long inactivity will stop the pipeline

Architecture Overview

Audio Capture Thread → FrameQueue → VAD Worker → SpeechEventQueue → ASR Dispatcher → AsrSession workers
    → ResultCoordinator (ordering + optional LLM post-processing) → ResultQueue → EventDispatcher → commitString

SpeechEvent types: Begin (speech onset) → Audio (32ms frames, batched to 200ms by Pipeline) → End (silence) / Cancel (too short)

Main thread + capture thread + VAD worker + per-session ASR workers, connected by ThreadSafeQueue. Every utterance is an AsrSession (factory: AsrEngine::StartSession); finished sessions are reaped by SessionReaper with timeout, and concurrent results are delivered in creation order. See ARCHITECTURE.md for details.

License

GNU Lesser General Public License v3.0

About

Fcitx5 voice input addon — PulseAudio/PipeWire capture, Silero VAD, OpenAI-compatible & Volcengine Doubao streaming ASR, AsrSession architecture

Topics

Resources

Stars

14 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages