python-voiceio 0.9.11__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_voiceio-1.1.0/PKG-INFO +314 -0
- python_voiceio-1.1.0/README.md +261 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/pyproject.toml +34 -19
- python_voiceio-1.1.0/python_voiceio.egg-info/PKG-INFO +314 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/python_voiceio.egg-info/SOURCES.txt +80 -17
- python_voiceio-1.1.0/python_voiceio.egg-info/entry_points.txt +3 -0
- python_voiceio-1.1.0/python_voiceio.egg-info/requires.txt +42 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_app_wiring.py +86 -146
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_audio_quality.py +4 -4
- python_voiceio-1.1.0/tests/test_audio_source.py +232 -0
- python_voiceio-1.1.0/tests/test_cli.py +71 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_commands.py +46 -61
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_concurrency_lockdown.py +85 -91
- python_voiceio-1.1.0/tests/test_config.py +156 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_corrections.py +41 -0
- python_voiceio-1.1.0/tests/test_decoders.py +124 -0
- python_voiceio-1.1.0/tests/test_engine.py +98 -0
- python_voiceio-1.1.0/tests/test_evdev_uaccess.py +85 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_fallback.py +6 -0
- python_voiceio-1.1.0/tests/test_fcitx_bridge.py +49 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_health.py +34 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_ibus_engine_limits.py +33 -1
- python_voiceio-1.1.0/tests/test_ibus_engine_listener.py +77 -0
- python_voiceio-1.1.0/tests/test_ibus_pids.py +35 -0
- python_voiceio-1.1.0/tests/test_ibus_session.py +536 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_ibus_typer.py +82 -23
- python_voiceio-1.1.0/tests/test_learn_clean.py +42 -0
- python_voiceio-1.1.0/tests/test_learn_import.py +37 -0
- python_voiceio-1.1.0/tests/test_learn_metrics.py +38 -0
- python_voiceio-1.1.0/tests/test_learn_pipeline.py +294 -0
- python_voiceio-1.1.0/tests/test_learn_review.py +20 -0
- python_voiceio-1.1.0/tests/test_learn_targets.py +52 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_llm.py +30 -28
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_llm_api.py +3 -3
- python_voiceio-1.1.0/tests/test_numbers.py +141 -0
- python_voiceio-1.1.0/tests/test_pipeline.py +67 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_platform.py +77 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_postcorrect.py +44 -8
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_postprocess.py +34 -14
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_retention.py +23 -8
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_robustness.py +122 -122
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_security_hardening.py +8 -8
- python_voiceio-1.1.0/tests/test_server.py +575 -0
- python_voiceio-1.1.0/tests/test_service.py +45 -0
- python_voiceio-0.9.11/tests/test_wizard.py → python_voiceio-1.1.0/tests/test_setup.py +69 -32
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_streaming.py +227 -110
- python_voiceio-1.1.0/tests/test_suggest.py +173 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_tokens.py +1 -1
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_transcriber.py +94 -47
- python_voiceio-1.1.0/tests/test_tts.py +425 -0
- python_voiceio-1.1.0/tests/test_typer_manager.py +39 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_vocabulary.py +12 -12
- python_voiceio-1.1.0/tests/test_worker_decode.py +62 -0
- python_voiceio-1.1.0/voiceio/__init__.py +1 -0
- python_voiceio-1.1.0/voiceio/app.py +716 -0
- python_voiceio-1.1.0/voiceio/audio_source.py +217 -0
- python_voiceio-1.1.0/voiceio/cli/__init__.py +191 -0
- python_voiceio-1.1.0/voiceio/cli/configcmd.py +77 -0
- python_voiceio-1.1.0/voiceio/cli/corrections.py +102 -0
- python_voiceio-1.1.0/voiceio/cli/doctor.py +191 -0
- python_voiceio-1.1.0/voiceio/cli/history.py +37 -0
- python_voiceio-1.1.0/voiceio/cli/learn.py +519 -0
- python_voiceio-1.1.0/voiceio/cli/models.py +106 -0
- python_voiceio-1.1.0/voiceio/cli/servicecmd.py +81 -0
- python_voiceio-1.1.0/voiceio/cli/uninstall.py +218 -0
- python_voiceio-1.1.0/voiceio/cli/vocab.py +101 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/commands.py +48 -20
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/config.py +125 -51
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/consent.py +1 -1
- python_voiceio-1.1.0/voiceio/core/__init__.py +6 -0
- python_voiceio-1.1.0/voiceio/core/bias.py +98 -0
- python_voiceio-1.1.0/voiceio/core/decoders/__init__.py +60 -0
- python_voiceio-1.1.0/voiceio/core/decoders/base.py +105 -0
- python_voiceio-1.1.0/voiceio/core/decoders/catalog.py +59 -0
- python_voiceio-0.9.11/voiceio/transcriber.py → python_voiceio-1.1.0/voiceio/core/decoders/faster_whisper/__init__.py +84 -57
- python_voiceio-1.1.0/voiceio/core/decoders/faster_whisper/worker.py +195 -0
- python_voiceio-1.1.0/voiceio/core/decoders/lanes.py +43 -0
- python_voiceio-1.1.0/voiceio/core/decoders/sherpa.py +108 -0
- python_voiceio-1.1.0/voiceio/core/decoders/whispercpp.py +93 -0
- python_voiceio-1.1.0/voiceio/core/engine.py +206 -0
- python_voiceio-1.1.0/voiceio/core/pipeline.py +213 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/corrections.py +99 -39
- python_voiceio-1.1.0/voiceio/data/60-voiceio-uaccess.rules +5 -0
- python_voiceio-1.1.0/voiceio/data/__init__.py +1 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/demo.py +13 -14
- python_voiceio-1.1.0/voiceio/display.py +150 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/feedback.py +6 -1
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/health.py +147 -26
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/history.py +4 -1
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/hotkeys/evdev.py +71 -9
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/hotkeys/pynput_backend.py +2 -1
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/ibus/__init__.py +31 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/ibus/engine.py +71 -14
- python_voiceio-1.1.0/voiceio/ibus/install.py +305 -0
- python_voiceio-1.1.0/voiceio/ibus/session.py +673 -0
- python_voiceio-1.1.0/voiceio/learn/__init__.py +14 -0
- python_voiceio-1.1.0/voiceio/learn/augment.py +105 -0
- python_voiceio-1.1.0/voiceio/learn/clean.py +145 -0
- python_voiceio-1.1.0/voiceio/learn/evaluate.py +291 -0
- python_voiceio-1.1.0/voiceio/learn/importer.py +101 -0
- python_voiceio-1.1.0/voiceio/learn/metrics.py +147 -0
- python_voiceio-1.1.0/voiceio/learn/review.py +114 -0
- python_voiceio-1.1.0/voiceio/learn/store.py +347 -0
- python_voiceio-1.1.0/voiceio/learn/teacher.py +87 -0
- python_voiceio-1.1.0/voiceio/learn/train.py +374 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/llm.py +11 -22
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/llm_api.py +6 -6
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/numbers.py +106 -5
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/platform.py +194 -4
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/postcorrect.py +70 -14
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/postprocess.py +11 -66
- python_voiceio-1.1.0/voiceio/privacy.py +13 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/recorder.py +21 -13
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/retention.py +11 -1
- python_voiceio-1.1.0/voiceio/server/__init__.py +44 -0
- python_voiceio-1.1.0/voiceio/server/__main__.py +51 -0
- python_voiceio-1.1.0/voiceio/server/app.py +389 -0
- python_voiceio-1.1.0/voiceio/server/config.py +108 -0
- python_voiceio-1.1.0/voiceio/server/runtime.py +301 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/service.py +72 -35
- python_voiceio-1.1.0/voiceio/setup/__init__.py +10 -0
- python_voiceio-1.1.0/voiceio/setup/configfile.py +133 -0
- python_voiceio-1.1.0/voiceio/setup/extras.py +246 -0
- python_voiceio-1.1.0/voiceio/setup/hotkey.py +171 -0
- python_voiceio-1.1.0/voiceio/setup/noninteractive.py +212 -0
- python_voiceio-1.1.0/voiceio/setup/speech.py +227 -0
- python_voiceio-1.1.0/voiceio/setup/steps.py +638 -0
- python_voiceio-1.1.0/voiceio/setup/system.py +166 -0
- python_voiceio-1.1.0/voiceio/setup/ui.py +357 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/streaming.py +137 -195
- python_voiceio-1.1.0/voiceio/suggest.py +138 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tokens.py +7 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tray/__init__.py +26 -41
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tts/chain.py +22 -2
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tts/edge_engine.py +1 -1
- python_voiceio-1.1.0/voiceio/tts/piper_engine.py +99 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/__init__.py +3 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/chain.py +16 -13
- python_voiceio-1.1.0/voiceio/typers/collecting.py +79 -0
- python_voiceio-1.1.0/voiceio/typers/fcitx_bridge.py +70 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/ibus.py +12 -269
- python_voiceio-1.1.0/voiceio/typers/manager.py +329 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/pynput_type.py +2 -1
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/ydotool.py +12 -0
- python_voiceio-1.1.0/voiceio/ui.py +18 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/vocab_stats.py +1 -1
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/vocabulary.py +21 -23
- python_voiceio-1.1.0/voiceio/watchdog.py +195 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/wordfreq.py +22 -1
- python_voiceio-0.9.11/PKG-INFO +0 -318
- python_voiceio-0.9.11/README.md +0 -270
- python_voiceio-0.9.11/python_voiceio.egg-info/PKG-INFO +0 -318
- python_voiceio-0.9.11/python_voiceio.egg-info/entry_points.txt +0 -6
- python_voiceio-0.9.11/python_voiceio.egg-info/requires.txt +0 -36
- python_voiceio-0.9.11/tests/test_adjudicate.py +0 -301
- python_voiceio-0.9.11/tests/test_audit.py +0 -297
- python_voiceio-0.9.11/tests/test_autocorrect.py +0 -527
- python_voiceio-0.9.11/tests/test_autocorrect_state.py +0 -51
- python_voiceio-0.9.11/tests/test_cli.py +0 -264
- python_voiceio-0.9.11/tests/test_config.py +0 -76
- python_voiceio-0.9.11/tests/test_correct_batch.py +0 -229
- python_voiceio-0.9.11/tests/test_evaluate.py +0 -198
- python_voiceio-0.9.11/tests/test_numbers.py +0 -101
- python_voiceio-0.9.11/tests/test_snapshots.py +0 -54
- python_voiceio-0.9.11/tests/test_tts.py +0 -158
- python_voiceio-0.9.11/voiceio/__init__.py +0 -1
- python_voiceio-0.9.11/voiceio/app.py +0 -1720
- python_voiceio-0.9.11/voiceio/audit.py +0 -430
- python_voiceio-0.9.11/voiceio/autocorrect.py +0 -713
- python_voiceio-0.9.11/voiceio/autocorrect_state.py +0 -184
- python_voiceio-0.9.11/voiceio/cli.py +0 -1835
- python_voiceio-0.9.11/voiceio/evaluate.py +0 -322
- python_voiceio-0.9.11/voiceio/snapshots.py +0 -78
- python_voiceio-0.9.11/voiceio/tts/piper_engine.py +0 -91
- python_voiceio-0.9.11/voiceio/wizard.py +0 -1997
- python_voiceio-0.9.11/voiceio/worker.py +0 -98
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/LICENSE +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/python_voiceio.egg-info/dependency_links.txt +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/python_voiceio.egg-info/top_level.txt +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/setup.cfg +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_backend_probes.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_clipboard_read.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_hints.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_history.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_ibus_pending.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_ibus_ping.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_ibus_textlimit.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_prebuffer.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_prompt.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_recorder_integration.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_vad.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/tests/test_wordfreq.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/__main__.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/backends.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/clipboard_read.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/hints.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/hotkeys/__init__.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/hotkeys/base.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/hotkeys/chain.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/hotkeys/socket_backend.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/ibus/pending.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/ibus/textlimit.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/models/__init__.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/models/silero_vad.onnx +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/pidlock.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/prompt.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/sounds/__init__.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/sounds/commit.wav +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/sounds/start.wav +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/sounds/stop.wav +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tray/_icons.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tray/_indicator.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tray/_pystray.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tts/__init__.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tts/base.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tts/espeak.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/tts/player.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/base.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/clipboard.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/wtype.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/typers/xdotool.py +0 -0
- {python_voiceio-0.9.11 → python_voiceio-1.1.0}/voiceio/vad.py +0 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-voiceio
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Voice dictation for Linux. Speak → text, locally, instantly.
|
|
5
|
+
Author: Hugo Montenegro
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Hugo0/voiceio
|
|
8
|
+
Project-URL: Repository, https://github.com/Hugo0/voiceio
|
|
9
|
+
Project-URL: Issues, https://github.com/Hugo0/voiceio/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/Hugo0/voiceio/releases
|
|
11
|
+
Keywords: voice,speech-to-text,whisper,linux,dictation,wayland,ibus
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: X11 Applications
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: faster-whisper>=1.0.0
|
|
22
|
+
Requires-Dist: numpy>=1.24.0
|
|
23
|
+
Requires-Dist: onnxruntime>=1.16.0
|
|
24
|
+
Requires-Dist: wordfreq>=3.0
|
|
25
|
+
Provides-Extra: desktop
|
|
26
|
+
Requires-Dist: sounddevice>=0.4.6; extra == "desktop"
|
|
27
|
+
Requires-Dist: evdev>=1.6.0; sys_platform == "linux" and extra == "desktop"
|
|
28
|
+
Requires-Dist: pynput>=1.7.6; extra == "desktop"
|
|
29
|
+
Requires-Dist: pystray>=0.19; extra == "desktop"
|
|
30
|
+
Requires-Dist: Pillow>=10.0; extra == "desktop"
|
|
31
|
+
Provides-Extra: linux
|
|
32
|
+
Requires-Dist: sounddevice>=0.4.6; extra == "linux"
|
|
33
|
+
Requires-Dist: evdev>=1.6.0; sys_platform == "linux" and extra == "linux"
|
|
34
|
+
Requires-Dist: pynput>=1.7.6; extra == "linux"
|
|
35
|
+
Requires-Dist: pystray>=0.19; extra == "linux"
|
|
36
|
+
Requires-Dist: Pillow>=10.0; extra == "linux"
|
|
37
|
+
Provides-Extra: server
|
|
38
|
+
Requires-Dist: aiohttp>=3.9; extra == "server"
|
|
39
|
+
Provides-Extra: tts
|
|
40
|
+
Requires-Dist: piper-tts>=1.3.0; extra == "tts"
|
|
41
|
+
Requires-Dist: edge-tts>=6.1.0; extra == "tts"
|
|
42
|
+
Provides-Extra: train
|
|
43
|
+
Requires-Dist: torch>=2.2; extra == "train"
|
|
44
|
+
Requires-Dist: transformers>=4.40; extra == "train"
|
|
45
|
+
Requires-Dist: peft>=0.10; extra == "train"
|
|
46
|
+
Provides-Extra: sherpa
|
|
47
|
+
Requires-Dist: sherpa-onnx>=1.12; extra == "sherpa"
|
|
48
|
+
Provides-Extra: dev
|
|
49
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
50
|
+
Requires-Dist: pytest-mock; extra == "dev"
|
|
51
|
+
Requires-Dist: ruff<0.18,>=0.15; extra == "dev"
|
|
52
|
+
Dynamic: license-file
|
|
53
|
+
|
|
54
|
+
# voiceio
|
|
55
|
+
|
|
56
|
+
[](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml)
|
|
57
|
+
[](https://pypi.org/project/python-voiceio/)
|
|
58
|
+
[](https://pypi.org/project/python-voiceio/)
|
|
59
|
+
[](LICENSE)
|
|
60
|
+
|
|
61
|
+
**Voice dictation that learns you.** Local, open source, private — and it fine-tunes itself on your own voice, on your own machine.
|
|
62
|
+
|
|
63
|
+
Off-the-shelf speech models stumble on exactly the words you say most: your colleagues' names, your project, your jargon. voiceio keeps (with your permission) the audio of what you dictate, has a bigger model transcribe it overnight, and trains a personal model from it — nothing uploaded, no GPU required. On the author's dictation, one overnight run on a laptop CPU cut word errors from **12.1% to 5.0%** on held-out clips and recognized more of the author's vocabulary, at the same speed. Every model is scored on clips it never trained on, and it only replaces the current one when it wins.
|
|
64
|
+
|
|
65
|
+
https://github.com/user-attachments/assets/9cf5d1ac-b4bb-4cf8-b775-7a66dc16b376
|
|
66
|
+
|
|
67
|
+
Press a hotkey, speak, and the text streams into whatever app has focus. Press again to commit.
|
|
68
|
+
|
|
69
|
+
- **Learns you.** `voiceio learn` fine-tunes a model on your own voice; a vocabulary steers it toward new names right away; corrections fix the rest. See [Make it yours](#make-it-yours).
|
|
70
|
+
- **Local.** Speech is decoded on-device ([faster-whisper](https://github.com/SYSTRAN/faster-whisper) by default). Audio never leaves the machine and there is no telemetry. Two optional, off-by-default features send *text* (never audio) to an LLM endpoint you configure: final-transcript polish (`[postcorrect]`) and an optional local Ollama cleanup (`[llm]`).
|
|
71
|
+
- **Yours.** History, retained audio, corrections, vocabulary and fine-tuned models are plain local files. See [Your data](#your-data).
|
|
72
|
+
- **Linux-first.** Wayland and X11, GNOME, KDE, Hyprland, sway and i3. Backends are picked by probing what works. See [Linux support](#linux-support).
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
> **Upgrading from 0.x?** See [UPGRADING.md](UPGRADING.md) — 1.0 renames a few commands and moves desktop dependencies to the `[desktop]` extra.
|
|
76
|
+
|
|
77
|
+
## Quickstart
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# 1. System packages: a C toolchain (evdev has no wheel), PortAudio, IBus + GObject bindings
|
|
81
|
+
sudo apt install pipx build-essential python3-dev portaudio19-dev ibus gir1.2-ibus-1.0 python3-gi # Debian/Ubuntu
|
|
82
|
+
sudo dnf install pipx gcc gcc-c++ make python3-devel portaudio-devel ibus ibus-libs python3-gobject # Fedora
|
|
83
|
+
sudo pacman -S python-pipx base-devel portaudio ibus python-gobject # Arch
|
|
84
|
+
|
|
85
|
+
# 2. voiceio with the desktop extra (microphone, hotkeys, tray)
|
|
86
|
+
pipx install 'python-voiceio[desktop]'
|
|
87
|
+
|
|
88
|
+
# 3. Guided setup: model download, hotkey, autostart
|
|
89
|
+
voiceio setup
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Then press **Ctrl+Alt+V**, speak, and press it again. `voiceio doctor` tells you what is working and `voiceio doctor --fix` repairs what it can.
|
|
93
|
+
|
|
94
|
+
NixOS users: see [NixOS](#nixos). Agents installing voiceio non-interactively: see [INSTALL.md](INSTALL.md).
|
|
95
|
+
|
|
96
|
+
<details>
|
|
97
|
+
<summary><strong>Extras</strong></summary>
|
|
98
|
+
|
|
99
|
+
The base package (`pip install python-voiceio`) is headless transcription only: no microphone, hotkeys or display needed.
|
|
100
|
+
|
|
101
|
+
| Extra | Adds |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `desktop` | The dictation app: microphone (sounddevice), hotkeys (evdev, pynput), tray icon |
|
|
104
|
+
| `server` | HTTP/WebSocket transcription server: `python -m voiceio.server` |
|
|
105
|
+
| `tts` | Text-to-speech: piper (local), edge-tts (cloud) |
|
|
106
|
+
| `sherpa` | sherpa-onnx runtime for non-Whisper models (experimental) |
|
|
107
|
+
| `train` | `voiceio learn train`: LoRA fine-tuning (torch, transformers, peft) |
|
|
108
|
+
|
|
109
|
+
</details>
|
|
110
|
+
|
|
111
|
+
<details>
|
|
112
|
+
<summary><strong>From source</strong></summary>
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
git clone https://github.com/Hugo0/voiceio && cd voiceio
|
|
116
|
+
uv sync --extra desktop --extra dev
|
|
117
|
+
uv run voiceio setup # also links voiceio into ~/.local/bin
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
</details>
|
|
121
|
+
|
|
122
|
+
## Commands
|
|
123
|
+
|
|
124
|
+
> **Note:** the CLI is being restructured for v1.0. This list is the target layout. Check it against `voiceio --help` before release.
|
|
125
|
+
|
|
126
|
+
| Command | What it does |
|
|
127
|
+
|---|---|
|
|
128
|
+
| `voiceio run` | Start the dictation daemon in the foreground (the systemd unit runs this) |
|
|
129
|
+
| `voiceio toggle` | Start/stop recording on the running daemon. Bind it to a key if you don't use evdev |
|
|
130
|
+
| `voiceio setup` | Guided setup (`--defaults` / `--answers '{json}'` for scripts) |
|
|
131
|
+
| `voiceio doctor [--fix]` | Check every backend; `--fix` repairs what it can, asking before anything that needs sudo |
|
|
132
|
+
| `voiceio service install\|uninstall\|start\|stop\|restart\|status\|logs` | systemd user unit: start on login, restart on crash; `logs -f` follows |
|
|
133
|
+
| `voiceio models list\|bench\|use` | See, compare and pick speech models ([Choose a model](#choose-a-model)) |
|
|
134
|
+
| `voiceio vocab` | Manage the vocabulary that steers the decoder |
|
|
135
|
+
| `voiceio corrections` | Manage find/replace rules for words it still gets wrong |
|
|
136
|
+
| `voiceio learn …` | Personalize: label → review → augment → build → eval → train → promote |
|
|
137
|
+
| `voiceio history` | Search what you have dictated |
|
|
138
|
+
| `voiceio config` | Show or set config values |
|
|
139
|
+
| `voiceio uninstall` | Remove the service, IBus component, shortcuts and symlinks (asks before deleting your data) |
|
|
140
|
+
|
|
141
|
+
## Your data
|
|
142
|
+
|
|
143
|
+
Everything voiceio keeps is in three directories (they follow `XDG_CONFIG_HOME`, `XDG_STATE_HOME` and `XDG_DATA_HOME`). Files are created `0600`, directories `0700`. Nothing is uploaded. Recordings, decode traces and window titles are **off unless you turn them on** — `voiceio setup` asks whether to keep recordings so voiceio can learn your voice. Logs record sizes and timings, never your words.
|
|
144
|
+
|
|
145
|
+
| Path | Holds | Retention |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| **`~/.config/voiceio/`** | *Settings and what it has learned about your words* | |
|
|
148
|
+
| `config.toml` | All settings | — |
|
|
149
|
+
| `vocabulary.txt` | Your terms, one per line, used as decoder hotwords | Never pruned; rarely used terms rank lower |
|
|
150
|
+
| `vocab_stats.json` | Per-term usage counts used to rank the vocabulary | Rebuilt as you dictate |
|
|
151
|
+
| `corrections.json` | Find/replace rules (`post grass` → `PostgreSQL`) | — |
|
|
152
|
+
| `flagged.txt` | Words flagged with the "correct that" voice command, for review | — |
|
|
153
|
+
| `snapshots/` | Copies of corrections + vocabulary from before 1.0 (safe to delete) | — |
|
|
154
|
+
| `consent.json` | Whether you allowed cloud LLM calls (text only) | — |
|
|
155
|
+
| `hints.json` | Which CLI tips you have already seen | — |
|
|
156
|
+
| **`~/.local/state/voiceio/`** | *What you said* | |
|
|
157
|
+
| `history.jsonl` | Every committed transcript: time, raw and final text (and the focused-window title with `[data] capture_context`) | `[history] enabled`, `max_entries`, `max_age_days` (0 = keep forever) |
|
|
158
|
+
| `recordings/*.wav` | The audio of each utterance, for `voiceio learn` — **opt-in** | `[data] retain_audio` (default off), `max_audio_mb` (default 4096), `min_free_gb` (default 5) |
|
|
159
|
+
| `streaming_trace.jsonl`, `postcorrect_pairs.jsonl` | Per-pass decode text and timings, LLM before/after pairs — **opt-in**, for debugging | `[data] capture_intermediates` (default off); each capped at 64 MB |
|
|
160
|
+
| `voiceio.log`, `worker.log`, `ibus-engine-stderr.log` | Logs | `voiceio.log` rotates at 2 MB × 3 |
|
|
161
|
+
| **`~/.local/share/voiceio/learn/`** | *Personalization corpus* (only exists once you run `voiceio learn`) | Never pruned; delete freely |
|
|
162
|
+
| `labels.jsonl` | Reference transcripts from the teacher model or your review | — |
|
|
163
|
+
| `augment/` | Synthetic TTS clips of your hard words | — |
|
|
164
|
+
| `datasets/vNNNN/` | Frozen train/dev/test splits | — |
|
|
165
|
+
| `exports/` | Datasets packed for training on another machine | — |
|
|
166
|
+
| `models/<run>/` | Your fine-tuned models, plus `promotions.jsonl` | — |
|
|
167
|
+
| `runs/` | Evaluation results | — |
|
|
168
|
+
|
|
169
|
+
Set `[data] capture_context = false` to stop recording window titles. `voiceio uninstall` offers to delete the config and state directories; delete `~/.local/share/voiceio` yourself.
|
|
170
|
+
|
|
171
|
+
## Make it yours
|
|
172
|
+
|
|
173
|
+
Most dictation errors are proper nouns and jargon: `PostgreSQL` heard as `post grass`, a colleague's name spelled three ways. There are three tools for that, from cheapest to most powerful.
|
|
174
|
+
|
|
175
|
+
**1. Vocabulary.** Put your names and terms in `~/.config/voiceio/vocabulary.txt` (or use `voiceio vocab`). They are passed to Whisper as *hotwords* on every decode, ranked by how often you use them. One honest limit: Whisper's hotword channel is capped at 223 tokens, and a proper noun costs 5 to 7 tokens, so only about **35 terms** steer each decode. The rest are kept and ranked, but they do nothing until they rank high enough. This ceiling comes from the model, not from voiceio. [CONTRIBUTING.md](CONTRIBUTING.md#model-choice-why-whisper-and-what-would-change-it) explains why we still use Whisper.
|
|
176
|
+
|
|
177
|
+
**2. Corrections.** Find/replace rules for what still comes out wrong (`voiceio corrections add WRONG RIGHT`, or say "correct that" right after a mistake and review with `voiceio corrections flagged`). `voiceio vocab suggest` lists unusual words from your history — offline — so you can add the real names to your vocabulary and turn the mishearings into corrections.
|
|
178
|
+
|
|
179
|
+
**3. Fine-tuning with `voiceio learn`.** This is how you get past the 35-term ceiling: teach the model your vocabulary directly, from your own retained audio.
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
voiceio learn import DIR --source phone # optional: add your own recordings from elsewhere
|
|
183
|
+
voiceio learn label # a stronger teacher model (large-v3-turbo) transcribes your clips
|
|
184
|
+
voiceio learn review # fix the teacher where it matters: your names and terms
|
|
185
|
+
voiceio learn review --test # once: verify the held-out clips, so eval scores against the truth
|
|
186
|
+
voiceio learn augment # synthesize extra examples of rare terms with local TTS
|
|
187
|
+
voiceio learn build # freeze a versioned train/dev/test dataset (the test split never trains)
|
|
188
|
+
voiceio learn eval # score the current model on your held-out clips: WER and term recall
|
|
189
|
+
# --streaming replays them through live dictation and times stop→text
|
|
190
|
+
voiceio learn train # LoRA fine-tune (needs the `train` extra; decoder-only on CPU, --full on a GPU)
|
|
191
|
+
voiceio learn promote <run> # dictate with the fine-tune; `voiceio learn rollback` undoes it
|
|
192
|
+
voiceio learn maintain # later: label what's new, and once 50+ clips piled up, retrain and compare
|
|
193
|
+
voiceio learn schedule on # …or let it run `maintain` every night, and notify you when a model wins
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Labeling, training and offline eval run in an idle-priority cgroup, so they never slow dictation down. Everything stays on your machine unless you choose `train --remote`.
|
|
197
|
+
|
|
198
|
+
`voiceio learn status` shows where you are, each model's scores, and suggests `promote` only when a fine-tune wins on everything. `promote` itself refuses a model that hasn't, and reports how many clips got better or worse with a confidence interval — a few dozen test clips can move an average by luck.
|
|
199
|
+
|
|
200
|
+
**Is it actually helping?** Once some clips are labeled, measure instead of guessing:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
voiceio learn eval --pipeline # what each text stage (numbers, commands, corrections, cloud
|
|
204
|
+
# postcorrect…) did to your past dictations, and its commonest edits
|
|
205
|
+
voiceio corrections audit # rules your own audio contradicts, and ones that look risky
|
|
206
|
+
voiceio learn eval --streaming # accuracy *and* stop→text, replaying clips through live dictation
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
On the author's data these found a correction that kept turning "composable" into "comparable", a number rule writing "no one" as "no 1", and a cloud pass that never fixed a single vocabulary term.
|
|
210
|
+
|
|
211
|
+
## Choose a model
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
voiceio models list # known models, your fine-tunes, and which is active
|
|
215
|
+
voiceio models bench # score candidates on your held-out clips (after `voiceio learn build`)
|
|
216
|
+
voiceio models use medium # switch
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
| Model | Runtime | License | Notes |
|
|
220
|
+
|---|---|---|---|
|
|
221
|
+
| `small` | faster-whisper | MIT | Default. About 5× realtime on a laptop CPU |
|
|
222
|
+
| `medium` | faster-whisper | MIT | Better on names, about 2.5× slower |
|
|
223
|
+
| `large-v3-turbo` | faster-whisper | MIT | Best Whisper for dictation; wants a GPU. Also the default `learn` teacher |
|
|
224
|
+
| `distil-large-v3` | faster-whisper | MIT | English only |
|
|
225
|
+
| `sherpa:parakeet-tdt-0.6b-v3` | sherpa-onnx | CC-BY-4.0 | Experimental. Fast, but no vocabulary biasing yet |
|
|
226
|
+
| `whispercpp:http://…` | whisper.cpp server | depends on the model | Experimental. E.g. a Vulkan build on an AMD iGPU |
|
|
227
|
+
|
|
228
|
+
Pick on your own audio, not leaderboards: for dictation full of names, how well a model can be *biased* matters more than its benchmark WER.
|
|
229
|
+
|
|
230
|
+
**Licenses.** voiceio ships no model weights. Each model is downloaded from its own source on first use, under its own license. The defaults are permissive (MIT). A fine-tune you make with `voiceio learn` inherits the license of the base model it was trained from.
|
|
231
|
+
|
|
232
|
+
## Dictate from your phone
|
|
233
|
+
|
|
234
|
+
`python -m voiceio.server` (the `server` extra) serves the same engine over HTTP and WebSocket, for a phone or any other client: `POST /transcribe` with an audio file, or stream PCM over `/ws/transcribe` for live partials. It binds `127.0.0.1` by default; put it behind your VPN or a reverse proxy and set `VOICE_TOKEN` (bearer token) and `VOICE_ALLOWED_ORIGINS` when it is reachable from elsewhere. `VOICE_MODEL`, `VOICE_LANES`, `VOICE_HOST`/`VOICE_PORT` override the rest.
|
|
235
|
+
|
|
236
|
+
The server reads its own machine's voiceio config, so it gets your vocabulary and corrections once you copy them over:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
scripts/sync_personalization.sh myserver # vocabulary + corrections
|
|
240
|
+
scripts/sync_personalization.sh myserver --model # …and your promoted fine-tune
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
To fine-tune on what you dictate from the phone too, opt in on the server with `[data] retain_audio = true` in its `config.toml`, then bring the clips home: `scripts/pull_phone_dictation.sh myserver` (an `rsync` over SSH followed by `voiceio learn import`). Only your own voice should go in: the model learns whoever is speaking.
|
|
244
|
+
|
|
245
|
+
## Linux support
|
|
246
|
+
|
|
247
|
+
| | Text injection | Streaming preview | Hotkey | Status |
|
|
248
|
+
|---|---|---|---|---|
|
|
249
|
+
| GNOME (Wayland) | IBus, ydotool fallback | Yes (IBus preedit) | evdev, or a GNOME shortcut set up by `setup` | Tested daily |
|
|
250
|
+
| GNOME (X11) | IBus, xdotool fallback | Yes | evdev, pynput | Supported |
|
|
251
|
+
| KDE Plasma (Wayland) | IBus, ydotool fallback | Yes with IBus | evdev | Should work |
|
|
252
|
+
| Hyprland, incl. Omarchy | IBus, else wtype → ydotool | Yes with IBus; with fcitx5 (Omarchy's default), words are typed as you speak, without the in-place preview | evdev, or `bind = CTRL ALT, V, exec, voiceio toggle` | Should work |
|
|
253
|
+
| sway | IBus, else wtype → ydotool | As Hyprland | evdev, or `bindsym` + `voiceio toggle` | Should work |
|
|
254
|
+
| i3 / other X11 | IBus, xdotool | Yes with IBus | pynput, evdev | Should work |
|
|
255
|
+
| NixOS | as above | as above | evdev via the flake's udev rule | Flake provided, unbuilt ([NixOS](#nixos)) |
|
|
256
|
+
|
|
257
|
+
**Input methods.** IBus is the only way to get a live, underlined preview that is corrected in place on Wayland. voiceio installs its own IBus engine and only activates it while you dictate. If fcitx5 is your input method, voiceio leaves it alone and types the final text with wtype or ydotool. Terminals that ignore input methods get the clipboard.
|
|
258
|
+
|
|
259
|
+
**Hotkeys without the `input` group.** The evdev backend reads keyboards from `/dev/input`. `voiceio doctor --fix` installs a udev rule, `/etc/udev/rules.d/60-voiceio-uaccess.rules`, that grants the logged-in user access to keyboard devices. It works immediately, without logging out. The old route still works as a fallback: `sudo usermod -aG input $USER`, then log out and back in. You can also skip evdev and bind `voiceio toggle` in your compositor.
|
|
260
|
+
|
|
261
|
+
**ydotool** needs write access to `/dev/uinput`; `voiceio doctor --fix` installs a uaccess rule for that too.
|
|
262
|
+
|
|
263
|
+
### NixOS
|
|
264
|
+
|
|
265
|
+
The repository is a flake. **It has not been built yet**; please report fixes.
|
|
266
|
+
|
|
267
|
+
```nix
|
|
268
|
+
# flake inputs: voiceio.url = "github:Hugo0/voiceio";
|
|
269
|
+
# NixOS: package, uinput, and the keyboard uaccess rule
|
|
270
|
+
imports = [ voiceio.nixosModules.default ];
|
|
271
|
+
programs.voiceio.enable = true;
|
|
272
|
+
|
|
273
|
+
# Home Manager: config.toml from Nix + a systemd user service
|
|
274
|
+
imports = [ voiceio.homeManagerModules.default ];
|
|
275
|
+
services.voiceio = {
|
|
276
|
+
enable = true;
|
|
277
|
+
settings.model.name = "small";
|
|
278
|
+
};
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
For the streaming preview, enable IBus as your input method: `i18n.inputMethod = { enable = true; type = "ibus"; };`.
|
|
282
|
+
|
|
283
|
+
### Windows and macOS
|
|
284
|
+
|
|
285
|
+
There is a best-effort pynput path for both (hotkeys and typing, no live preview). It is untested and unmaintained, with no installers or CI. Patches are welcome; bug reports will likely sit.
|
|
286
|
+
|
|
287
|
+
## Troubleshooting
|
|
288
|
+
|
|
289
|
+
| Problem | Fix |
|
|
290
|
+
|---|---|
|
|
291
|
+
| Nothing is typed | `voiceio doctor --fix`; usually the IBus component or the GNOME input source |
|
|
292
|
+
| Hotkey does nothing on Wayland | `voiceio doctor --fix` installs the keyboard udev rule, or bind `voiceio toggle` in your compositor |
|
|
293
|
+
| `sounddevice is not installed` | You installed without the desktop extra: `pipx install --force 'python-voiceio[desktop]'` |
|
|
294
|
+
| evdev fails to build | Install a C toolchain and Python headers (see Quickstart), then reinstall |
|
|
295
|
+
| Too slow | `voiceio doctor` shows your real stop→text; turn off cloud postcorrect, or `voiceio models use small` (or a GPU with `large-v3-turbo`) |
|
|
296
|
+
| Words come out wrong in a pattern | `voiceio learn eval --pipeline` and `voiceio corrections audit` show which stage or rule did it |
|
|
297
|
+
| Start over | `voiceio uninstall`, then `voiceio setup` |
|
|
298
|
+
|
|
299
|
+
Logs: `journalctl --user -u voiceio` or `~/.local/state/voiceio/voiceio.log`.
|
|
300
|
+
|
|
301
|
+
## Roadmap
|
|
302
|
+
|
|
303
|
+
- **A landing page** — voiceio as local, open-source, private dictation that learns from you.
|
|
304
|
+
- **Hands-off promotion** — `learn schedule` already retrains nightly and tells you when a model wins; next is switching to it automatically, with one-command rollback.
|
|
305
|
+
- **Unbounded vocabulary** — move to a decoder whose biasing has no token cap (see [model choice](CONTRIBUTING.md#model-choice-why-whisper-and-what-would-change-it)).
|
|
306
|
+
- **One model everywhere** — sync your fine-tune to your phone server and laptops, peer to peer.
|
|
307
|
+
|
|
308
|
+
## Contributing
|
|
309
|
+
|
|
310
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the architecture, conventions and the reasoning behind the model choice. Please open an issue before a large PR.
|
|
311
|
+
|
|
312
|
+
## License
|
|
313
|
+
|
|
314
|
+
MIT. Model weights are not part of voiceio and carry their own licenses (see [Choose a model](#choose-a-model)).
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# voiceio
|
|
2
|
+
|
|
3
|
+
[](https://github.com/Hugo0/voiceio/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/python-voiceio/)
|
|
5
|
+
[](https://pypi.org/project/python-voiceio/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
**Voice dictation that learns you.** Local, open source, private — and it fine-tunes itself on your own voice, on your own machine.
|
|
9
|
+
|
|
10
|
+
Off-the-shelf speech models stumble on exactly the words you say most: your colleagues' names, your project, your jargon. voiceio keeps (with your permission) the audio of what you dictate, has a bigger model transcribe it overnight, and trains a personal model from it — nothing uploaded, no GPU required. On the author's dictation, one overnight run on a laptop CPU cut word errors from **12.1% to 5.0%** on held-out clips and recognized more of the author's vocabulary, at the same speed. Every model is scored on clips it never trained on, and it only replaces the current one when it wins.
|
|
11
|
+
|
|
12
|
+
https://github.com/user-attachments/assets/9cf5d1ac-b4bb-4cf8-b775-7a66dc16b376
|
|
13
|
+
|
|
14
|
+
Press a hotkey, speak, and the text streams into whatever app has focus. Press again to commit.
|
|
15
|
+
|
|
16
|
+
- **Learns you.** `voiceio learn` fine-tunes a model on your own voice; a vocabulary steers it toward new names right away; corrections fix the rest. See [Make it yours](#make-it-yours).
|
|
17
|
+
- **Local.** Speech is decoded on-device ([faster-whisper](https://github.com/SYSTRAN/faster-whisper) by default). Audio never leaves the machine and there is no telemetry. Two optional, off-by-default features send *text* (never audio) to an LLM endpoint you configure: final-transcript polish (`[postcorrect]`) and an optional local Ollama cleanup (`[llm]`).
|
|
18
|
+
- **Yours.** History, retained audio, corrections, vocabulary and fine-tuned models are plain local files. See [Your data](#your-data).
|
|
19
|
+
- **Linux-first.** Wayland and X11, GNOME, KDE, Hyprland, sway and i3. Backends are picked by probing what works. See [Linux support](#linux-support).
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
> **Upgrading from 0.x?** See [UPGRADING.md](UPGRADING.md) — 1.0 renames a few commands and moves desktop dependencies to the `[desktop]` extra.
|
|
23
|
+
|
|
24
|
+
## Quickstart
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 1. System packages: a C toolchain (evdev has no wheel), PortAudio, IBus + GObject bindings
|
|
28
|
+
sudo apt install pipx build-essential python3-dev portaudio19-dev ibus gir1.2-ibus-1.0 python3-gi # Debian/Ubuntu
|
|
29
|
+
sudo dnf install pipx gcc gcc-c++ make python3-devel portaudio-devel ibus ibus-libs python3-gobject # Fedora
|
|
30
|
+
sudo pacman -S python-pipx base-devel portaudio ibus python-gobject # Arch
|
|
31
|
+
|
|
32
|
+
# 2. voiceio with the desktop extra (microphone, hotkeys, tray)
|
|
33
|
+
pipx install 'python-voiceio[desktop]'
|
|
34
|
+
|
|
35
|
+
# 3. Guided setup: model download, hotkey, autostart
|
|
36
|
+
voiceio setup
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then press **Ctrl+Alt+V**, speak, and press it again. `voiceio doctor` tells you what is working and `voiceio doctor --fix` repairs what it can.
|
|
40
|
+
|
|
41
|
+
NixOS users: see [NixOS](#nixos). Agents installing voiceio non-interactively: see [INSTALL.md](INSTALL.md).
|
|
42
|
+
|
|
43
|
+
<details>
|
|
44
|
+
<summary><strong>Extras</strong></summary>
|
|
45
|
+
|
|
46
|
+
The base package (`pip install python-voiceio`) is headless transcription only: no microphone, hotkeys or display needed.
|
|
47
|
+
|
|
48
|
+
| Extra | Adds |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `desktop` | The dictation app: microphone (sounddevice), hotkeys (evdev, pynput), tray icon |
|
|
51
|
+
| `server` | HTTP/WebSocket transcription server: `python -m voiceio.server` |
|
|
52
|
+
| `tts` | Text-to-speech: piper (local), edge-tts (cloud) |
|
|
53
|
+
| `sherpa` | sherpa-onnx runtime for non-Whisper models (experimental) |
|
|
54
|
+
| `train` | `voiceio learn train`: LoRA fine-tuning (torch, transformers, peft) |
|
|
55
|
+
|
|
56
|
+
</details>
|
|
57
|
+
|
|
58
|
+
<details>
|
|
59
|
+
<summary><strong>From source</strong></summary>
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
git clone https://github.com/Hugo0/voiceio && cd voiceio
|
|
63
|
+
uv sync --extra desktop --extra dev
|
|
64
|
+
uv run voiceio setup # also links voiceio into ~/.local/bin
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
</details>
|
|
68
|
+
|
|
69
|
+
## Commands
|
|
70
|
+
|
|
71
|
+
> **Note:** the CLI is being restructured for v1.0. This list is the target layout. Check it against `voiceio --help` before release.
|
|
72
|
+
|
|
73
|
+
| Command | What it does |
|
|
74
|
+
|---|---|
|
|
75
|
+
| `voiceio run` | Start the dictation daemon in the foreground (the systemd unit runs this) |
|
|
76
|
+
| `voiceio toggle` | Start/stop recording on the running daemon. Bind it to a key if you don't use evdev |
|
|
77
|
+
| `voiceio setup` | Guided setup (`--defaults` / `--answers '{json}'` for scripts) |
|
|
78
|
+
| `voiceio doctor [--fix]` | Check every backend; `--fix` repairs what it can, asking before anything that needs sudo |
|
|
79
|
+
| `voiceio service install\|uninstall\|start\|stop\|restart\|status\|logs` | systemd user unit: start on login, restart on crash; `logs -f` follows |
|
|
80
|
+
| `voiceio models list\|bench\|use` | See, compare and pick speech models ([Choose a model](#choose-a-model)) |
|
|
81
|
+
| `voiceio vocab` | Manage the vocabulary that steers the decoder |
|
|
82
|
+
| `voiceio corrections` | Manage find/replace rules for words it still gets wrong |
|
|
83
|
+
| `voiceio learn …` | Personalize: label → review → augment → build → eval → train → promote |
|
|
84
|
+
| `voiceio history` | Search what you have dictated |
|
|
85
|
+
| `voiceio config` | Show or set config values |
|
|
86
|
+
| `voiceio uninstall` | Remove the service, IBus component, shortcuts and symlinks (asks before deleting your data) |
|
|
87
|
+
|
|
88
|
+
## Your data
|
|
89
|
+
|
|
90
|
+
Everything voiceio keeps is in three directories (they follow `XDG_CONFIG_HOME`, `XDG_STATE_HOME` and `XDG_DATA_HOME`). Files are created `0600`, directories `0700`. Nothing is uploaded. Recordings, decode traces and window titles are **off unless you turn them on** — `voiceio setup` asks whether to keep recordings so voiceio can learn your voice. Logs record sizes and timings, never your words.
|
|
91
|
+
|
|
92
|
+
| Path | Holds | Retention |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| **`~/.config/voiceio/`** | *Settings and what it has learned about your words* | |
|
|
95
|
+
| `config.toml` | All settings | — |
|
|
96
|
+
| `vocabulary.txt` | Your terms, one per line, used as decoder hotwords | Never pruned; rarely used terms rank lower |
|
|
97
|
+
| `vocab_stats.json` | Per-term usage counts used to rank the vocabulary | Rebuilt as you dictate |
|
|
98
|
+
| `corrections.json` | Find/replace rules (`post grass` → `PostgreSQL`) | — |
|
|
99
|
+
| `flagged.txt` | Words flagged with the "correct that" voice command, for review | — |
|
|
100
|
+
| `snapshots/` | Copies of corrections + vocabulary from before 1.0 (safe to delete) | — |
|
|
101
|
+
| `consent.json` | Whether you allowed cloud LLM calls (text only) | — |
|
|
102
|
+
| `hints.json` | Which CLI tips you have already seen | — |
|
|
103
|
+
| **`~/.local/state/voiceio/`** | *What you said* | |
|
|
104
|
+
| `history.jsonl` | Every committed transcript: time, raw and final text (and the focused-window title with `[data] capture_context`) | `[history] enabled`, `max_entries`, `max_age_days` (0 = keep forever) |
|
|
105
|
+
| `recordings/*.wav` | The audio of each utterance, for `voiceio learn` — **opt-in** | `[data] retain_audio` (default off), `max_audio_mb` (default 4096), `min_free_gb` (default 5) |
|
|
106
|
+
| `streaming_trace.jsonl`, `postcorrect_pairs.jsonl` | Per-pass decode text and timings, LLM before/after pairs — **opt-in**, for debugging | `[data] capture_intermediates` (default off); each capped at 64 MB |
|
|
107
|
+
| `voiceio.log`, `worker.log`, `ibus-engine-stderr.log` | Logs | `voiceio.log` rotates at 2 MB × 3 |
|
|
108
|
+
| **`~/.local/share/voiceio/learn/`** | *Personalization corpus* (only exists once you run `voiceio learn`) | Never pruned; delete freely |
|
|
109
|
+
| `labels.jsonl` | Reference transcripts from the teacher model or your review | — |
|
|
110
|
+
| `augment/` | Synthetic TTS clips of your hard words | — |
|
|
111
|
+
| `datasets/vNNNN/` | Frozen train/dev/test splits | — |
|
|
112
|
+
| `exports/` | Datasets packed for training on another machine | — |
|
|
113
|
+
| `models/<run>/` | Your fine-tuned models, plus `promotions.jsonl` | — |
|
|
114
|
+
| `runs/` | Evaluation results | — |
|
|
115
|
+
|
|
116
|
+
Set `[data] capture_context = false` to stop recording window titles. `voiceio uninstall` offers to delete the config and state directories; delete `~/.local/share/voiceio` yourself.
|
|
117
|
+
|
|
118
|
+
## Make it yours
|
|
119
|
+
|
|
120
|
+
Most dictation errors are proper nouns and jargon: `PostgreSQL` heard as `post grass`, a colleague's name spelled three ways. There are three tools for that, from cheapest to most powerful.
|
|
121
|
+
|
|
122
|
+
**1. Vocabulary.** Put your names and terms in `~/.config/voiceio/vocabulary.txt` (or use `voiceio vocab`). They are passed to Whisper as *hotwords* on every decode, ranked by how often you use them. One honest limit: Whisper's hotword channel is capped at 223 tokens, and a proper noun costs 5 to 7 tokens, so only about **35 terms** steer each decode. The rest are kept and ranked, but they do nothing until they rank high enough. This ceiling comes from the model, not from voiceio. [CONTRIBUTING.md](CONTRIBUTING.md#model-choice-why-whisper-and-what-would-change-it) explains why we still use Whisper.
|
|
123
|
+
|
|
124
|
+
**2. Corrections.** Find/replace rules for what still comes out wrong (`voiceio corrections add WRONG RIGHT`, or say "correct that" right after a mistake and review with `voiceio corrections flagged`). `voiceio vocab suggest` lists unusual words from your history — offline — so you can add the real names to your vocabulary and turn the mishearings into corrections.
|
|
125
|
+
|
|
126
|
+
**3. Fine-tuning with `voiceio learn`.** This is how you get past the 35-term ceiling: teach the model your vocabulary directly, from your own retained audio.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
voiceio learn import DIR --source phone # optional: add your own recordings from elsewhere
|
|
130
|
+
voiceio learn label # a stronger teacher model (large-v3-turbo) transcribes your clips
|
|
131
|
+
voiceio learn review # fix the teacher where it matters: your names and terms
|
|
132
|
+
voiceio learn review --test # once: verify the held-out clips, so eval scores against the truth
|
|
133
|
+
voiceio learn augment # synthesize extra examples of rare terms with local TTS
|
|
134
|
+
voiceio learn build # freeze a versioned train/dev/test dataset (the test split never trains)
|
|
135
|
+
voiceio learn eval # score the current model on your held-out clips: WER and term recall
|
|
136
|
+
# --streaming replays them through live dictation and times stop→text
|
|
137
|
+
voiceio learn train # LoRA fine-tune (needs the `train` extra; decoder-only on CPU, --full on a GPU)
|
|
138
|
+
voiceio learn promote <run> # dictate with the fine-tune; `voiceio learn rollback` undoes it
|
|
139
|
+
voiceio learn maintain # later: label what's new, and once 50+ clips piled up, retrain and compare
|
|
140
|
+
voiceio learn schedule on # …or let it run `maintain` every night, and notify you when a model wins
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Labeling, training and offline eval run in an idle-priority cgroup, so they never slow dictation down. Everything stays on your machine unless you choose `train --remote`.
|
|
144
|
+
|
|
145
|
+
`voiceio learn status` shows where you are, each model's scores, and suggests `promote` only when a fine-tune wins on everything. `promote` itself refuses a model that hasn't, and reports how many clips got better or worse with a confidence interval — a few dozen test clips can move an average by luck.
|
|
146
|
+
|
|
147
|
+
**Is it actually helping?** Once some clips are labeled, measure instead of guessing:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
voiceio learn eval --pipeline # what each text stage (numbers, commands, corrections, cloud
|
|
151
|
+
# postcorrect…) did to your past dictations, and its commonest edits
|
|
152
|
+
voiceio corrections audit # rules your own audio contradicts, and ones that look risky
|
|
153
|
+
voiceio learn eval --streaming # accuracy *and* stop→text, replaying clips through live dictation
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
On the author's data these found a correction that kept turning "composable" into "comparable", a number rule writing "no one" as "no 1", and a cloud pass that never fixed a single vocabulary term.
|
|
157
|
+
|
|
158
|
+
## Choose a model
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
voiceio models list # known models, your fine-tunes, and which is active
|
|
162
|
+
voiceio models bench # score candidates on your held-out clips (after `voiceio learn build`)
|
|
163
|
+
voiceio models use medium # switch
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| Model | Runtime | License | Notes |
|
|
167
|
+
|---|---|---|---|
|
|
168
|
+
| `small` | faster-whisper | MIT | Default. About 5× realtime on a laptop CPU |
|
|
169
|
+
| `medium` | faster-whisper | MIT | Better on names, about 2.5× slower |
|
|
170
|
+
| `large-v3-turbo` | faster-whisper | MIT | Best Whisper for dictation; wants a GPU. Also the default `learn` teacher |
|
|
171
|
+
| `distil-large-v3` | faster-whisper | MIT | English only |
|
|
172
|
+
| `sherpa:parakeet-tdt-0.6b-v3` | sherpa-onnx | CC-BY-4.0 | Experimental. Fast, but no vocabulary biasing yet |
|
|
173
|
+
| `whispercpp:http://…` | whisper.cpp server | depends on the model | Experimental. E.g. a Vulkan build on an AMD iGPU |
|
|
174
|
+
|
|
175
|
+
Pick on your own audio, not leaderboards: for dictation full of names, how well a model can be *biased* matters more than its benchmark WER.
|
|
176
|
+
|
|
177
|
+
**Licenses.** voiceio ships no model weights. Each model is downloaded from its own source on first use, under its own license. The defaults are permissive (MIT). A fine-tune you make with `voiceio learn` inherits the license of the base model it was trained from.
|
|
178
|
+
|
|
179
|
+
## Dictate from your phone
|
|
180
|
+
|
|
181
|
+
`python -m voiceio.server` (the `server` extra) serves the same engine over HTTP and WebSocket, for a phone or any other client: `POST /transcribe` with an audio file, or stream PCM over `/ws/transcribe` for live partials. It binds `127.0.0.1` by default; put it behind your VPN or a reverse proxy and set `VOICE_TOKEN` (bearer token) and `VOICE_ALLOWED_ORIGINS` when it is reachable from elsewhere. `VOICE_MODEL`, `VOICE_LANES`, `VOICE_HOST`/`VOICE_PORT` override the rest.
|
|
182
|
+
|
|
183
|
+
The server reads its own machine's voiceio config, so it gets your vocabulary and corrections once you copy them over:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
scripts/sync_personalization.sh myserver # vocabulary + corrections
|
|
187
|
+
scripts/sync_personalization.sh myserver --model # …and your promoted fine-tune
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
To fine-tune on what you dictate from the phone too, opt in on the server with `[data] retain_audio = true` in its `config.toml`, then bring the clips home: `scripts/pull_phone_dictation.sh myserver` (an `rsync` over SSH followed by `voiceio learn import`). Only your own voice should go in: the model learns whoever is speaking.
|
|
191
|
+
|
|
192
|
+
## Linux support
|
|
193
|
+
|
|
194
|
+
| | Text injection | Streaming preview | Hotkey | Status |
|
|
195
|
+
|---|---|---|---|---|
|
|
196
|
+
| GNOME (Wayland) | IBus, ydotool fallback | Yes (IBus preedit) | evdev, or a GNOME shortcut set up by `setup` | Tested daily |
|
|
197
|
+
| GNOME (X11) | IBus, xdotool fallback | Yes | evdev, pynput | Supported |
|
|
198
|
+
| KDE Plasma (Wayland) | IBus, ydotool fallback | Yes with IBus | evdev | Should work |
|
|
199
|
+
| Hyprland, incl. Omarchy | IBus, else wtype → ydotool | Yes with IBus; with fcitx5 (Omarchy's default), words are typed as you speak, without the in-place preview | evdev, or `bind = CTRL ALT, V, exec, voiceio toggle` | Should work |
|
|
200
|
+
| sway | IBus, else wtype → ydotool | As Hyprland | evdev, or `bindsym` + `voiceio toggle` | Should work |
|
|
201
|
+
| i3 / other X11 | IBus, xdotool | Yes with IBus | pynput, evdev | Should work |
|
|
202
|
+
| NixOS | as above | as above | evdev via the flake's udev rule | Flake provided, unbuilt ([NixOS](#nixos)) |
|
|
203
|
+
|
|
204
|
+
**Input methods.** IBus is the only way to get a live, underlined preview that is corrected in place on Wayland. voiceio installs its own IBus engine and only activates it while you dictate. If fcitx5 is your input method, voiceio leaves it alone and types the final text with wtype or ydotool. Terminals that ignore input methods get the clipboard.
|
|
205
|
+
|
|
206
|
+
**Hotkeys without the `input` group.** The evdev backend reads keyboards from `/dev/input`. `voiceio doctor --fix` installs a udev rule, `/etc/udev/rules.d/60-voiceio-uaccess.rules`, that grants the logged-in user access to keyboard devices. It works immediately, without logging out. The old route still works as a fallback: `sudo usermod -aG input $USER`, then log out and back in. You can also skip evdev and bind `voiceio toggle` in your compositor.
|
|
207
|
+
|
|
208
|
+
**ydotool** needs write access to `/dev/uinput`; `voiceio doctor --fix` installs a uaccess rule for that too.
|
|
209
|
+
|
|
210
|
+
### NixOS
|
|
211
|
+
|
|
212
|
+
The repository is a flake. **It has not been built yet**; please report fixes.
|
|
213
|
+
|
|
214
|
+
```nix
|
|
215
|
+
# flake inputs: voiceio.url = "github:Hugo0/voiceio";
|
|
216
|
+
# NixOS: package, uinput, and the keyboard uaccess rule
|
|
217
|
+
imports = [ voiceio.nixosModules.default ];
|
|
218
|
+
programs.voiceio.enable = true;
|
|
219
|
+
|
|
220
|
+
# Home Manager: config.toml from Nix + a systemd user service
|
|
221
|
+
imports = [ voiceio.homeManagerModules.default ];
|
|
222
|
+
services.voiceio = {
|
|
223
|
+
enable = true;
|
|
224
|
+
settings.model.name = "small";
|
|
225
|
+
};
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
For the streaming preview, enable IBus as your input method: `i18n.inputMethod = { enable = true; type = "ibus"; };`.
|
|
229
|
+
|
|
230
|
+
### Windows and macOS
|
|
231
|
+
|
|
232
|
+
There is a best-effort pynput path for both (hotkeys and typing, no live preview). It is untested and unmaintained, with no installers or CI. Patches are welcome; bug reports will likely sit.
|
|
233
|
+
|
|
234
|
+
## Troubleshooting
|
|
235
|
+
|
|
236
|
+
| Problem | Fix |
|
|
237
|
+
|---|---|
|
|
238
|
+
| Nothing is typed | `voiceio doctor --fix`; usually the IBus component or the GNOME input source |
|
|
239
|
+
| Hotkey does nothing on Wayland | `voiceio doctor --fix` installs the keyboard udev rule, or bind `voiceio toggle` in your compositor |
|
|
240
|
+
| `sounddevice is not installed` | You installed without the desktop extra: `pipx install --force 'python-voiceio[desktop]'` |
|
|
241
|
+
| evdev fails to build | Install a C toolchain and Python headers (see Quickstart), then reinstall |
|
|
242
|
+
| Too slow | `voiceio doctor` shows your real stop→text; turn off cloud postcorrect, or `voiceio models use small` (or a GPU with `large-v3-turbo`) |
|
|
243
|
+
| Words come out wrong in a pattern | `voiceio learn eval --pipeline` and `voiceio corrections audit` show which stage or rule did it |
|
|
244
|
+
| Start over | `voiceio uninstall`, then `voiceio setup` |
|
|
245
|
+
|
|
246
|
+
Logs: `journalctl --user -u voiceio` or `~/.local/state/voiceio/voiceio.log`.
|
|
247
|
+
|
|
248
|
+
## Roadmap
|
|
249
|
+
|
|
250
|
+
- **A landing page** — voiceio as local, open-source, private dictation that learns from you.
|
|
251
|
+
- **Hands-off promotion** — `learn schedule` already retrains nightly and tells you when a model wins; next is switching to it automatically, with one-command rollback.
|
|
252
|
+
- **Unbounded vocabulary** — move to a decoder whose biasing has no token cap (see [model choice](CONTRIBUTING.md#model-choice-why-whisper-and-what-would-change-it)).
|
|
253
|
+
- **One model everywhere** — sync your fine-tune to your phone server and laptops, peer to peer.
|
|
254
|
+
|
|
255
|
+
## Contributing
|
|
256
|
+
|
|
257
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the architecture, conventions and the reasoning behind the model choice. Please open an issue before a large PR.
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
MIT. Model weights are not part of voiceio and carry their own licenses (see [Choose a model](#choose-a-model)).
|