tapscribe 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.
- tapscribe-1.1.0/LICENSE +21 -0
- tapscribe-1.1.0/PKG-INFO +399 -0
- tapscribe-1.1.0/README.md +297 -0
- tapscribe-1.1.0/pyproject.toml +295 -0
- tapscribe-1.1.0/setup.cfg +4 -0
- tapscribe-1.1.0/tapscribe/__init__.py +28 -0
- tapscribe-1.1.0/tapscribe/__main__.py +319 -0
- tapscribe-1.1.0/tapscribe/app.py +2197 -0
- tapscribe-1.1.0/tapscribe/audio.py +228 -0
- tapscribe-1.1.0/tapscribe/auth.py +148 -0
- tapscribe-1.1.0/tapscribe/batch_pipeline.py +199 -0
- tapscribe-1.1.0/tapscribe/batch_strip.py +246 -0
- tapscribe-1.1.0/tapscribe/batch_summarize.py +164 -0
- tapscribe-1.1.0/tapscribe/batch_transcribe.py +515 -0
- tapscribe-1.1.0/tapscribe/bridges_catalog.py +37 -0
- tapscribe-1.1.0/tapscribe/chunking.py +76 -0
- tapscribe-1.1.0/tapscribe/config.py +256 -0
- tapscribe-1.1.0/tapscribe/config_store.py +451 -0
- tapscribe-1.1.0/tapscribe/cuda_torch.py +156 -0
- tapscribe-1.1.0/tapscribe/hallucinations.py +207 -0
- tapscribe-1.1.0/tapscribe/install_picker.py +1307 -0
- tapscribe-1.1.0/tapscribe/install_target.py +114 -0
- tapscribe-1.1.0/tapscribe/language_select.py +155 -0
- tapscribe-1.1.0/tapscribe/live.py +1043 -0
- tapscribe-1.1.0/tapscribe/live_control.py +209 -0
- tapscribe-1.1.0/tapscribe/live_relay.py +392 -0
- tapscribe-1.1.0/tapscribe/logging_setup.py +96 -0
- tapscribe-1.1.0/tapscribe/moonshine_live.py +603 -0
- tapscribe-1.1.0/tapscribe/name_resolution.py +238 -0
- tapscribe-1.1.0/tapscribe/nb_whisper.py +193 -0
- tapscribe-1.1.0/tapscribe/people.py +199 -0
- tapscribe-1.1.0/tapscribe/preflight.py +225 -0
- tapscribe-1.1.0/tapscribe/recorder.py +762 -0
- tapscribe-1.1.0/tapscribe/roster.py +120 -0
- tapscribe-1.1.0/tapscribe/runtime_probe.py +194 -0
- tapscribe-1.1.0/tapscribe/session_maintenance.py +528 -0
- tapscribe-1.1.0/tapscribe/session_merge.py +432 -0
- tapscribe-1.1.0/tapscribe/session_paths.py +199 -0
- tapscribe-1.1.0/tapscribe/sessions.py +908 -0
- tapscribe-1.1.0/tapscribe/setup_install.py +226 -0
- tapscribe-1.1.0/tapscribe/setup_state.py +144 -0
- tapscribe-1.1.0/tapscribe/speech_gate.py +336 -0
- tapscribe-1.1.0/tapscribe/strip_silence.py +255 -0
- tapscribe-1.1.0/tapscribe/summarizers/__init__.py +103 -0
- tapscribe-1.1.0/tapscribe/summarizers/api.py +147 -0
- tapscribe-1.1.0/tapscribe/summarizers/base.py +177 -0
- tapscribe-1.1.0/tapscribe/summarizers/catalog.py +413 -0
- tapscribe-1.1.0/tapscribe/summarizers/command.py +181 -0
- tapscribe-1.1.0/tapscribe/summarizers/local.py +234 -0
- tapscribe-1.1.0/tapscribe/tap_fan_out.py +498 -0
- tapscribe-1.1.0/tapscribe/tap_relay.py +338 -0
- tapscribe-1.1.0/tapscribe/text.py +199 -0
- tapscribe-1.1.0/tapscribe/tls.py +123 -0
- tapscribe-1.1.0/tapscribe/transcribers/__init__.py +448 -0
- tapscribe-1.1.0/tapscribe/transcribers/_chunked.py +164 -0
- tapscribe-1.1.0/tapscribe/transcribers/_moonshine_window.py +327 -0
- tapscribe-1.1.0/tapscribe/transcribers/_parakeet_tdt.py +103 -0
- tapscribe-1.1.0/tapscribe/transcribers/_voxtral_common.py +208 -0
- tapscribe-1.1.0/tapscribe/transcribers/base.py +292 -0
- tapscribe-1.1.0/tapscribe/transcribers/catalog.py +862 -0
- tapscribe-1.1.0/tapscribe/transcribers/faster_whisper.py +177 -0
- tapscribe-1.1.0/tapscribe/transcribers/mlx_parakeet.py +217 -0
- tapscribe-1.1.0/tapscribe/transcribers/mlx_voxtral.py +114 -0
- tapscribe-1.1.0/tapscribe/transcribers/mlx_whisper.py +173 -0
- tapscribe-1.1.0/tapscribe/transcribers/moonshine_mlx.py +68 -0
- tapscribe-1.1.0/tapscribe/transcribers/moonshine_onnx.py +80 -0
- tapscribe-1.1.0/tapscribe/transcribers/parakeet.py +172 -0
- tapscribe-1.1.0/tapscribe/transcribers/voxtral.py +137 -0
- tapscribe-1.1.0/tapscribe/wav_append.py +114 -0
- tapscribe-1.1.0/tapscribe/wav_cache.py +599 -0
- tapscribe-1.1.0/tapscribe/wav_predecode.py +62 -0
- tapscribe-1.1.0/tapscribe/web/components/active-taps.html +64 -0
- tapscribe-1.1.0/tapscribe/web/components/config-card.html +35 -0
- tapscribe-1.1.0/tapscribe/web/components/live-channel.html +108 -0
- tapscribe-1.1.0/tapscribe/web/components/live-feed.html +36 -0
- tapscribe-1.1.0/tapscribe/web/components/merged-transcript.html +73 -0
- tapscribe-1.1.0/tapscribe/web/components/next/people.html +49 -0
- tapscribe-1.1.0/tapscribe/web/components/next/recordings.html +185 -0
- tapscribe-1.1.0/tapscribe/web/components/next/sessions.html +138 -0
- tapscribe-1.1.0/tapscribe/web/components/next/spine.html +60 -0
- tapscribe-1.1.0/tapscribe/web/components/next/summary.html +139 -0
- tapscribe-1.1.0/tapscribe/web/components/next/taps.html +103 -0
- tapscribe-1.1.0/tapscribe/web/components/next/views.html +475 -0
- tapscribe-1.1.0/tapscribe/web/dashboard.css +705 -0
- tapscribe-1.1.0/tapscribe/web/js/api.js +480 -0
- tapscribe-1.1.0/tapscribe/web/js/api.test.js +261 -0
- tapscribe-1.1.0/tapscribe/web/js/components/active-taps.js +232 -0
- tapscribe-1.1.0/tapscribe/web/js/components/active-taps.test.js +55 -0
- tapscribe-1.1.0/tapscribe/web/js/components/config-card.js +178 -0
- tapscribe-1.1.0/tapscribe/web/js/components/live-channel.js +322 -0
- tapscribe-1.1.0/tapscribe/web/js/components/live-feed.js +274 -0
- tapscribe-1.1.0/tapscribe/web/js/components/live-feed.test.js +167 -0
- tapscribe-1.1.0/tapscribe/web/js/components/merged-transcript.js +229 -0
- tapscribe-1.1.0/tapscribe/web/js/formatters.js +82 -0
- tapscribe-1.1.0/tapscribe/web/js/lib/chrome.js +75 -0
- tapscribe-1.1.0/tapscribe/web/js/lib/format.js +141 -0
- tapscribe-1.1.0/tapscribe/web/js/lib/render.js +268 -0
- tapscribe-1.1.0/tapscribe/web/js/lib/templates.js +198 -0
- tapscribe-1.1.0/tapscribe/web/js/model-select.js +121 -0
- tapscribe-1.1.0/tapscribe/web/js/model-select.test.js +77 -0
- tapscribe-1.1.0/tapscribe/web/js/next/components/engine.js +102 -0
- tapscribe-1.1.0/tapscribe/web/js/next/components/language-picker.js +38 -0
- tapscribe-1.1.0/tapscribe/web/js/next/components/spine.js +381 -0
- tapscribe-1.1.0/tapscribe/web/js/next/components/spine.test.js +70 -0
- tapscribe-1.1.0/tapscribe/web/js/next/components/summarizer-controls.js +259 -0
- tapscribe-1.1.0/tapscribe/web/js/next/components/waveform.js +251 -0
- tapscribe-1.1.0/tapscribe/web/js/next/components/waveform.test.js +28 -0
- tapscribe-1.1.0/tapscribe/web/js/next/main.js +713 -0
- tapscribe-1.1.0/tapscribe/web/js/next/poll-pacer.js +46 -0
- tapscribe-1.1.0/tapscribe/web/js/next/poll-pacer.test.js +78 -0
- tapscribe-1.1.0/tapscribe/web/js/next/shell.js +326 -0
- tapscribe-1.1.0/tapscribe/web/js/next/shell.test.js +100 -0
- tapscribe-1.1.0/tapscribe/web/js/next/subtitles.js +50 -0
- tapscribe-1.1.0/tapscribe/web/js/next/subtitles.test.js +54 -0
- tapscribe-1.1.0/tapscribe/web/js/next/ui.js +77 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/capture.js +216 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/people.js +245 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/recordings.js +892 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/sessions.js +727 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/settings.js +402 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/summary.js +490 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/taps.js +96 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/transcript.js +798 -0
- tapscribe-1.1.0/tapscribe/web/js/next/views/transcript.test.js +76 -0
- tapscribe-1.1.0/tapscribe/web/js/setup/setup.css +164 -0
- tapscribe-1.1.0/tapscribe/web/js/setup/setup.js +253 -0
- tapscribe-1.1.0/tapscribe/web/js/speakers.js +26 -0
- tapscribe-1.1.0/tapscribe/web/js/templates.js +288 -0
- tapscribe-1.1.0/tapscribe/web/js/types.d.ts +637 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/alert/alert.css +32 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/alert/alert.element.js +14 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/alert/alert.html +10 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/alert/alert.js +61 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/button/button.css +57 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/button/button.element.js +17 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/button/button.html +7 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/button/button.js +81 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/chip/chip.css +44 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/chip/chip.element.js +15 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/chip/chip.html +7 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/chip/chip.js +27 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/empty-state/empty-state.css +19 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/empty-state/empty-state.element.js +10 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/empty-state/empty-state.html +8 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/empty-state/empty-state.js +28 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/field/field.css +41 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/field/field.html +8 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/field/field.js +68 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/panel/panel.css +47 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/panel/panel.html +7 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/panel/panel.js +58 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/progress/progress.css +26 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/progress/progress.element.js +12 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/progress/progress.html +7 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/progress/progress.js +32 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/spinner/spinner.css +28 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/spinner/spinner.element.js +11 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/spinner/spinner.html +7 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/components/spinner/spinner.js +27 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/lib/component.js +42 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/lib/element.js +113 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/lib/templates.js +198 -0
- tapscribe-1.1.0/tapscribe/web/js/vc/lib/tone.js +48 -0
- tapscribe-1.1.0/tapscribe/web/next.css +1322 -0
- tapscribe-1.1.0/tapscribe/web/next.html +52 -0
- tapscribe-1.1.0/tapscribe/web/setup.html +29 -0
- tapscribe-1.1.0/tapscribe/web/tokens.css +55 -0
- tapscribe-1.1.0/tapscribe/web/tones.css +21 -0
- tapscribe-1.1.0/tapscribe.egg-info/PKG-INFO +399 -0
- tapscribe-1.1.0/tapscribe.egg-info/SOURCES.txt +280 -0
- tapscribe-1.1.0/tapscribe.egg-info/dependency_links.txt +1 -0
- tapscribe-1.1.0/tapscribe.egg-info/entry_points.txt +2 -0
- tapscribe-1.1.0/tapscribe.egg-info/requires.txt +96 -0
- tapscribe-1.1.0/tapscribe.egg-info/top_level.txt +1 -0
- tapscribe-1.1.0/tests/test_api_state_etag_quiet_tap.py +204 -0
- tapscribe-1.1.0/tests/test_app_bridges.py +92 -0
- tapscribe-1.1.0/tests/test_audio.py +291 -0
- tapscribe-1.1.0/tests/test_auth.py +93 -0
- tapscribe-1.1.0/tests/test_auth_non_ascii_credentials.py +110 -0
- tapscribe-1.1.0/tests/test_batch_pipeline.py +438 -0
- tapscribe-1.1.0/tests/test_batch_strip.py +117 -0
- tapscribe-1.1.0/tests/test_batch_summarize.py +373 -0
- tapscribe-1.1.0/tests/test_batch_transcribe.py +1211 -0
- tapscribe-1.1.0/tests/test_batch_transcribe_atomic_writes.py +137 -0
- tapscribe-1.1.0/tests/test_bulk_reclaim_audio.py +121 -0
- tapscribe-1.1.0/tests/test_bulk_reclaim_mid_walk_race.py +155 -0
- tapscribe-1.1.0/tests/test_chunking.py +80 -0
- tapscribe-1.1.0/tests/test_cli_flags.py +36 -0
- tapscribe-1.1.0/tests/test_concurrency_races.py +368 -0
- tapscribe-1.1.0/tests/test_config_env.py +99 -0
- tapscribe-1.1.0/tests/test_dashboard_pipeline_trigger.py +206 -0
- tapscribe-1.1.0/tests/test_domain_errors_fastapi_free.py +192 -0
- tapscribe-1.1.0/tests/test_ensure_cuda_torch.py +139 -0
- tapscribe-1.1.0/tests/test_hallucinations.py +249 -0
- tapscribe-1.1.0/tests/test_hallucinations_config_write.py +208 -0
- tapscribe-1.1.0/tests/test_idle_ttl_config.py +194 -0
- tapscribe-1.1.0/tests/test_imports.py +21 -0
- tapscribe-1.1.0/tests/test_install_matrix.py +42 -0
- tapscribe-1.1.0/tests/test_install_picker.py +1442 -0
- tapscribe-1.1.0/tests/test_install_picker_not_imported_by_app.py +111 -0
- tapscribe-1.1.0/tests/test_install_target.py +141 -0
- tapscribe-1.1.0/tests/test_language_select.py +181 -0
- tapscribe-1.1.0/tests/test_live_autostart_default_off.py +113 -0
- tapscribe-1.1.0/tests/test_live_cmd.py +525 -0
- tapscribe-1.1.0/tests/test_live_control.py +213 -0
- tapscribe-1.1.0/tests/test_live_gate_knob_apply.py +174 -0
- tapscribe-1.1.0/tests/test_live_gate_knob_no_restart.py +164 -0
- tapscribe-1.1.0/tests/test_live_matches_noop.py +178 -0
- tapscribe-1.1.0/tests/test_live_relay.py +736 -0
- tapscribe-1.1.0/tests/test_live_supervision.py +626 -0
- tapscribe-1.1.0/tests/test_local_test_bridge.py +104 -0
- tapscribe-1.1.0/tests/test_logging_setup.py +174 -0
- tapscribe-1.1.0/tests/test_main_cli.py +550 -0
- tapscribe-1.1.0/tests/test_moonshine_live.py +792 -0
- tapscribe-1.1.0/tests/test_moonshine_window.py +356 -0
- tapscribe-1.1.0/tests/test_name_resolution.py +232 -0
- tapscribe-1.1.0/tests/test_nb_whisper.py +65 -0
- tapscribe-1.1.0/tests/test_package_bridge.py +61 -0
- tapscribe-1.1.0/tests/test_parakeet_tdt.py +78 -0
- tapscribe-1.1.0/tests/test_people.py +145 -0
- tapscribe-1.1.0/tests/test_people_registry_memoized.py +134 -0
- tapscribe-1.1.0/tests/test_poll_caching.py +277 -0
- tapscribe-1.1.0/tests/test_poll_caching_session_sidecars.py +248 -0
- tapscribe-1.1.0/tests/test_preflight.py +159 -0
- tapscribe-1.1.0/tests/test_recorder.py +99 -0
- tapscribe-1.1.0/tests/test_recorder_subcomponents.py +484 -0
- tapscribe-1.1.0/tests/test_registry_single_source.py +185 -0
- tapscribe-1.1.0/tests/test_resolve_install_state.py +216 -0
- tapscribe-1.1.0/tests/test_roster.py +93 -0
- tapscribe-1.1.0/tests/test_routes.py +3441 -0
- tapscribe-1.1.0/tests/test_runtime_probe.py +105 -0
- tapscribe-1.1.0/tests/test_search_endpoint.py +235 -0
- tapscribe-1.1.0/tests/test_session_active_tap_guard.py +160 -0
- tapscribe-1.1.0/tests/test_session_layout.py +90 -0
- tapscribe-1.1.0/tests/test_session_maintenance_bulk_reclaim.py +231 -0
- tapscribe-1.1.0/tests/test_session_maintenance_fault_injection.py +175 -0
- tapscribe-1.1.0/tests/test_session_merge.py +280 -0
- tapscribe-1.1.0/tests/test_session_merge_selection.py +128 -0
- tapscribe-1.1.0/tests/test_session_merge_stripped_silence_gate.py +127 -0
- tapscribe-1.1.0/tests/test_session_paths_symlink_containment.py +189 -0
- tapscribe-1.1.0/tests/test_sessions_path_safety.py +92 -0
- tapscribe-1.1.0/tests/test_setup_install.py +281 -0
- tapscribe-1.1.0/tests/test_setup_state.py +191 -0
- tapscribe-1.1.0/tests/test_speech_gate.py +405 -0
- tapscribe-1.1.0/tests/test_strip_silence.py +178 -0
- tapscribe-1.1.0/tests/test_strip_silence_cli.py +88 -0
- tapscribe-1.1.0/tests/test_strip_silence_split.py +502 -0
- tapscribe-1.1.0/tests/test_summarizers.py +306 -0
- tapscribe-1.1.0/tests/test_summarizers_api.py +229 -0
- tapscribe-1.1.0/tests/test_summarizers_local.py +486 -0
- tapscribe-1.1.0/tests/test_tap_endpoint.py +1176 -0
- tapscribe-1.1.0/tests/test_tap_fan_out.py +1257 -0
- tapscribe-1.1.0/tests/test_tap_fan_out_chaos.py +265 -0
- tapscribe-1.1.0/tests/test_tap_fan_out_fault_injection.py +223 -0
- tapscribe-1.1.0/tests/test_tap_fan_out_lifecycle_safety.py +348 -0
- tapscribe-1.1.0/tests/test_tap_fan_out_probe_identity.py +195 -0
- tapscribe-1.1.0/tests/test_tap_fan_out_resume_append.py +155 -0
- tapscribe-1.1.0/tests/test_tap_relay.py +666 -0
- tapscribe-1.1.0/tests/test_text.py +468 -0
- tapscribe-1.1.0/tests/test_text_module_is_pure.py +184 -0
- tapscribe-1.1.0/tests/test_tls.py +71 -0
- tapscribe-1.1.0/tests/test_transcriber_lease.py +200 -0
- tapscribe-1.1.0/tests/test_transcribers_base.py +281 -0
- tapscribe-1.1.0/tests/test_transcribers_cache_eviction.py +209 -0
- tapscribe-1.1.0/tests/test_transcribers_catalog.py +724 -0
- tapscribe-1.1.0/tests/test_transcribers_factory.py +254 -0
- tapscribe-1.1.0/tests/test_transcribers_faster_whisper.py +223 -0
- tapscribe-1.1.0/tests/test_transcribers_mlx_moonshine.py +117 -0
- tapscribe-1.1.0/tests/test_transcribers_mlx_parakeet.py +448 -0
- tapscribe-1.1.0/tests/test_transcribers_mlx_voxtral.py +210 -0
- tapscribe-1.1.0/tests/test_transcribers_mlx_whisper.py +174 -0
- tapscribe-1.1.0/tests/test_transcribers_onnx_moonshine.py +121 -0
- tapscribe-1.1.0/tests/test_transcribers_parakeet.py +240 -0
- tapscribe-1.1.0/tests/test_transcribers_voxtral.py +278 -0
- tapscribe-1.1.0/tests/test_transcribers_voxtral_common.py +209 -0
- tapscribe-1.1.0/tests/test_version_consistency.py +32 -0
- tapscribe-1.1.0/tests/test_voxtral_text.py +93 -0
- tapscribe-1.1.0/tests/test_wav_append.py +132 -0
- tapscribe-1.1.0/tests/test_wav_cache.py +582 -0
- tapscribe-1.1.0/tests/test_wav_cache_atomic_writes.py +251 -0
- tapscribe-1.1.0/tests/test_wav_cache_inflight_append.py +114 -0
- tapscribe-1.1.0/tests/test_wav_predecode.py +52 -0
tapscribe-1.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TapScribe contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
tapscribe-1.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tapscribe
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Local-first transcription recorder + operator dashboard built on Whisper.
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 TapScribe contributors
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Project-URL: Homepage, https://github.com/Vortiago/TapScribe
|
|
28
|
+
Project-URL: Repository, https://github.com/Vortiago/TapScribe
|
|
29
|
+
Project-URL: Issues, https://github.com/Vortiago/TapScribe/issues
|
|
30
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
31
|
+
Classifier: Operating System :: OS Independent
|
|
32
|
+
Classifier: Programming Language :: Python :: 3
|
|
33
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
37
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
38
|
+
Requires-Python: >=3.12
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
License-File: LICENSE
|
|
41
|
+
Requires-Dist: fastapi>=0.110
|
|
42
|
+
Requires-Dist: uvicorn>=0.27
|
|
43
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
44
|
+
Requires-Dist: numpy>=1.24
|
|
45
|
+
Requires-Dist: websockets>=12
|
|
46
|
+
Requires-Dist: cryptography>=42
|
|
47
|
+
Requires-Dist: silero-vad[onnx-cpu]>=5.0
|
|
48
|
+
Requires-Dist: torch>=2.1
|
|
49
|
+
Provides-Extra: whisper-live
|
|
50
|
+
Requires-Dist: whisperlivekit>=0.1; extra == "whisper-live"
|
|
51
|
+
Provides-Extra: whisper-cpu
|
|
52
|
+
Requires-Dist: faster-whisper>=1.0; extra == "whisper-cpu"
|
|
53
|
+
Provides-Extra: whisper-mlx
|
|
54
|
+
Requires-Dist: mlx-whisper>=0.4; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "whisper-mlx"
|
|
55
|
+
Provides-Extra: voxtral-cpu
|
|
56
|
+
Requires-Dist: transformers>=4.46; extra == "voxtral-cpu"
|
|
57
|
+
Requires-Dist: torch>=2.1; extra == "voxtral-cpu"
|
|
58
|
+
Requires-Dist: mistral-common>=1.5; extra == "voxtral-cpu"
|
|
59
|
+
Provides-Extra: parakeet-cpu
|
|
60
|
+
Requires-Dist: transformers<6,>=5.12; extra == "parakeet-cpu"
|
|
61
|
+
Requires-Dist: librosa>=0.10; extra == "parakeet-cpu"
|
|
62
|
+
Requires-Dist: torch>=2.1; extra == "parakeet-cpu"
|
|
63
|
+
Provides-Extra: parakeet-mlx
|
|
64
|
+
Requires-Dist: parakeet-mlx<0.6,>=0.5; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "parakeet-mlx"
|
|
65
|
+
Provides-Extra: moonshine-mlx
|
|
66
|
+
Requires-Dist: mlx-audio<0.5,>=0.4.1; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "moonshine-mlx"
|
|
67
|
+
Provides-Extra: moonshine-cpu
|
|
68
|
+
Requires-Dist: useful-moonshine-onnx<20270101,>=20251120; extra == "moonshine-cpu"
|
|
69
|
+
Provides-Extra: cuda-libs
|
|
70
|
+
Requires-Dist: nvidia-cublas-cu12; sys_platform != "darwin" and extra == "cuda-libs"
|
|
71
|
+
Requires-Dist: nvidia-cudnn-cu12; sys_platform != "darwin" and extra == "cuda-libs"
|
|
72
|
+
Provides-Extra: summarize
|
|
73
|
+
Requires-Dist: mlx-lm<0.33,>=0.31; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "summarize"
|
|
74
|
+
Requires-Dist: llama-cpp-python<0.4,>=0.3.26; (sys_platform != "darwin" or platform_machine != "arm64") and extra == "summarize"
|
|
75
|
+
Requires-Dist: huggingface-hub>=0.24; extra == "summarize"
|
|
76
|
+
Provides-Extra: whisper
|
|
77
|
+
Requires-Dist: tapscribe[whisper-cpu,whisper-live,whisper-mlx]; extra == "whisper"
|
|
78
|
+
Provides-Extra: mlx
|
|
79
|
+
Requires-Dist: tapscribe[whisper-mlx]; extra == "mlx"
|
|
80
|
+
Provides-Extra: voxtral
|
|
81
|
+
Requires-Dist: tapscribe[voxtral-cpu]; extra == "voxtral"
|
|
82
|
+
Provides-Extra: parakeet
|
|
83
|
+
Requires-Dist: tapscribe[parakeet-mlx]; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "parakeet"
|
|
84
|
+
Requires-Dist: tapscribe[parakeet-cpu]; (sys_platform != "darwin" or platform_machine != "arm64") and extra == "parakeet"
|
|
85
|
+
Provides-Extra: moonshine
|
|
86
|
+
Requires-Dist: tapscribe[moonshine-mlx]; (sys_platform == "darwin" and platform_machine == "arm64") and extra == "moonshine"
|
|
87
|
+
Requires-Dist: tapscribe[moonshine-cpu]; (sys_platform != "darwin" or platform_machine != "arm64") and extra == "moonshine"
|
|
88
|
+
Provides-Extra: dev
|
|
89
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
90
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
91
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
92
|
+
Requires-Dist: httpx>=0.27; extra == "dev"
|
|
93
|
+
Requires-Dist: hypothesis>=6.100; extra == "dev"
|
|
94
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
95
|
+
Requires-Dist: bandit>=1.7; extra == "dev"
|
|
96
|
+
Requires-Dist: pip-audit>=2.7; extra == "dev"
|
|
97
|
+
Requires-Dist: sounddevice>=0.4; extra == "dev"
|
|
98
|
+
Requires-Dist: soundfile>=0.12; extra == "dev"
|
|
99
|
+
Requires-Dist: scipy>=1.10; extra == "dev"
|
|
100
|
+
Requires-Dist: playwright>=1.40; extra == "dev"
|
|
101
|
+
Dynamic: license-file
|
|
102
|
+
|
|
103
|
+
# TapScribe
|
|
104
|
+
|
|
105
|
+
Local transcription recorder and operator dashboard.
|
|
106
|
+
|
|
107
|
+
TapScribe records one WAV per utterance per speaker over a WebSocket, runs
|
|
108
|
+
Whisper, Voxtral, or Parakeet batch transcription on demand, and supervises a
|
|
109
|
+
[WhisperLiveKit](https://github.com/QuentinFuxa/WhisperLiveKit) child process
|
|
110
|
+
for live captions. Nothing leaves the machine.
|
|
111
|
+
|
|
112
|
+
A FastAPI app serves a REST API and a dashboard at `/`:
|
|
113
|
+
|
|
114
|
+
- Start, stop, and restart `whisperlivekit-server` from the dashboard.
|
|
115
|
+
- One WAV per utterance per speaker, written to `recordings/<session>/`.
|
|
116
|
+
- Re-transcribe single WAVs or merge a whole session into one transcript.
|
|
117
|
+
- Hallucination filter with substring, `exact:`, and `re:` rules. Suppressed
|
|
118
|
+
segments are kept in an audit array.
|
|
119
|
+
- Optional silero-VAD pass writes trimmed copies to `<session>/stripped/`.
|
|
120
|
+
Originals are not touched.
|
|
121
|
+
- Summarize a session's merged transcript — bundled local model, an
|
|
122
|
+
operator CLI, or an OpenAI-compatible API — and persist the result.
|
|
123
|
+
- End-of-meeting pipeline: strip → transcribe → summarize as one job, so a
|
|
124
|
+
Bridge can take a session from raw WAVs to a summary with no operator
|
|
125
|
+
in the loop.
|
|
126
|
+
- People registry: a cross-session identity → display-name map, with
|
|
127
|
+
merge/detach, so the same speaker keeps one name across meetings.
|
|
128
|
+
|
|
129
|
+
Audio reaches TapScribe via a *bridge*: usually a browser extension that taps
|
|
130
|
+
the meeting platform's audio tracks and forwards raw PCM over WebSocket. The
|
|
131
|
+
included bridge, `spacialchat-bridge/`, targets spatial.chat. See
|
|
132
|
+
[`bridges/README.md`](bridges/README.md) for the wire protocol if you want to
|
|
133
|
+
add another.
|
|
134
|
+
|
|
135
|
+
## Dashboard
|
|
136
|
+
|
|
137
|
+
One operator console at `/` — the "Stages" UI. A slim left spine
|
|
138
|
+
navigates the global views (Taps · Sessions · People · Settings) and the
|
|
139
|
+
per-session journey (Capture → Recordings → Transcript → Summary); the
|
|
140
|
+
active-taps rail on the right follows you across views. Live captions
|
|
141
|
+
stream in Capture; silence-stripping and the per-WAV files live in
|
|
142
|
+
Recordings; the **▶ transcribe range** button, the meeting-languages
|
|
143
|
+
declaration (you declare the meeting's languages, not a model — ADR-0011),
|
|
144
|
+
and the merged transcript live in Transcript; the global live and batch
|
|
145
|
+
engine pickers live in Settings.
|
|
146
|
+
|
|
147
|
+

|
|
148
|
+
|
|
149
|
+
The screenshot is captured live by the browser E2E test described
|
|
150
|
+
under [Tests](#tests), running the real Apollo 11 audio fixture
|
|
151
|
+
through the bridge and a real `faster-whisper` `tiny.en`.
|
|
152
|
+
Whisper self-flagged the imperfect output as low-confidence; bigger
|
|
153
|
+
models clean that up considerably.
|
|
154
|
+
|
|
155
|
+
## Quick start (macOS / Linux)
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
bash start.sh # localhost only
|
|
159
|
+
bash start.sh --lan # bind 0.0.0.0
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The script finds Python 3.12+, creates `.venv`, installs dependencies
|
|
163
|
+
(`whisperlivekit`, `python-multipart`, `transformers`, plus `mlx-whisper` on
|
|
164
|
+
Apple Silicon), and launches the TapScribe recorder on port 8001. Live
|
|
165
|
+
captions are **off by default**: start `whisperlivekit-server` from the
|
|
166
|
+
dashboard (or boot with it running via `--auto-live`). When live is running,
|
|
167
|
+
the recorder supervises it as a child on an ephemeral internal port (pin one
|
|
168
|
+
with `SX_PORT_WLK`); child logs are prefixed `[wlk]`. Ctrl+C stops the
|
|
169
|
+
recorder and any child.
|
|
170
|
+
|
|
171
|
+
On first run, pick transcription models in the **browser setup screen**: open
|
|
172
|
+
`http://localhost:8001/setup` (`/` redirects there until a model is installed)
|
|
173
|
+
and choose Whisper / Voxtral / Parakeet — the page installs them. `/setup`
|
|
174
|
+
doubles as a "manage models" surface. Headless hosts can pass
|
|
175
|
+
`--non-interactive` to install the saved/default selection without the browser.
|
|
176
|
+
|
|
177
|
+
Open `http://localhost:8001/`. On first run two secrets are generated and
|
|
178
|
+
printed:
|
|
179
|
+
|
|
180
|
+
- A dashboard password for HTTP Basic auth, persisted to `.auth-password`.
|
|
181
|
+
- A `/tap` bearer token for the bridge, persisted to `.tap-token`. Paste it
|
|
182
|
+
into the bridge popup along with the host and port.
|
|
183
|
+
|
|
184
|
+
Rotate with `.venv/bin/tapscribe --rotate-password` or `--rotate-tap-token`
|
|
185
|
+
(these are `tapscribe` flags, not `start.sh` flags). Pass `--tls` to `start.sh`
|
|
186
|
+
to serve `https://` and `wss://`; a self-signed cert is generated on first boot
|
|
187
|
+
(`.tapscribe-cert.pem`, `.tapscribe-key.pem`) and reused after. Supply your
|
|
188
|
+
own with `--cert <path> --key <path>`.
|
|
189
|
+
|
|
190
|
+
## Windows
|
|
191
|
+
|
|
192
|
+
### Windows Bundle (no Python needed)
|
|
193
|
+
|
|
194
|
+
Download **`TapScribe-Setup-win-x64.exe`** from the
|
|
195
|
+
[latest release](https://github.com/Vortiago/TapScribe/releases/latest) and run
|
|
196
|
+
it. It installs per-user (no admin prompt) and needs no Python, no checkout, and
|
|
197
|
+
no PowerShell — it carries its own interpreter. A tray icon starts the
|
|
198
|
+
dashboard, and its **Copy password** item gives you the generated dashboard
|
|
199
|
+
login on first run.
|
|
200
|
+
|
|
201
|
+
The Bundle is **unsigned**, so SmartScreen shows "Windows protected your PC".
|
|
202
|
+
Click **More info → Run anyway**.
|
|
203
|
+
|
|
204
|
+
Program files land in `%LOCALAPPDATA%\Programs\TapScribe`; your recordings,
|
|
205
|
+
transcripts and settings live separately in `%USERPROFILE%\TapScribe`, so
|
|
206
|
+
uninstalling never deletes them. Model weights are cached in
|
|
207
|
+
`%USERPROFILE%\.cache\huggingface`.
|
|
208
|
+
|
|
209
|
+
See [packaging/README.md](packaging/README.md) for what's in the Bundle and
|
|
210
|
+
[ADR-0015](docs/adr/0015-windows-bundle-embedded-interpreter.md) for why it
|
|
211
|
+
embeds an interpreter instead of freezing to a single binary.
|
|
212
|
+
|
|
213
|
+
### From a checkout (developers)
|
|
214
|
+
|
|
215
|
+
```powershell
|
|
216
|
+
.\start.ps1
|
|
217
|
+
.\start.ps1 -Lan
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Configuration
|
|
221
|
+
|
|
222
|
+
Eight files under `config/` shape transcription, live captions, and
|
|
223
|
+
summarization; all are re-read on every job. Most are editable from the
|
|
224
|
+
dashboard's Settings view instead of by hand.
|
|
225
|
+
|
|
226
|
+
| File | Shapes | Format |
|
|
227
|
+
|---|---|---|
|
|
228
|
+
| `config/prompt.txt` | Batch `initial_prompt` | Prose under ~150 words. Biases style and vocabulary. |
|
|
229
|
+
| `config/hotwords.txt` | Batch `hotwords` | Comma- or space-separated proper nouns. faster-whisper only. |
|
|
230
|
+
| `config/hallucinations.txt` | Post-decode suppression | substring, `exact:`, or `re:`. Matches are kept in an audit array. |
|
|
231
|
+
| `config/live-prompt.txt` | Live `--init-prompt` | Same prose format; independent of `prompt.txt`. |
|
|
232
|
+
| `config/live-model.txt` | Default live-channel model | Model id; the live channel adopts it on (re)start. |
|
|
233
|
+
| `config/batch-model.txt` | Default batch model (generalist) | Model id; what the end-of-meeting pipeline transcribes with. |
|
|
234
|
+
| `config/languages.txt` | Candidate languages (ADR-0010) | Comma-separated ISO codes; default `da,no,en`. |
|
|
235
|
+
| `config/summarizer.json` | Default summarizer | JSON: source, command/model/base_url, prompt. `api_key` is write-only. |
|
|
236
|
+
|
|
237
|
+
Templates: `config/prompt.example.txt`, `config/hotwords.example.txt`.
|
|
238
|
+
`config/hallucinations.txt` ships with rules for common YouTube-trained
|
|
239
|
+
Whisper hallucinations.
|
|
240
|
+
|
|
241
|
+
## Architecture
|
|
242
|
+
|
|
243
|
+
One backend, one supervised child, N bridges. Audio flows in over WebSocket;
|
|
244
|
+
captions and recordings come out.
|
|
245
|
+
|
|
246
|
+
```mermaid
|
|
247
|
+
flowchart LR
|
|
248
|
+
subgraph Meeting["Meeting platform (e.g. spatial.chat)"]
|
|
249
|
+
Bridge["Bridge<br/>(browser extension<br/>or native helper)"]
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
subgraph Host["TapScribe host"]
|
|
253
|
+
Backend["TapScribe backend<br/>FastAPI :8001<br/>/tap · /api · dashboard"]
|
|
254
|
+
WLK["whisperlivekit-server<br/>(supervised child, internal port)"]
|
|
255
|
+
WAVs[("recordings/<br/><session>/*.wav")]
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
Operator["Operator browser<br/>(dashboard)"]
|
|
259
|
+
|
|
260
|
+
Bridge -- "PCM 16k mono<br/>over WS /tap" --> Backend
|
|
261
|
+
Backend -- "forwards PCM" --> WLK
|
|
262
|
+
WLK -- "settled live captions" --> Backend
|
|
263
|
+
Backend -- "one WAV per utterance" --> WAVs
|
|
264
|
+
Operator <-- "HTTPS (500 ms /api/state poll)" --> Backend
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
- **Bridges** tap a meeting platform's audio and stream raw PCM to `/tap`.
|
|
268
|
+
One WebSocket per speaker per utterance. See [`bridges/README.md`](bridges/README.md).
|
|
269
|
+
- **Backend** (`tapscribe/`) fans each PCM frame out to two sinks: a
|
|
270
|
+
per-utterance WAV on disk, and an internal relay to the supervised
|
|
271
|
+
WhisperLiveKit child for live captions. It also serves the operator
|
|
272
|
+
dashboard.
|
|
273
|
+
- **WhisperLiveKit** runs as a child process the backend starts, stops, and
|
|
274
|
+
restarts from the dashboard. Bridges never talk to it directly.
|
|
275
|
+
|
|
276
|
+
### Audio pipeline (per utterance)
|
|
277
|
+
|
|
278
|
+
One `/tap` WebSocket = one utterance. Each PCM frame is tee'd: appended to
|
|
279
|
+
the per-utterance WAV on disk **and** forwarded to the WhisperLiveKit child
|
|
280
|
+
for live captions. Settled caption lines flow back to the operator
|
|
281
|
+
dashboard. WAV writing is independent of the live relay — if WhisperLiveKit
|
|
282
|
+
is down, recording still works.
|
|
283
|
+
|
|
284
|
+
```mermaid
|
|
285
|
+
sequenceDiagram
|
|
286
|
+
autonumber
|
|
287
|
+
participant B as Bridge
|
|
288
|
+
participant T as /tap handler
|
|
289
|
+
participant W as WAV file
|
|
290
|
+
participant R as WlKRelay
|
|
291
|
+
participant L as WhisperLiveKit
|
|
292
|
+
participant D as Dashboard
|
|
293
|
+
|
|
294
|
+
B->>T: open /tap?identity&name<br/>(one WS per utterance)
|
|
295
|
+
T->>W: open recordings/<session>/<utt>.wav
|
|
296
|
+
T->>R: connect to WhisperLiveKit
|
|
297
|
+
|
|
298
|
+
loop each PCM frame (16 kHz mono s16le)
|
|
299
|
+
B->>T: PCM bytes
|
|
300
|
+
T->>W: append frame
|
|
301
|
+
T->>R: forward frame
|
|
302
|
+
R->>L: PCM
|
|
303
|
+
L-->>R: settled caption line
|
|
304
|
+
R-->>T: on_settled_line(text)
|
|
305
|
+
T-->>D: push to live feed
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
B->>T: close (mute / leave)
|
|
309
|
+
T->>W: finalise WAV<br/>(or delete if empty)
|
|
310
|
+
T->>R: close
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## After the meeting
|
|
314
|
+
|
|
315
|
+
- **Summarize** (`POST /api/sessions/{session}/summarize`) turns a session's
|
|
316
|
+
merged transcript into a summary via a bundled local model, an operator
|
|
317
|
+
CLI (`command`), or an OpenAI-compatible API (`api`, e.g. Ollama). The
|
|
318
|
+
summary and the operator's default source/model/prompt both persist
|
|
319
|
+
(`session-summary.json`, `config/summarizer.json`).
|
|
320
|
+
- **End-of-meeting pipeline** (`POST`/`GET /api/tap/sessions/{session}/pipeline`)
|
|
321
|
+
chains strip → transcribe → summarize as one job. A Bridge triggers it
|
|
322
|
+
and polls it with the tap bearer token — no dashboard needed.
|
|
323
|
+
- **People** (`/api/people*`) is the cross-session identity → display-name
|
|
324
|
+
registry: every new speaker auto-gets a Person, merge/detach combine or
|
|
325
|
+
split them, and a per-session alias can override the name for one meeting.
|
|
326
|
+
|
|
327
|
+
See [CONTEXT.md](CONTEXT.md) for the full model (Bracketed meeting, Detached
|
|
328
|
+
session, Person/Identity/Roster).
|
|
329
|
+
|
|
330
|
+
## Backends
|
|
331
|
+
|
|
332
|
+
| Family | Models | Backend | Languages | Notes |
|
|
333
|
+
|---|---|---|---|---|
|
|
334
|
+
| Whisper | `tiny(.en)`/`base(.en)`/`small(.en)`/`medium(.en)`, `large-v3`, `large-v3-turbo` | mlx-whisper (AS) / faster-whisper | English-only suffixes; else multilingual | `large-v3-turbo` is the default generalist (ADR-0010). |
|
|
335
|
+
| NB-Whisper | `nb-whisper-tiny`/`base`/`small`/`medium`/`large` | faster-whisper on CT2 weights | Norwegian | Pulled from `NbAiLab/nb-whisper-*/ct2/`. No MLX. |
|
|
336
|
+
| Voxtral | `voxtral-mini` | mlx-voxtral (AS) / HF transformers | EN/ES/FR/PT/HI/DE/NL/IT | Batch-only (no live channel yet). First load downloads ~6 GB. |
|
|
337
|
+
| Parakeet | `parakeet-tdt-0.6b-v3` | parakeet-mlx (AS) / HF transformers | 25 EU languages, no Norwegian | Batch-only (no live channel yet); replaced Canary (ADR-0006). |
|
|
338
|
+
| Moonshine | `moonshine-tiny`/`base` | mlx-audio (AS) / ONNX-CPU (`useful-moonshine-onnx`) | English | Live-only, lightweight low-latency captions — `MoonshineLiveChannel`. Install via `[moonshine-mlx]` / `[moonshine-cpu]` (picker: "Moonshine"). |
|
|
339
|
+
|
|
340
|
+
On Apple Silicon, live and batch both route through mlx-whisper by default.
|
|
341
|
+
Pass `--no-mlx` to opt out.
|
|
342
|
+
|
|
343
|
+
## Tests
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
pip install -e ".[dev]"
|
|
347
|
+
python -m pytest -q
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Four layers:
|
|
351
|
+
|
|
352
|
+
- **Unit + route tests** (`tests/test_*.py`) cover pure helpers
|
|
353
|
+
(hallucination filter, prompt/hotwords reading, slug parsing, WAV I/O,
|
|
354
|
+
model routing) and FastAPI routes via `TestClient`. Whisper / Voxtral
|
|
355
|
+
backends are stubbed; the suite stays under 20 s.
|
|
356
|
+
- **HTTP pipeline E2E** (`tests/e2e/test_pipeline_e2e.py`) boots a real
|
|
357
|
+
uvicorn server, streams two synthetic WAVs concurrently through real
|
|
358
|
+
`/tap` WebSockets, then walks every dashboard HTTP route to verify
|
|
359
|
+
the recorder finalised the WAVs, fanned settled lines into the live
|
|
360
|
+
feed, and produced a merged session transcript. Uses a
|
|
361
|
+
`FakeTranscriber` so the test runs without faster-whisper installed.
|
|
362
|
+
- **Real-Whisper E2E** (same file, `test_pipeline_with_real_whisper`)
|
|
363
|
+
streams committed CC-licensed audio fixtures (Apollo 11 English, Marlene
|
|
364
|
+
Dietrich Norwegian) through the bridge and runs real `faster-whisper`
|
|
365
|
+
on what the recorder wrote. Skipped automatically when
|
|
366
|
+
`faster-whisper` isn't installed. See
|
|
367
|
+
[`tests/fixtures/audio/README.md`](tests/fixtures/audio/README.md) for
|
|
368
|
+
licence details and how to add more clips.
|
|
369
|
+
- **Dashboard UI E2E** (`tests/e2e/test_dashboard_ui.py`) launches
|
|
370
|
+
headless Chromium via Playwright against the running server and
|
|
371
|
+
asserts on actual DOM. Two variants:
|
|
372
|
+
- The fast plumbing check (synthetic WAVs + `FakeTranscriber`)
|
|
373
|
+
verifies taps-rail rows appear while bridges stream, settled
|
|
374
|
+
lines land in Capture's captions feed with correct per-speaker
|
|
375
|
+
attribution, and Transcript's **▶ transcribe range** button
|
|
376
|
+
renders the merged transcript with both speakers' text — plus the
|
|
377
|
+
alias-applied copy-to-clipboard contract.
|
|
378
|
+
- The real-audio check (`@pytest.mark.real_audio`) streams the
|
|
379
|
+
committed Apollo 11 fixture through the bridge, clicks the same
|
|
380
|
+
button, and waits for real `faster-whisper` to produce a merged
|
|
381
|
+
transcript in the UI. This is what produces the screenshot in
|
|
382
|
+
the [Dashboard](#dashboard) section above.
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
pip install -e ".[dev]" && python -m playwright install chromium
|
|
386
|
+
python -m pytest tests/e2e/test_dashboard_ui.py
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
- **Bridge browser E2E** (`tests/e2e/test_bridge_extension_e2e.py`,
|
|
390
|
+
`test_bridge_meeting_e2e.py`) loads the real MV3 extension in a headed
|
|
391
|
+
Chromium to test the tap/mute/pipeline flow end to end. Needs a display
|
|
392
|
+
(`xvfb-run -a python -m pytest ... -m browser_e2e`); self-skips without one.
|
|
393
|
+
|
|
394
|
+
GitHub Actions runs the suite and `ruff check` on every push and PR across
|
|
395
|
+
Python 3.12-3.14 on Ubuntu, macOS, and Windows.
|
|
396
|
+
|
|
397
|
+
## License
|
|
398
|
+
|
|
399
|
+
MIT. See [LICENSE](LICENSE).
|