Tags give the ability to mark specific points in history as being important
-
v2.2.28-beta2
protectedc8fb5685 · ·v2.2.28-beta2 — voiceprint identity fixes + selfcheck threshold tune Follows the 2026-09-18 voiceprint DB audit which found 23 base names duplicated as 'Name / Name 2 / Name 3' across meetings. Root cause: same-person WeSpeaker embeddings drift 0.05-0.55 cos across sessions (mic/room/codec differences), well below the 0.72 hard-match threshold — so auto-enroll silently spawned fresh guest-name records with numeric suffixes on every meeting. Four coordinated fixes: Embedding stability Canonical pre-WeSpeaker normalization: every embed() runs input through HP-60Hz + energy-gated RMS to -20 dBFS + safety clip. Decouples voice identity from recording gain / rumble / room — same voice through headset vs loopback vs conf-room mic should now produce embeddings that cluster tighter. Matching Multi-centroid via top-K mean of per-sample cosines instead of centroid-only. K=3 (env SCRIBEAIR_MATCH_TOPK). Safety guards: min 8 samples required before multi kicks in; boost capped at +0.20 above the aggregate cos so a polluted DB record can't false-positive uncapped. identify_clusters + new identify_loose both use it. Env SCRIBEAIR_MATCH_MULTI=0 for legacy behaviour. Enrollment Identify-before-enroll gate: before store.enroll() creates a new speaker record, ask identify_loose(centroid, 0.45) whether an existing voice matches at a loose threshold (below the 0.72 hard tier). If yes, append the cluster's samples to that speaker via add_sample() instead of spawning 'Name 2'. Threshold sits above typical different-speaker cos (0.05-0.30 on our DB) and catches drift-affected same-person matches like Максим ↔ Максим 2 (0.549). Env SCRIBEAIR_ENROLL_LOOSE_THR=0 disables. Diarizer split guard Cluster-merge threshold in _resolve_speaker_names lowered 0.85 → 0.75. Within a single session the audio path is identical, so same-speaker clusters group tighter than the cross-session 0.85 anticipated. Catches same-day splits like Павел 2 + Павел 3 (measured cos 0.875) without collapsing distinct in-session voices. Also * selfcheck C7 (Stage O RTF) gate 0.05 → 0.06 to eliminate the intermittent false-fail hovering at 0.049-0.053 under ambient GPU load. Still 4-12× headroom over healthy CUDA. * tools/consolidate_voiceprints.py — one-shot cleanup for existing duplicate speaker records. dry-run by default; --apply backs up the DB and merges only same-name pairs with cos ≥ 0.72. Verified * pytest 47/47 pass on affected test modules (test_diarization, test_transcriber, test_finalize_v2_dual_track, test_audio_processor) * dev selfcheck --strict 8/8 pass on venv-gpu (CUDA) -
v2.2.27-beta2
protectedfcb1deae · ·v2.2.27-beta2 — post-ASR filters + CPU cascade inversion + sliding AGC Substantial iteration over beta1. Headline changes: Audio & ASR * Sliding BS.1770-style AGC replaces one-shot gain — quiet speakers on multi-speaker conferences no longer get dropped by Whisper VAD (Пк тест 2026-08-05: 13:30 of 149-min meeting was lost by default Silero threshold). * Silero VAD threshold 0.5 → 0.35, min_silence 300/500 → 800/1000 ms. * CPU cascade inversion: GigaAM primary on CPU + RU/auto (5-30× faster than Whisper for the same RU quality). Whisper stays lazy fallback for empty results / EN. Configurable via cascade_primary=auto|whisper|gigaam. * Whisper CPU threads cap 16 → 4 (int8 GEMM saturates early). DiariZen / WeSpeaker capped at 8 (16 fights parallel workers). Diarization * DiariZen int8 segmentation model default (282 MB → 98 MB, +10% CPU speed, posterior cosine 1.0000). * NME-SC clustering (Park & Han 2019) replaces silhouette default — fixes both over-split (Мистраль 7→8-9) and under-split (Пк тест 10→2) failures on WeSpeaker embeddings. * Overlap-aware word→turn assignment kills 148 empty 'Анна?' turns on Пк тест 2026-08-06. * Honest speaker labels — 'Спикер N (Ж)' instead of 'Виктор?' pseudo-real-name pool (mymeet.ai convention). * Trust ANY resolved speaker_name — dropped string-based pool filter that wiped 11 hard-tier voiceprint matches on Мистраль. Post-ASR quality (all opt-in, disabled by default) * spellfix: pymorphy3 + SymSpell repairs Whisper transliteration errors (подскажки → подсказки, лицензыи → лицензии). * llm_cleanup: local Ollama post-pass (gemma3:12b) restores punctuation, ё, capitalization. ~17 min on 149-min file. * summarizer: Sumy TextRank/LexRank/LSA extractive TL;DR, fully offline. Rendered as fenced ## TL;DR block in MD export. * wav2vec2 CTC forced alignment: refines Whisper word timings ±200 ms → ±20-40 ms. Critical for overlap-heavy conferences. Meeting UX * Loopback level meter (🔊) below mic meter — immediate feedback when loopback endpoint goes silent (Bluetooth headphones, routing changes). * Tray tooltip progress «загрузка/диаризация/распознавание NN%» for file-mode CPU users instead of static spinner. * Removed noisy meeting start/stop/rerun toasts. * Меню 'Скопировать путь к транскрипту' в подменю записей. * Hotkey rebind fix — old check silently ignored new combos. * Model-warmup tray guard preserves PROCESSING state when a file was queued during boot. Startup * Stage O CUDA warmup runs one dummy inference at load — kills the 12 s freeze on first finalize (Pavel 2026-08-20). * torch stub install probes with real import — catches half- uninstalled torch that segfaults downstream ORT DLL preload. Distribution * MossFormer2 lazy download from mirror on first meeting use — CPU-minimal bundle can ship without the 220 MB blob. * Config schema v16 with codeswitch model name migration. Mac port scaffolding * Cocoa (NSEvent) hotkey adapter as pynput replacement on macOS. Testing * 10 new tests: crash scrub, diarization invariants, ed25519 sign/ verify, dual-track finalize, full updater e2e.