Skip to content

Settings

acarteron edited this page Jun 11, 2026 · 5 revisions

Client Settings

Voicetastic Desktop keeps a small set of client-side, persisted preferences behind a centralised SettingsApi. The same store backs every front-end:

  • GUISettings tab in voicetastic-gui.
  • CLIvoicetastic-cli settings {list, get, set, reset}.
  • Android bridgeSettingsApi exposed through UniFFI.

None of these values are shipped over the air. They live in a TOML file at $XDG_CONFIG_HOME/voicetastic/config.toml (typically ~/.config/voicetastic/config.toml) on desktop, and in the app's per-app data directory on Android.


CLI usage

# Show every key, current value, default, accepted range/variants
voicetastic-cli settings list

# Read one key (machine-friendly: no trailing newline)
voicetastic-cli settings get voice.codec

# Write one key (same string format as `list` displays)
voicetastic-cli settings set voice.codec amrnb
voicetastic-cli settings set voice.amrnb_mode 7

# Reset one key, or all keys, to the default
voicetastic-cli settings reset voice.amrnb_mode
voicetastic-cli settings reset

set validates the value (range, enum membership, u8 bounds, …) and rejects out-of-range input with a clear error.


Key reference

All keys are stable string ids — they appear in config.toml verbatim and are what the CLI accepts.

last_device

Kind optional string
Default unset

Last BLE address (AA:BB:CC:DD:EE:FF) or serial port path (/dev/ttyUSB0) that successfully connected. The GUI's Devices tab uses it for one-click reconnect on startup. Pass an empty string to set to clear it.

voice.max_duration_secs

Kind integer
Range 1..=120
Default 30

Hard cap on a single voice-message recording. Capture stops automatically when the cap is reached. The 120 s upper bound is enforced by set (anything larger would reliably exceed the protocol's per-message size budget at typical voice bitrates).

voice.reassembly_timeout_secs

Kind integer
Range 10..=3600
Default 1200

How long the receiver waits for missing chunks of an in-flight voice message before emitting a partial. Long values help on slow LoRa presets (where a full burst can take minutes); short values reclaim memory faster on busy mesh.

Applies immediately to the in-process assembler — no restart needed. The sender's retransmit retain TTL is coupled to this same value so a NACK can't arrive for a message the sender already forgot.

voice.codec

Kind enum
Variants amrnb, codec2, opus
Default amrnb

Codec used to encode new outgoing voice messages. Inbound messages are always decoded using the codec advertised in their header, so this setting only affects what you send.

Codec Rate Bitrates Notes
amrnb 8 kHz 4.75 - 12.2 kbps (8 modes) Wire-compatible with Voicetastic Android.
codec2 8 kHz 1.2 - 3.2 kbps (6 modes) Most LoRa-friendly bitrates.
opus 48 kHz 6 - 16 kbps (default 12), narrow/wide Configurable via voice.opus_bitrate_kbps and voice.opus_bandwidth.

voice.amrnb_mode

Kind integer
Range 0..=7
Default 7 (MR122, 12.20 kbps)

AMR-NB bitrate mode used when voice.codec = amrnb.

Value Mode Bitrate Bytes / 20 ms frame (incl. ToC)
0 MR475 4.75 kbps 13
1 MR515 5.15 kbps 14
2 MR590 5.90 kbps 16
3 MR670 6.70 kbps 18
4 MR740 7.40 kbps 20
5 MR795 7.95 kbps 21
6 MR102 10.20 kbps 27
7 MR122 12.20 kbps 32

Lower values are friendlier to slow LoRa presets at the cost of audio quality.

voice.codec2_mode

Kind integer
Range 0..=5
Default 5 (1200 bps)

Codec2 bitrate mode used when voice.codec = codec2.

Value Bitrate
0 3200 bps
1 2400 bps
2 1600 bps
3 1400 bps
4 1300 bps
5 1200 bps

At 1200 bps a 30 s clip fits in ~4.5 kB - recommended for LongFast and slower presets.

voice.opus_bitrate_kbps

Kind integer
Range 6..=16
Default 12

Opus encoder bitrate (kbps), used when voice.codec = opus. Informational on the wire (the Opus bitstream self-describes, so the decoder ignores the codec_param byte). 12 kbps mono is intelligible and fits a 30 s clip on every preset.

voice.opus_bandwidth

Kind enum
Variants narrow, wide
Default wide

Opus audio bandwidth when voice.codec = opus: narrow = SILK 8 kHz, wide = SILK 16 kHz. Higher modes (super-wide, full-band) are deliberately omitted - they cost airtime without helping voice intelligibility.

voice.denoise_enabled

Kind bool
Default false

Capture-side RNNoise noise suppression before the encoder. On builds without the voicetastic-core/denoise feature the setting persists but the runtime is a passthrough.

voice.partial_play_on_timeout

Kind bool
Default true

Receive-side policy. When true, an incomplete voice message whose reassembly timer fires is finalised with whatever chunks arrived (silence padded for the rest); when false, the partial is dropped on timeout. Maps to AssemblerConfig::partial_play_on_timeout.

voice.fec_mode

Kind enum
Variants auto, off, light, medium, heavy
Default auto

Sender-side FEC parity policy, resolved to a concrete parity_count at send time against destination (broadcast/unicast) and modem preset:

Mode Parity (% of total_data)
off 0 % (rely on NACK retransmits, or partial on broadcast)
light 10 %
medium 25 %
heavy 50 % (recommended for broadcast / high-loss long-range)
auto Broadcast → 50 %; unicast → 33 % long-range, 20 % medium, 0 % short, 20 % unknown

Resolved value is clamped to [0, min(total_data, 128)]. See VoiceFecMode.

voice.nack_mode

Kind enum
Variants auto, off, conservative, aggressive
Default auto

Receive-side NACK aggressiveness, resolved to (nack_window, backoff_base, max_nack_rounds) against the modem preset. Broadcast messages always behave as off regardless of this setting - the assembler suppresses NACKs for broadcast destinations so a chatty channel isn't flooded by every listener.

Mode nack_window backoff_base max_nack_rounds
off (NACK disabled) 0 0
conservative pacing × 4 min 4 s 3 200
aggressive 1.5 s 2 800
auto short/med-fast 1.5 s · med-slow/LongFast 3 s · long-range/unknown pacing × 4 min 4 s 2 / 2 / 3 800 / 400 / 200

See Reliability - NACK aggressiveness.

theme.mode

Kind enum
Variants system, light, dark
Default dark

Desktop GUI theme mode. system follows the host OS / desktop theme; light and dark pin the preference. GUI-only; ignored by headless front-ends.

theme.contrast

Kind enum
Variants standard, high
Default standard

Desktop GUI contrast tier. standard uses the M3 TonalSpot palette; high opts into the HighContrast variant that mirrors the meshtastic-device-ui firmware theme (useful as an a11y theme). GUI-only.


File format

config.toml is a flat TOML document; unset keys are omitted so the file stays small and human-editable:

last_device = "AA:BB:CC:DD:EE:FF"
voice_codec = "amrnb"
voice_amrnb_mode = 7
max_voice_duration_secs = 30
reassembly_timeout_secs = 1200

The field names on disk use snake_case; the dotted keys (voice.codec, voice.amrnb_mode, …) are the stable wire ids used by the CLI and the Android bridge, and are translated to/from the TOML schema by SettingsApi.

If the file is missing, malformed, or contains an unknown value, the API silently falls back to defaults instead of refusing to start.

Clone this wiki locally