VibeVox — Technikai Architektúra
Backend · Pipeline · Adatfolyam · Infrastruktúra
Kapcsolódó:
09_Product.md·06_GDPR.md·ROADMAP.mdStátusz: Élő dokumentum — v1.5.x állapot alapján Strategic Architecture integráció: ✅ GAP-1–4 + Bet-3 + riport ajánlások beépítve (2026-04-11) — WebSocket streaming (GAP-4), CEE endpointing ADR (GAP-1), MCP Fázis 2 (GAP-2), ADR-001 On-Device STT (GAP-3), ElevenLabs Scribe v2 fallback, gRPC migration roadmap, Distil-Whisper CEE rejection, Context-Aware Output Formatting, Azure MAI-Transcribe-1 B2B — forrás:Strategic_Architecture_Market_Analysis.mdPost-CTA funnel integráció: ✅ SHA-256 release pipeline +onboarding_completedevent timestamp beépítve (2026-04-18) — forrás:post_cta_funnel_analysis.md
Tartalomjegyzék
- Architektúra áttekintés
- STT pipeline
- Backend proxy szerver
- Adatbázis és szinkronizáció
- Fizetési infrastruktúra
- Platform-specifikus architektúrák
- Biztonsági architektúra
- Ismert technikai adósságok
1. Architektúra áttekintés
Rendszerkomponensek
┌─────────────────────────────────────────────────────────────────┐
│ VibeVox KLIENS (Windows / Linux App) │
│ ├── PySide6 UI (main_window.py, tray.py) │
│ ├── Audio recording (workers.py — hold-to-talk + session cap) │
│ ├── Post-processing (post_process.py — filler removal) │
│ ├── Local DB (SQLite — history, vocabulary, usage) │
│ └── Sync engine (sync.py — Supabase ↔ local DB) │
└───────────────────┬─────────────────────────────� ├── Routing: stt_router.py → provider-agnostik routing │
└── Billing sync (Stripe webhooks) │
└───────────────────┬─────────────────────────────────────────────┘
┌─────────┴──────────┐
▼ ▼
┌───────────────────────┐ ┌───────────────────┐
│ Deepgram Nova-3 │ │ Supabase │
│ (STT — PRIMARY) │ │ (history, vocab, │
│ WebSocket streaming │ │ usage sync) │
│ EU adatközpont, SCC │ │ Zürich, EU │
└───────────────────────┘ └───────────────────┘
│
│ Managed fallback lánc
▼
┌──────────────────────────────────────────────────┐
│ Groq Whisper large-v3 (Frankfurt, SCC) │ ← Managed fallback / BYOK alt.
│ → OpenAI gpt-4o-transcribe │ ← Végső fallback (3.2× drágább)
│ → Azure AI Speech (VNet) — B2B compliance tier │ ← Fázis 2 high-compliance B2B
└──────────────────────────────────────────────────┘─────────────────────────────────────┘
┌─────────┴──────────┐
▼ ▼
┌───────────────┐ ┌───────────────────┐
│ Groq API │ │ Supabase │
│ (STT) │ │ (history, vocab, │
│ Frankfurt │ │ usage sync) │
│ routing, SCC │ │ Zürich, EU │
└───────────────┘ └───────────────────┘
│
│ Fallback lánc
▼
┌───────────────────────────────┐
│ OpenAI gpt-4o-transcribe │ ← Legjobb minőség (3.2× drágább)
│ → Gemini 2.5 Flash (EU) │ ← Jövőbeli EU backend (Fázis 2)
└───────────────────────────────┘
BYOK mód architektúra
VibeVox KLIENS
│
├──► KÖZVETLENÜL a user STT API-jára (Groq / OpenAI / Azure / Gemini)
│ Az API kulcs a felhasználóé — ETS LLC nem proxyzza
│
└──► Supabase Zürich (history szinkron — ha bejelentkezve)
2. STT pipeline
Elsődleges pipeline (Managed Cloud) — WebSocket True Streaming
Döntés (2026-04-11 · GAP-4 javítás): A VibeVox P0-tól true streaming architektúrán indul. Nem batch WAV → egyszeri válasz, hanem valós idejű audio chunk streaming → live interim results. Ez az aha-moment kritikus eleme (live bubble). Batch→streaming migráció helyett: az alap eleve streaming.
ADR-002: Deepgram ELVETETT (2026-04 — végleges döntés)
Deepgram Nova-3-at megpróbáltuk — többször is. Elvetés oka: nem kezeli a CEE code-switching-et.
A CEE felhasználók (HU/PL/CZ/SK) természetesen kever angolt az anya nyelvhez
("menj a settings-be", "klikkelj a button-ra"). A Deepgram API egyetlen nyelvet vett
paraméterként — a váltásnál hibás leirat vagy teljes csőd következett.
Helyébe lép: Groq Whisper large-v3 — OpenAI Whisper alapú, natívan kezeli a
többnyelvű hangot, code-switching-et. §2.1 Háromszintű multilinguális STT pipeline épít erre.
Ezzel a Deepgram-mal kapcsolatos TASK_CALENDAR feladatok (D-13, D-9, D+24)
érvénytelenek — lásd 18_TASK_CALENDAR.md módosítás.
[GOMB NYOMVA TARTVA]
│
↓ Hang rögzítés (workers.py) — gomb elengedésekor WAV buffer lezárva
│
↓ Proxy WebSocket kapcsolat (kliens → GCP proxy)
│
↓ stt_router.py → Groq Whisper large-v3 (Frankfurt, SCC) ← ELSŐDLEGES
│ language=BCP47_MAP[primary_language] (hu, pl, cs, sk...)
│ prompt="Primary: Hungarian. Also: English." (⇒ code-switching support)
│ Batch WAV — gomb elengedésekor küld, válasz ms-eken belül
[GOMB ELENGEDVE]
│
↓ post_process.py — filler removal (ööö/szóval/hm), írásjel, mondatvég
│
↓ Szöveg commit az aktív ablakba (OS keyboard injection)
│
↓ Storage: SQLite (local) + Supabase szinkron (cloud)
[Fallback lánc]
→ OpenAI gpt-4o-transcribe (3.2× drágább, de legjobb accuracy)
→ Azure AI Speech (Fázis 2 — B2B VNet compliance tier)
[NOTE: Live bubble / interim results — Fázis 2+ kutatási cél]
Groq nem támogat WebSocket streaming-et (részben ezért próbáltuk Deepgramot).
Jövőbeli lehetőség: EU-alapú provider WebSocket streaming-gel, ami egyben
kezeli a CEE code-switching-et — jelenleg ilyen nincs azonosítva.
Pipeline kulcsparaméterei:
| Paraméter | Érték | Indok |
|---|---|---|
language |
BCP47_MAP[primary_language] |
CEE pontos nyelvi fókusz (nem auto-detect) |
prompt |
"Primary: HU. Also: EN." |
Code-switching támogatás Whisper prompt hint-el |
| Batch mód | WAV gomb elengedésekor | Groq, ellentétben Deepgrammal, nem hibás HU+EN váltásnál |
temperature |
0 | Determinisztikus — konzisztens leiratok |
Protokoll Stratégia: WebSocket (P0) → gRPC (Fázis 3+)
Döntés (2026-04-11 · riport ajánlás): A P0 WebSocket-alapú streaming helyes és elégséges a hold-to-talk use case-re; jól dokumentált, széles klienssupport. A gRPC az egyértelmű hosszú távú cél (Fázis 3+) — HTTP/2 multiplexing, natív kétirányú streaming, alacsonyabb overhead.
| Dimenzió | WebSocket (P0 — most) | gRPC (Fázis 3+ — jövő) |
|---|---|---|
| Latency | ~80–150ms end-to-end | ~30–60ms (HTTP/2 multiplexing) |
| Streaming | Kétirányú (külön kezelés) | Natív kétirányú (bidirectional) |
| Kapcsolat overhead | Magas (handshake per request) | Alacsony (connection multiplex) |
| CEE morfológia | Jó (jelenlegi utterance_end_ms) |
Kiváló (server push interim tokens) |
| Backward compat | Széles kliens support | gRPC-web szükséges browserben |
| Implementáció risk | Nulla (kész) | Közepes (proto def., migration) |
Migrációs döntési pont (Fázis 3): Ha a D+83 CEE endpointing A/B teszt eredményei után is latencia-panasz marad a top bug-reportok között → gRPC sprint indul. Ha a WebSocket latencia felhasználói szinten nem érzékelhető → marad, mert nincs user-visible probléma, és a migráció overhead nem indokolt.
2.1. Háromszintű multilinguális STT pipeline
Ez egy tudatos architektúrális döntés — NEM auto-detect. Dokumentálandó és aktívan kommunikálandó marketing anyagokban.
A probléma az auto-detect-tel: A Whisper auto-detect az audio első ~30 másodpercére alapozva választ a 100+ lehetséges nyelv közül. Kétnyelvű (pl. hu + en) diktálásnál pontatlan — a magyar–finn fonológiai hasonlóság (mindkettő Uralic) miatt pl. magyar szövegből finn leirat is keletkezhet. (Ez a Wispr Flow auto-detect konkrét, saját tapasztalatból dokumentált hibája.)
A VibeVox 3 szintű megoldása:
Szint 1: Primary Language PIN
app/config/settings.py → "primary_language": "Hungarian"
groq_engine.py → language=LANG_BCP47_MAP[primary] → "hu"
Hatás: A Whisper modell pontosan erre a nyelvre fókuszál
(nem választ 100+ közül)
Szint 2: Prompt Hint (Secondary + Tertiary)
_lang_helpers.py → build_lang_context(settings, previous_context)
⚠️ ADR — Prompt Hint Hallucináció Bug (2026-04-19 — FIX)
PROBLÉMA: A Whisper API `prompt` paramétere NEM utasítás, hanem kontextus-szöveg.
Ha az első diktálásnál (üres rolling tail) lang-hint mondatot küldtünk:
"The speaker uses Hungarian, English."
A Whisper ezt szó szerint beleírta a leírat elejére — pontosan ugyanaz a szöveg
jelent meg a transzkriptben: "A speaker uses Hungarian, English."
Megpróbált megoldások:
① Post-process strip CSAK — tüneti kezelés (hallucináció megtörtént,
csak utólag töröltük; átugorja a proxy-ágat és jövőbeli motorokat).
② Format megváltoztatás ("[Hungarian, English]" → nem mondat)
— nem dokumentált Whisper viselkedésre támaszkodik; nincs benchmark
garancia; elvetettük.
③ VÁLASZTOTT FIX: a `prompt` mezőt CSAK akkor küldjük el, ha van valódi
rolling-context tail. Üres tail esetén üres string → motorok nem küldik
a prompt-ot → Whisper semmi „mondandót" nem hall hallucinálni.
+ strip_lang_hint() safeguard marad aktív DEFENCE 1-ként minden motornál.
Hatás a secondary/tertiary language-re:
Az első chunk-nál nincs explicit lang hint — DE:
• A Whisper Large v3 belső multilinguális képessége HU+EN code-switchingre
erős (~85-90% a CEE use case-ben hint nélkül is).
• A 2. chunk-tól a rolling tail stílus-kontextusa pótol mindent.
• A language= API param (primary) mindig aktív marad.
Nettó hatás: első mondat margóan gyengébb cold-start detekció — elfogadott trade-off.
⚠️ Google STT + Azure Speech integráció (Fázis 2):
Mindkét új engine-be be kell kötni a strip_lang_hint() safeguard-ot.
A Google multimodal API más mechanizmust használ (nem `prompt=`),
az Azure Speech pedig PhraseListGrammar → a lang hint küldési mechanizmusa
más lesz, de a strip-safeguard engine-független és minden kimenetre alkalmazható.
Implementáció: `raw = strip_lang_hint(raw, settings)` a transcribe() return előtt.
Szint 2b: Rolling Context Window — Whisper prompt optimális felhasználása
Az előző transzkripció utolsó ~150 szava kerül a Whisper prompt-ba.
NEM szótár — a 224-token limitet szótárra pazarolni értelmetlen.
→ Hatás: Mondathatár-hibák, stílus-öröklés, folyamatos diktálás kontextusa
→ Kód: prompt = previous_transcript_tail(max_tokens=224)
BYOK Provider-specifikus prompt limit — Kutatás (2026-04-18):
A 224-token limit a Whisper modell belső architektúrájának korlátja.
NEM érvényes minden BYOK providerre — provider-specifikus kezelés szükséges!
| STT Provider | Prompt mód | Limit / Mechanizmus | Implementáció a rolling contexthez |
|---------------------------|------------------------|------------------------------------------------|-----------------------------------------------------|
| Groq Whisper large-v3 | `prompt=` string | 224 token (végéről számolva, korábbi szöveg ignorálva) | `max_tokens=224` — jelenlegi implementáció ✅ |
| OpenAI BYOK (gpt-4o-transcribe) | `prompt=` string | ~224 token — prompt leakage kockázat hosszabb inputnál | rövid trailing context, `max_tokens=200` |
| Azure BYOK (OpenAI Whisper) | `prompt=` string | 224 token (azonos Whisper architektúra) | azonos, `max_tokens=224` |
| Google Gemini BYOK | multimodal chat üzenet | ~1M token kontextusablak (32 token/sec audio) | **1 000 token** rolling window — lásd döntés lent |
ADR — Azure Cognitive Services Speech ELVETVE (2026-04-18):
Az Azure BYOK = kizárólag Azure OpenAI Whisper. Azure Cognitive Speech NEM kerül implementálásra.
Indok:
✅ Ár: azonos ($0.006/perc batch) — nincs cost-előny az Azure Speech mellett
✅ WER: nagyjából azonos CEE nyelveken — nincs accuracy-előny
❌ Azure Speech fő előnye: real-time streaming alacsony latenciával
→ VibeVox hold-to-talk = BATCH (gomb elengedésekor küld WAV-t)
→ a streaming előny irreleváns a use case-re
❌ Azure Speech API: teljesen más SDK (Microsoft Cognitive), PhraseListGrammar,
külön rolling context logika → nagy fejlesztési overhead, semmi extra értékért
✅ Azure OpenAI Whisper: OpenAI-kompatibilis endpoint → ugyanaz a kód mint OpenAI BYOK,
csak `base_url` + `api_key` különbözik — trivialis implementáció
✅ Azure OpenAI = EU data residency oka megtartható (B2B compliance tier)
ADR — OpenAI whisper-1 ELVETVE (2026-04-18, végleges döntés):
OpenAI BYOK = kizárólag gpt-4o-transcribe. whisper-1 NEM kerül implementálásra.
A felhasználó csak „OpenAI API kulcs"-ot lát — a modellválasztás VibeVox belső döntése.
Indok:
✅ WER: gpt-4o-transcribe lényegesen alacsonyabb hibaarány mint whisper-1
(OpenAI belső benchmarkok: ~30-50% WER csökkentés tipikus use case-en)
✅ CEE code-switching: gpt-4o-transcribe jobb HU+EN, PL+EN, CZ+EN kezelése
(whisper-1 a CEE morfológián és vegyes nyelvű mondatokon gyengébben teljesít)
✅ API kulcs: gpt-4o-transcribe ugyanazon OPENAI_API_KEY alatt érhető el — nincs
külön engedélyezési lépés vagy plan-upgrade a BYOK user számára
✅ UX: a felhasználónak irreleváns a modell neve — csak a pontosság számít
❌ whisper-1 egyetlen előnye lett volna: alacsonyabb cost
→ de a pontosság-különbség ezt nem indokolja, és BYOK user a saját számlájára fizet
❌ Karbantartás: két OpenAI-ágat fenntartani (whisper-1 + gpt-4o-transcribe)
semmi pluszt nem adna, csak kódbonyolítást
Összefoglalva: ha valakinek OpenAI kulcsa van, a legjobb modellt kapja — automatikusan.
⚠️ Fejlesztési figyelő (2026-04-19 sprint):
- Groq Whisper large-v3: max_tokens=224 ✓ (jelenlegi implementáció)
- OpenAI gpt-4o-transcribe: max_tokens=200 (prompt leakage kockázat miatt konzervatív)
- Azure OpenAI Whisper: max_tokens=224 (azonos Whisper architektúra)
- Gemini BYOK: max_tokens=1000 — dedicated branch a build_lang_context()-ben
A Gemini 1M token kontextusa lehetővé teszi, hogy lényegesen több előző szöveget adjunk át
mint Whisper-nél. Ez jobb kontextus-öröklést ad (proper nouns, stílus, terminológia).
DE: az audio maga is tokenekbe kerül (32 tok/sec), és a text input is pénzbe kerül.
Cost-benefit kalkuláció (Gemini 1.5 Flash, BYOK user fizeti):
Egy 30mp-es diktálás audio cost: 30 × 32 tok = 960 audio token
Text input (~26× olcsóbb audio-nál):
224 token kontextus → +$0.000017/diktálás → napi 50 alkalom: $0.00085/nap
1 000 token kontextus → +$0.000075/diktálás → napi 50 alkalom: $0.004/nap ← VÁLASZTOTT
3 000 token kontextus → +$0.000225/diktálás → napi 50 alkalom: $0.011/nap
10 000 token kontextus → +$0.00075/diktálás → napi 50 alkalom: $0.038/nap
DÖNTÉS: Gemini BYOK rolling window = 1 000 token (~750 szó, ~5 perc kontextus)
Indok:
✅ 4× több kontextus mint Whisper — érzékelhető kontextus-öröklés proper nouns-ra, stílusra
✅ Napi extra cost < $0.004 — elhanyagolható a BYOK user számára
✅ Konzervatív megközelítés — könnyen növelhető ha A/B teszt indokolja
❌ 3K+ token: extra cost nő, a margináló minőségjavulás már kicsi
Implementáció: `build_lang_context(provider="gemini", max_tokens=1000)`
⚠️ Fejlesztési figyelő (2026-04-19 sprint):
- Whisper-alapú providerek (Groq, OpenAI whisper-1, Azure OAI): max_tokens=224 marad ✓
- gpt-4o-transcribe: max_tokens=200 (prompt leakage kockázat miatt konzervatív)
- Gemini BYOK: max_tokens=3000 — dedicated branch a build_lang_context()-ben
- Azure Cognitive Speech (nem OAI): rolling context teljesen más API — PhraseListGrammar
→ fejlesztési döntés szükséges: külön implementáció vagy Azure OAI-ra irányítás
Szint 2c: LLM Post-Processing — Custom Vocabulary Correction (Fázis 2+)
DÖNTÉS (2026-04-18): A custom vocabulary NEM a Whisper promptba kerül.
A Whisper 224 token limitje ~80-120 orvosi/jogi szót fed le — elégtelen.
Helyette 2-lépéses pipeline:
1. Groq Whisper large-v3 → nyers transzkript (rolling context prompt)
2. Groq Llama 3 8B Instant → vocabulary-korrigált végleges szöveg
Rendszer-prompt = összes aktív szótár teljes listája
(500-1500 szó gond nélkül befér a Llama 3 8K+ kontextusba)
Triggerelés (OPT-IN — 2026-04-18 döntés):
Az LLM lépés CSAK akkor fut le, ha a felhasználónak van legalább 1 aktív szótára
VAGY aktív Style Persona van kiválasztva (nem Standard).
Ez magában foglalja az előre beépített (Medical, Legal, Dev) szótárakat is —
de ezek is csak aktiválás után futnak. Alapértelmezett állapotban: LLM nem fut.
Style Persona = Standard → LLM NEM fut (ha nincs szótár sem)
Style Persona ≠ Standard → LLM fut, rendszer-promptba kerül a persona definíció
Szótár + Persona egyszerre → EGYETLEN API hívásban kezelve (nincs extra latencia)
Filler removal (ööö, hát, szóval) — marad regex/post_process.py — NEM kerül LLM-be.
Előnyök: korlátlan szótárméret, több szótár egyszerre, kontextus-érzékeny;
stílus és szótár egyetlen API hívásban egyesíthető — nincs extra latencia
Cost: ld. 05_Pricing.md — LLM Post-Processing cost szekció (részletes leépítés)
Gboard ellentéte: Gboard explicit ignorálja a Personal Dictionary-t
voice mode-ban → VibeVox LLM pipeline megoldja
Android kiemelten releváns: Gboard monopolhelyzet → erős differenciátor
BYOK Provider Routing — Döntés (2026-04-18):
A post-processing LLM KÖVETI az STT providert.
Elv: egykulcsos BYOK — a felhasználó egyetlen API kulcsa fedi az STT-t ÉS
az LLM post-processinget is. ETS LLC nem kezel más provider kulcsát.
| STT Provider | Modell (user NEM választ) | LLM Post-Processing | Kulcs |
|---------------------|---------------------------|--------------------------|-----------------|
| Groq (managed/BYOK) | Whisper large-v3 | Groq Llama 3 8B Instant | GROQ_API_KEY |
| OpenAI BYOK | **gpt-4o-transcribe** | OpenAI gpt-4o-mini | OPENAI_API_KEY |
| Google BYOK | Gemini 1.5 Flash | Gemini 1.5 Flash | GOOGLE_API_KEY |
| Azure BYOK (OAI) | Azure OpenAI Whisper | Azure OpenAI gpt-4o-mini | AZURE_OPENAI_* |
| Azure BYOK (Speech) | Azure Speech | Groq Llama 3 (fallback) | — |
Implementáció: _get_postprocessing_provider() helper (_orchestrator.py)
Tesztelési scope: Groq/OpenAI/Gemini/Azure × szótár aktív/inaktív × literal mód = 16 kombináció
Fejlesztési sprint: 2026-04-19 (D-12)
Szint 3: Filler Removal (CEE-specifikus)
post_process.py → filler_removal(text, primary_language)
→ "ööö", "hát", "szóval", "no", "takže", "teda", "eee"
Hatás: CEE-specifikus, az auto-detect nem ismeri ezeket
Kódból:
# groq_engine.py
lang_code = LANG_BCP47_MAP.get(settings.get("primary_language", "Hungarian"), "hu")
# → Whisper language param: pontosan "hu" (nem auto)
# _lang_helpers.py
langs = [settings.get("primary_language", "Hungarian")]
# secondary + tertiary → prompt hint
Marketing érv:
„Wispr Flow-nak van auto-detect funkciója. Nálunk nincs — mert ez pontosabb. Egy felhasználó által explicit megadott 2-3 nyelv mindig jobb eredményt ad, mint 100+ közötti gépi választás."
2.2. Hallucináció-megelőzési réteg (Anti-Confabulation)
Probléma: A Whisper seq2seq architektúra csend esetén hallucinál — a training adatából generál szöveget (pl. „Thanks for watching", „Transcription by CastingWords", „Subscribe to our channel", véletlenszerű mondatok más nyelveken). Ez a hold-to-talk modellben is előfordul, ha a user gondolkodás közben nyomva tartja a gombot.
Forrás: Churn post-mortem kutatás (2026-04) — az AquaVoice és Wispr Flow felhasználóknál reprodukálható, dokumentált probléma.
3 szintű védekezés:
Szint 1: Kliens-oldali VAD (Voice Activity Detection) — Fázis 1
├── A VibeVox app a hangfelvételt küldés ELŐTT elemzi
├── RMS energia < küszöbérték AND nincs speech onset → NEM küld API-nak
├── Teljes csend session → üres string, nem API hívás (megtakarítás!)
└── Implementáció: webrtcvad (Python) vagy egyszerű RMS threshold
Szint 2: Proxy-oldali blocklist szűrés — Fázis 1
├── A FastAPI proxy ismert hallucináció-mintákat szűr a Groq válaszban:
│ ["Thanks for watching", "Transcription by", "Subscribe to",
│ "bye", "thank you for listening", "Amara.org"]
├── Regex blocklist: ha a TELJES válasz ilyen szöveg → üres string return
└── Nyelvi koherencia: ha user HU-t diktál és válasz 100% EN → eldobás
Szint 3: Felhasználói feedback
└── Üres eredménynél: "Nem hallottam semmit — próbáld újra" toast
(NEM jelenít meg random hallucinált szöveget)
Teljesítmény hatás:
- VAD check: <5ms (kliens-oldali, minimális overhead)
- Proxy blocklist: <10ms (egyszerű string matching)
- Megtakarítás: felesleges Groq API hívások eliminálása csend esetén
A fenti az orvosi/jogi B2B szegmensben kritikus: „Köszönöm a figyelmet" vagy random szöveg a zárójelentésben azonnali bizalomvesztést okoz.
2.3. Latency SLA
A kutatás (2026-04) szerint a 3 másodperc feletti E2E latency a flow state megsemmisítője — ennél a pontnál a felhasználó visszatér a gépeléshez. Az AquaVoice 450ms–1s sávja az iparági arany-standard.
SLA célok és alerting:
| Metrika | P50 cél | P95 cél | P99 cél | Alerting küszöb |
|---|---|---|---|---|
| E2E TTV (gomb felengedés → szöveg megjelenik) | <1.0s | <1.5s | <2.5s | P95 > 2.0s = alert |
| Groq API response | <500ms | <1.0s | <1.5s | P50 > 800ms = fallback trigger |
| Audio upload (kliens → proxy) | <200ms | <400ms | <600ms | — |
| Text injection (proxy return → aktív ablak) | <50ms | <100ms | <150ms | — |
Versenytárs benchmarkok:
| Versenytárs | TTV | Módszer |
|---|---|---|
| AquaVoice (Avalon motor) | 450ms-1s | Saját modell, agresszív optimalizálás |
| Wispr Flow | 1.5-3s | Cloud roundtrip (flow state killer) |
| Typeless | ~1.5-3s | Cloud-native, hasonló Wispr sávban |
| VibeVox (cél) | <2s (P95) | Groq Frankfurt routing |
Monitoring implementáció — Sentry performance tracing (opt-in):
# Mérendő Sentry spanok
sentry_sdk.start_span(op="stt.upload_latency_ms")
sentry_sdk.start_span(op="stt.processing_time_ms")
sentry_sdk.start_span(op="stt.total_ttv_ms")
sentry_sdk.start_span(op="stt.text_insertion_ms")
A Groq Frankfurt routing természetes előnyt ad a CEE felhasználóknak vs. US-központú versenytársak (~50-100ms RTT nyereség). Ez aktívan kommunikálandó a marketing narratívában.
2.4. CEE Nyelv-specifikus Endpointing ADR (Hipotézis — Validálandó)
Döntés (2026-04-11): A VibeVox language-aware
endpointingkonfigurációt alkalmaz Deepgram WebSocket streaming esetén. Az optimális érték CEE nyelvenként eltérő — a szóhossz és morfológiai komplexitás függvénye. Ez jelenleg hipotézis, Fázis 2-ben A/B teszttel validálandó.
A probléma: Deepgram default endpointing angol-centrikus
Deepgram endpointing = hány ms csend után zárja le az utterance-t
Default: 10ms — az angol rövid szavakra optimalizálva (~4-5 karakter)
Magyar példa a problémára (800ms-nél rövidebb endpointing esetén):
Felhasználó mondja: "megvizsgálhatatlan" (~1.4 mp kiejtési idő)
10ms endpointing: "megvizsgálha" [LEZÁR] "tlan" → 2 töredék, rossz
200ms endpointing: "megvizsgálhata" [LEZÁR] "lan" → még mindig rossz
800ms endpointing: "megvizsgálhatatlan" [LEZÁR] → ✅ teljes szó
CEE nyelvek morfológiai komplexitása és endpointing hipotézis
| Nyelv | Típus | Átl. szóhossz | Max szóhossz | Jellemző probléma | Endpointing hipotézis |
|---|---|---|---|---|---|
| English (baseline) | Izoláló | ~4-5 kar. | ~15 kar. | — | 10ms (Deepgram default) |
| Slovak (SK) | Fuzionáló | ~5-6 kar. | ~25 kar. | Kevesebb eset-suffix | ~400ms |
| Czech (CZ) | Fuzionáló | ~5-6 kar. | ~28 kar. | Hasonló SK-hoz | ~400–500ms |
| Polish (PL) | Fuzionáló + klaszter | ~6-7 kar. | ~30 kar. | szcz, prz, strz msh-torlódás |
~500–600ms |
| Hungarian (HU) | Agglutináló | ~7-8 kar. | ~44+ kar. | Korlátlan suffix-lánc | ~700–800ms |
A PL eset különleges: a lengyel mássalhangzó-csoportok (szcz, prz) nem hosszú szavakat, hanem nehezen szegmentálható fonémasorozatokat okoznak. Az endpointing itt a téves szóhatár-detektálás ellen véd, nem a szóhossz miatt.
Implementáció — Primary Language PIN alapján automatikus
# stt_router.py / deepgram_handler.py
# Egy dict vezérel mindent — a Primary Language PIN már megvan
LANGUAGE_ENDPOINTING_MS = {
"en": 10, # Deepgram default — angol baseline
"sk": 400, # Fuzionáló, mérsékelten hosszú szavak
"cs": 450, # Fuzionáló, hasonló SK-hoz
"pl": 550, # Fuzionáló + msh-torlódás (szcz, prz)
"hu": 800, # Agglutináló — a leghosszabb szavak
}
# Deepgram WebSocket konfig (language = Primary Language PIN):
deepgram_config = {
"language": lang_code, # pl. "hu"
"endpointing": LANGUAGE_ENDPOINTING_MS[lang_code], # pl. 800
"utterance_end_ms": 1000, # 1 mp szünet = utterance lezárva (minden CEE-n)
"smart_format": True,
"model": "nova-3",
}
Miért elegáns ez az arhitektúra:
- A Primary Language PIN (2.1. szekció) már meghatározza a
lang_code-ot - Az endpointing automatikusan következik belőle — a user semmit nem állít be
- Új CEE nyelv hozzáadása = 1 sor a dict-ben
A/B Teszt Protokoll (Fázis 2, D+83)
Tesztkészlet: 30 mondat × 4 CEE nyelv = 120 teszt
- 10 rövid mondat (1-3 szó)
- 10 közepes mondat (4-8 szó, normál szóhossz)
- 10 hosszú mondat (9+ szó, komplex agglutináció/klaszter)
Tesztelt endpointing értékek: [10, 200, 400, 600, 800, 1200] ms
Mért metrika: WER (Word Error Rate) a ground truth transzkripthez képest
Várható eredmény:
EN: 10ms optimális (egyértelmű)
HU: 700-900ms sávban optimális
PL: 500-700ms sávban optimális
CZ/SK: 400-600ms sávban optimális
Ha mért optimum ≠ hipotézis → LANGUAGE_ENDPOINTING_MS frissítése
Marketing értéke (ha validált): Ez az egyetlen publikusan dokumentált, tesztelt CEE-specifikus Deepgram endpointing konfiguráció. Nincs más STT termék ami ezt méri és publikálja. Dev community számára megosztható technikai blog post / HN post alapja.
Versenytárs-összehasonlítás
| Versenytárs | Magyar endpointing optimalizálás? |
|---|---|
| Wispr Flow | ❌ Default 10ms (angol-centrikus) |
| Typeless | ❌ Default (auto-detect, generikus) |
| Windows Fluid Dictation | ❌ Azure default konfig |
| Dragon HU | N/A (nem streaming) |
| VibeVox | ✅ Language-aware, mért endpointing |
STT provider összehasonlítás
Architektúrális döntés felülvizsgálat (2026-04-11 — éles tesztelés alapján) Az eredeti architektúra Deepgram Nova-3-t jelölt ki PRIMARY motornak elméleti benchmark adatok alapján. Éles, valós körülmények között végzett tesztelés ezt megcáfolta. Lásd a teszteredmények szekciót alább.
Deepgram Nova-3 — Éles teszteredmények (2026-04-11)
Deepgram Nova-3 CEE tesztelés — SIKERTELEN Tesztkörnyezet: Boya gooseneck USB mikrofon · Magyar elsődleges nyelv · Windows 11 · Koh Phangan (TH → EU szerver)
| Teszt | Konfiguráció | Eredmény | Értékelés |
|---|---|---|---|
| Magyar monolinguális | language=hu |
✅ Működik — ~0.4 mp latencia | Jó |
| Magyar + "AI" szó | language=hu |
❌ "AI" felismerhetetlenül elrontva | Kritikus hiba |
| Magyar + angol márkanév (Boya) | language=hu |
❌ Értelmetlen output | Kritikus hiba |
Multilinguális (language=multi) |
language=multi |
❌ Magyar szövegből svéd/nordikus leirat (ä/å/ø karakterek) | Disqualifying |
| Sebességmérés (batch baseline-hoz képest) | language=hu |
✅ ~5-6× gyorsabb mint batch | Pozitív |
Gyökérokok:
1. language=hu: Nova-3 a teljes hangot magyar fonetikán erőlteti át
→ Angol szavak (AI, Boya, app) elvesznek vagy torzulnak
→ Magyar + bármilyen idegen szó = hibás output
2. language=multi: Nova-3 100+ nyelv közül választ mondatonként
→ Magyar fonológia átfedést mutat finnugor/skandináv nyelvekkel
→ Valós teszten: magyar mondatok svéd szövegként kerültek leiratba
→ Ez diszqualifikálja a CEE kódváltó (HU+EN) use case-re
3. Nincs prompt paraméter: Deepgram API nem támogatja a
"primary=HU, secondary=EN" hint megadását
→ Whisper-rel szemben nincs megoldás erre az use case-re
Összehasonlítás WhisperFloat-tal (Groq Whisper, azonos mikrofon):
WhisperFloat (Groq Whisper large-v3): Magyar + angol szavak → TÖKÉLETES
Deepgram Nova-3: Magyar + angol szavak → MEGBÍZHATATLAN
Döntés: Deepgram Nova-3 kizárva a PRIMARY pozícióból. Deepgram WebSocket streaming sebesség-előnye valós (~0.4 mp), de a CEE kódváltó minőség elfogadhatatlan. A Managed Cloud PRIMARY motor: Groq Whisper large-v3 (VAD-alapú szegmentálással).
Döntés (2026-04-11 — éles teszt alapján felülírva): Deepgram Nova-3 → Groq Whisper large-v3 a Managed Cloud elsődleges motorja.
A Whisper language= + prompt= kombinációja lehetővé teszi a primary+secondary+tertiary hint megadását — ez az egyetlen megbízható megoldás a CEE kódváltó use case-re.
| Provider | Ár/perc | EU Data Residency | CEE kódváltó minőség | Transzkripciós minőség (WER) | Szerepe |
|---|---|---|---|---|---|
| Groq Whisper large-v3 | ~$0.00185 | ✅ SCC, Frankfurt | ✅ Kiváló (tesztelve, HU+EN) | ✅ Jó — Whisper large-v3 ~4–6% WER EN; CEE-n ~8–12% | Managed Cloud PRIMARY · BYOK low-cost default |
| OpenAI gpt-4o-transcribe | ~$0.006 | ❌ US | ✅ Legjobb (benchmark-vezető) | ✅✅ Legjobb — ~2–4% WER EN; ~30–50% WER jobb mint whisper-1 | Managed végső fallback · BYOK opció |
| Azure AI Speech / OAI Whisper | ~$0.006 | ✅ EU Data Zones | ✅ Kiváló (Whisper arch.) | ✅ Jó — azonos Whisper large-v3 szint | BYOK B2B compliance tier (Fázis 2) |
| Gemini 2.5 Flash (Vertex) | ~$0.001–0.002 | ✅ EU (europe-west4) | 🟡 Tesztelendő | 🟡 Tesztelendő — Google erős multilingvális, CEE benchmark nincs | Jövőbeli managed kandidált |
| ❌ CEE kódváltásnál megbízhatatlan | |||||
| ❌ Gyenge CEE WER | ❌ Gyengébb mint large-v3 | KIZÁRVA | |||
| ❌ Auto-detect megbízhatatlan | ❌ CEE-n gyenge | KIZÁRVA |
ADR — Miért nem GPT-4o (full) és miért nem Gemini 2.5 Pro STT-re? GPT-4o (full, chat API) kizárás: A GPT-4o chat API nem dedikált STT — audio bemenetből szöveget tud generálni, de ez multimodal chat completion, nem transzkripció. Problémák:
- Ár: $5–15/1M input token vs.
gpt-4o-transcribe~$0.006/perc = 10–50× drágább azonos feladatra - Kontroll hiánya: A chat completion modell hozzáadhat, parafrazeálhat, „javíthat" — nem garancia az exact transcript outputra
- Nincs timestamp/confidence:
gpt-4o-transcribead strukturált transzkripció-outputot; a chat API-nál ezt kézzel kellene parseolni - Konklúzió: Ha OpenAI-t akarunk, a
gpt-4o-transcribeAPI a helyes eszköz — az jobb transzkripciós minőséget ad, olcsóbban, strukturáltan.
- Ár: $1.25–2.50/1M input token vs. Gemini 2.5 Flash ~$0.001–0.002/perc = 100–1000× drágább azonos STT feladatra
- Latencia: A Pro méretű modell inferencia-ideje 2–5× lassabb mint Flash — hold-to-talk < 2s SLA-nk nem tartható
- Over-engineering: A vocab-correction task (ahol esetleg indokolt lenne a Pro) inherensen egyszerű — kisebb modell kevesebbet „okoskodik", pontosabb output
- Konklúzió: Gemini 2.5 Flash (STT) + Gemini 1.5 Flash (LLM post-proc.) pontosan elég. A Pro méret semmit nem ad a use case-hez — csak drágább és lassabb.
primary=HU, secondary=EN hint megadási lehetőséget.
Éles teszten (language=multi): magyar mondatok svéd szövegként leiratba kerültek (finnugor–skandináv fonológiai átfedés) — ez diszqualifikáló.
Monolinguális, EN-only BYOK use case-re a Nova-3 alternatívaként megtartható (ld. BYOK provider routing szekció).
Forrás: stt_ux_architecture_analysis.md §6 · 18_TASK_CALENDAR.md ADR-002 · Érintett kutatás: Strategic UX and Architecture for Real-Time Professional Dictation Systems (2026-04-11)BYOK Provider Routing — Átláthatóság-alapú modell
Alapelv: A BYOK tier provider-agnostik. A felhasználó maga dönt — a VibeVox tájékoztatja a trade-off-okról, de nem korlátozza a választást.
BYOK onboarding wizard — provider választás:
★ AJÁNLOTT: Groq Whisper large-v3
Legjobb CEE WER + HU/EN kódváltás prompt-alapon + EU Frankfurt
Ár: ~$0.00185/perc | Streaming: VAD-alapú szegmentálás
→ Ideális: minden CEE user, napi diktálók, jogi/orvosi B2B userek
○ Alternatíva: Deepgram Nova-3 (csak EN-domináns diktáláshoz)
WebSocket streaming sebessége valós (~0.4 mp), de CEE kódváltásnál megbízhatatlan
Ár: ~$0.0043/perc | Trade-off: drágább + CEE minőség nem megfelelő
→ Kizárólag akkor ajánlott, ha a user CSAK angol nyelven diktál
○ Haladó: OpenAI gpt-4o-transcribe
Legjobb EN minőség, de US-adatközpont
→ Ideális: EN-only power userek, akiknek fontos az OpenAI ökoszisztéma
○ Vállalati: Azure AI Speech (Fázis 2)
100% EU Data Residency, VNet integráció
→ Ideális: healthcare/legal B2B (GDPR hard requirement)
✗ NEM ELÉRHETŐ: Groq Whisper Turbo — gyenge CEE WER
✗ NEM ELÉRHETŐ: Google Chirp 2 — megbízhatatlan multi-language
Margin megjegyzés: A BYOK felhasználó saját API kulcsával fizet közvetlenül a providernek — a VibeVox €3,50/hó licence fix bevétel, független a provider választástól. A VibeVox margin 100% a BYOK tiernél.
BYOK STT Provider — API Capability Matrix
Forrás: GAP-C6 kutatás + Azure ADR (2026-04-19 — éles API referencia alapján) Cél: Meghatározni, melyik providernél mit tudunk lefejleszteni (feature feasibility per provider). Ez az egyetlen hiteles referencia a provider-specifikus API korlátokhoz és fejlesztési lehetőségekhez.
STT (Transcription) Képességek
| Képesség | Groq Whisper large-v3 | OpenAI gpt-4o-transcribe | Google Gemini 1.5 Flash | Azure OpenAI Whisper |
|---|---|---|---|---|
| Protokoll | REST (batch) | REST (batch) | REST (batch / multimodal) | REST (batch) |
| WebSocket streaming | ❌ Nem elérhető | ❌ Nem elérhető | ❌ Nem elérhető¹ | ❌ Nem elérhető² |
| Prompt paraméter | ✅ prompt= string |
✅ prompt= string |
✅ System instruction (chat) | ✅ prompt= string |
| Prompt token limit | 224 token (Whisper arch.) | ~200 token (prompt leakage kockázat) | ~1M token (text), 32 tok/s audio | 224 token (azonos Whisper arch.) |
| Rolling context max | 224 token ✅ | 200 token (konzervatív) | 1 000 token (DÖNTÉS: 4× jobb, elhanyagolható cost) | 224 token |
| Language hint | language= BCP-47 |
language= BCP-47 |
System prompt szöveg | language= BCP-47 |
| Confidence score | ⚠️ avg_logprob (szegmens szint, verbose_json) |
❌ Nem elérhető | ❌ Nem elérhető³ | ❌ Nem elérhető |
| Word-level timestamps | ✅ verbose_json + timestamp_granularities=["word"] |
❌ — | ❌ — | ❌ — |
| CEE code-switching | ✅ Kiváló (tesztelve, HU+EN) | ✅ Legjobb EN (tesztelendő HU) | 🟡 Tesztelendő | ✅ Kiváló (Whisper arch.) |
| Max fájlméret | 25 MB | 25 MB | ~20 MB⁴ | 25 MB |
| Rate limit (free tier) | 2 000 req/nap · 7 200 audio-s/h | Fizetős (nincs ingyenes tier) | Gemini API: 1 500 req/nap (free) | Fizetős (Azure Portal) |
| Ár/perc (referencia) | ~$0.00185 | ~$0.006 | ~$0.001–0.002 | ~$0.006 |
| EU Data Residency | ✅ Frankfurt (SCC) | ❌ US | ✅ europe-west4 (Vertex) / ❌ AI Studio |
✅ EU Data Zones |
¹ Gemini Live API létezik WebSocket-tel, de audio→text streaming B2B production use-ra még nem érett (2026-04 állapot). A VibeVox Fázis 3+ roadmapján szerepel. ² Azure Cognitive Services Speech (NEM Azure OpenAI Whisper) támogatja a WebSocket streaming-et — de ezt ADR-002 kizárta (ld. §2.1 ADR szekció): a hold-to-talk batch modellhez irreleváns, és SDK-overhead nem indokolt. ³ Gemini
candidates[0].safetyRatingsad content-filter jelet, de audio transzkripció accuracy score-t nem. ⁴ Gemini multimodal inline data limitje modell-függő; base64-ban küldött WAV esetén ~$0.002/mb overhead.
LLM Post-Processing Modellek — Részletes Összehasonlítás (Step 2c — Vocabulary Correction)
Kontextus: A vocab-correction pipeline (
_orchestrator.py → _run_vocab_correction()) mind a 4 providernél más LLM-et hív az egykulcsos BYOK elv miatt. Ezek a modellek nem egyenértékűek — az alábbi tábla az fejlesztési döntéseket alátámasztó hiteles referencia.A legkritikusabb tulajdonság:
instruction-followingminősége — a modell pontosan az utasítás szerint dolgozik-e? A vocab-correction taskban: „Csak a félrehallott technikia szavakat javítsd. Ne változtass mondatszerkezeten, ne adj hozzá, ne vegyél el semmit." Ha a modell ennél többet tesz, a user elveszíti a bizalmat.
Modell specs (jelenlegi VibeVox választás + benchmark összehasonlítás):
A szürke oszlopok (gpt-4o, Gemini 2.5 Pro) nem kerülnek implementálásra — referenciaként szerepelnek, hogy lássuk mit nyernénk/veszítenénk a váltással.
| Groq — Llama 3.1 8B (aktív) | OpenAI — gpt-4o-mini (aktív) | Google — Gemini 1.5 Flash (aktív) | Azure — gpt-4o-mini (aktív) | OpenAI — gpt-4o (referencia) | Google — Gemini 2.5 Pro (referencia) | |
|---|---|---|---|---|---|---|
| Modell méret | 8B | ~8–9B (zárt) | MoE ~unknown | = gpt-4o-mini | ~200B (becsült) | ~unknown (MoE, nagy) |
| Kontextus ablak | 128K | 128K | 1M | 128K | 128K | 1M |
| Max output token | 8 192 | 16 384 | 8 192 | 16 384 | 16 384 | 65 536 |
| Sebesség | ⚡ ~500–800 tok/s | ~80–120 tok/s | ~150–250 tok/s | ~80–120 tok/s | ~40–80 tok/s | ~60–100 tok/s |
| E2E latencia hatás | +50–100ms | +150–300ms | +100–200ms | +150–300ms | +300–600ms | +200–400ms |
| Cost/1M input token | $0.05 | $0.15 | $0.075 | $0.165 | $2.50 | $1.25 |
| Cost/1M output token | $0.08 | $0.60 | $0.30 | $0.66 | $10.00 | $10.00 |
| Becsült cost/diktálás | ~$0.00005 | ~$0.0002 | ~$0.0001 | ~$0.0002 | ~$0.003 | ~$0.002 |
| Cost szorzó vs mini | 1× (Groq) | 1× | 0.5× | 1× | ~15–17× | ~10–13× |
| temperature=0 | ✅ | ✅ | ✅ generationConfig |
✅ | ✅ | ✅ |
| EU Data Residency | ❌ US | ❌ US | ✅ Vertex EU | ✅ Azure EU | ❌ US | ✅ Vertex EU |
Minőségi dimenziók (vocab-correction feladatra, 1–10 skálán):
Módszertan: Iparági benchmarkok (LMSYS, Chatbot Arena, OpenAI/Google belső) + vocab-correction specifikus szempontok (instruction-following, CEE language, over-correction hajlam). A számok relatív rangsorolást tükröznek, nem abszolút mértéket.
| Llama 3.1 8B | gpt-4o-mini | Gemini 1.5 Flash | Azure gpt-4o-mini | gpt-4o | Gemini 2.5 Pro | |
|---|---|---|---|---|---|---|
| 🎯 Instruction-following | 🟡 6/10 | ✅ 8/10 | ✅ 8/10 | ✅ 8/10 | ✅✅ 9.5/10 | ✅✅ 9.5/10 |
| ⚠️ Over-correction kockázat | 🟠 Magas | ✅ Alacsony | ✅ Alacsony | ✅ Alacsony | ✅ Minimális | ✅ Minimális |
| 🌍 CEE szófelismerés (HU/PL/CZ) | 🟡 6/10 | ✅ 8/10 | 🟡 7/10* | ✅ 8/10 | ✅✅ 9/10 | ✅✅ 9/10 |
| 📚 Szótárméret-skálázás | 🟡 ~150 szó max | ✅ 1 000+ | ✅✅ 10 000+ | ✅ 1 000+ | ✅ 1 000+ | ✅✅ 10 000+ |
| 🚫 Hallucináció / hozzáadás | 🟠 Ritkán előfordul | ✅ Alacsony | ✅ Alacsony | ✅ Alacsony | ✅ Nagyon alacsony | ✅ Nagyon alacsony |
| 🔤 Multilingual output stabilitás | ✅ Stabil | ✅ Erős | 🟡 Tesztelendő | ✅ Erős | ✅✅ Kiváló | ✅✅ Kiváló |
| ⚡ Sebesség (pipeline impact) | ✅✅ Legjobb | ✅ Jó | ✅ Jó | ✅ Jó | 🟡 Lassabb | 🟡 Közepes |
| 💰 Cost-efficiency | ✅✅ Legjobb | ✅ Jó | ✅✅ Nagyon jó | ✅ Jó | ❌ 15–17× drágább | ❌ 10–13× drágább |
| 📊 Összesített érték-arány | 🟡 6.5/10 | ✅ 8.5/10 | ✅ 8/10 | ✅ 8.5/10 | 🟡 7/10 | 🟡 7.5/10 |
*Gemini 1.5 Flash CEE coverage: Google belső training adatok HU/PL/CZ jelenlétét nem publikálják; a Flash modell multilingual erős, de a CEE specifikus ragozás-invariáns javítás mélysége tesztelendő.
ADR — Miért nem gpt-4o (full) és miért nem Gemini 2.5 Pro? (2026-04-19, végleges)
Döntés: A vocab-correction task szándékosan mini/flash modelleket használ. Ez NEM kompromisszum — ez a feladathoz optimális választás. Az alábbi okok egymást erősítik.
| Szempont | Mini/Flash (jelenlegi) | Full/Pro (elvetett) | Verdict |
|---|---|---|---|
| Instruction-following delta | 8/10 | 9.5/10 | +1.5 pont — a vocab-correction prompt egyszerű elég, hogy 8/10 is elég legyen |
| Cost delta/diktálás | ~$0.0001–0.0002 | ~$0.002–0.003 | 15–17× drágább — BYOK user saját számlájára megy |
| Latencia delta | +100–300ms | +300–600ms | +200–300ms extra — felhasználó érzi (3s flow-state limit) |
| Over-correction kockázat | Alacsony | Minimális | A különbség marginális — a full modell „okosabb" átírás kísértésével ellensúlyozza |
| Task komplexitás | Egyszerű szócsere — nem igényel reasoning-t | Reasoning kapacitás kihasználatlan marad | Pazarlás 10× áron |
| Szótárméret limit | 1 000+ szó (Mini/Flash) — elegendő | Nincs előny | Nincs win a full modellnél |
Mikor érdemes mégis full modellre váltani (trigger feltételek):
gpt-4o full → bekapcsol, ha:
✓ OpenAI BYOK user aktív szótára > 500 orvosi/jogi terminus
✓ AND user explicit "Maximum Quality" módot vált (opt-in Fázis 2+)
✓ AND user elfogadja a ~15× cost overhead-et (előre közölt)
→ Implementáció: quality_tier=["standard", "max"] setting + orchestrator branch
Gemini 2.5 Pro → bekapcsol, ha:
✓ Gemini BYOK user + aktív szótár > 1 000 szó (Flash 1M = bőséges, szóméret nem trigger)
✓ AND mért CEE WER romlás > 5% a Flash teszten (cédulaváltó)
→ Egyelőre nem indokolt — Fázis 2 A/B teszttől függ
Összefoglalva: A gpt-4o összesített érték-aránya 7/10 vs. gpt-4o-mini 8.5/10 — azaz a mini nem egyszerűen „olcsóbb alternatíva", hanem a vocab-correction taskhoz objektíven jobb választás, főleg ha figyelembe vesszük, hogy a full modell erős reasoning képessége itt kihasználatlan marad és olykor éppen az over-correction irányába tolja a modellt.
Fejlesztési konzekvenciák és watchlistek:
| Kérdés | Döntés / Figyelő |
|---|---|
| Mikor kell Llama 3.1 8B-t lecserélni? | Ha a Groq BYOK vocab-correction user-panasz top-3-ba kerül (over-correction, kihagyott szavak) → upgrade Llama 3.3 70B-re (drágább, de 8× pontosabb instruction-following) |
| Gemini CEE minőség validálás | Fázis 1.5 smoke test: 50 HU+EN mondat × 20 szótárszó → mért WER a javítás előtt/után. Ha rontja a CEE szavakat → fallback Groq Llama 3-ra Gemini STT esetén is |
| Llama 3.1 8B szótárméret limit | Ha aktív szótár > 100 szó + persona prompt → tokenszám > 4K → 8K kontextus szorul. Monitor: prompt_tokens logolása _orchestrator.py-ban. Küszöb: 6 000 token → warning |
| Azure gpt-4o-mini vs OpenAI gpt-4o-mini | Azonos modell, de Azure EU data residency-t ad → B2B healthcare/legal tier számára Azure BYOK kötelező ajánlás, nem opció |
| Gemini 1M kontextus kihasználás | Gemini BYOK vocab-correction esetén opcionálisan az egész session history beküldhető system-promptba → Gemini egyértelmű winner long-form B2B diktálásnál (orvosi lelet, jogi szerződés folytatása) |
Llama 3.1 8B Instant — ismert korlát: A modell 8B paramétermérete miatt a „ne változtass semmit a javításon kívül" boundary case-eknél nem 100% megbízható. A jelenlegi prompt a _lang_helpers.py-ban tartalmaz explicit záróutasítást: „Output ONLY the corrected transcript. Do not add explanations." — ez csökkenti, de nem eliminálja a kockázatot. Fázis 2-ben A/B teszt Llama 3.3 70B ellen.
Miért nem gpt-4o (full) és nem Gemini 2.5 Pro? A vocab-correction task szándékosan konzervatív modelleket használ: az egyszerű, gyors, olcsó modell (8B–mini méret) pontosan elég a szótárjavításhoz, és a veszélye kisebb mint egy erős modellé (kevesebb esély az „okos átírásra"). A jobb modell = jobb instruction-following, de nem = jobb output, ha a task inherentemente egyszerű.
Fejlesztési Feasibility Összefoglaló (mi fejleszthető melyik providernél)
| Feature | Groq | OpenAI | Gemini | Azure |
|---|---|---|---|---|
| Rolling context (Whisper prompt) | ✅ 224 tok | ✅ 200 tok | ✅ 1 000 tok | ✅ 224 tok |
| Vocabulary correction (LLM) | ✅ Llama 3 | ✅ gpt-4o-mini | ✅ 1.5 Flash | ✅ gpt-4o-mini |
| Low-confidence toast (GAP-C3) | ✅ avg_logprob |
❌ N/A | ❌ N/A | ❌ N/A |
| Word-level timestamps | ✅ | ❌ | ❌ | ❌ |
| WebSocket live streaming | ❌ | ❌ | 🟡 Fázis 3+ | ❌ (Speech-only, ADR kizárta) |
| EU GDPR compliance | ✅ | ❌ | ✅ (Vertex) | ✅ |
| B2B VNet integráció | ❌ | ❌ | 🟡 Vertex Private | ✅ |
| CEE code-switch minőség | ✅ Tesztelve | 🟡 Tesztelendő | 🟡 Tesztelendő | ✅ Whisper arch. |
Legfontosabb fejlesztési korlát (2026-04-19): A low-confidence toast (GAP-C3) csak Groq-nál működik natívan — az egyetlen provider, amelyik avg_logprob szegmens-szintű pontossági jelzést ad vissza. Az összes többi provider esetén a felhasználónak saját megfigyelésre kell hagyatkoznia.
Gemini rolling context stratégiai előnye: A Gemini 1.5 Flash 1M tokenes kontextusa lehetővé teszi, hogy az STT rolling context az egész diktálási session előzményét magában foglalja — nem csak az utolsó ~150 szót (224 token). Ez B2B long-form diktálóknál (orvosi lelet, jogi beadvány) lényegesen jobb kontextus-öröklést ad. A Gemini BYOK tier így valódi differenciáló érv hosszú dokumentumokhoz.
Session hard cap
# workers.py — session limitek
MAX_SESSION_DURATION = 360 # 6 perc másodpercben
WARNING_THRESHOLD = 300 # 5 percnél figyelmeztetés
Célja: Margin védelem (heavy usereknél veszteség megelőzése) + UX (fókuszált munkamód).
A Typeless szintén 6 perces session limitet alkalmaz — de az ő felhasználóik ezt negatívumként élik meg (flow state megszakítás). A VibeVox-ben ez tudatos UX döntés:
- Hold-to-talk modell = természetes szünet a gombengedéskor
- Session Summary Toast = „127 szó, ~3 perc megtakarítva" → pozitív megerősítés
- Margin védelem = heavy userek sem generálnak veszteséget
A VibeVox UX-ben a 6 perc NEM limit, hanem „mikro-fókusz session" framing.
Post-processing (post_process.py)
Filler word eltávolítás (opt-in, default be):
HU: ööö, hát, szóval, ugye, tehát, mondjuk
EN: um, uh, like, you know, basically
Automatic punctuation:
Mondatvég detektálás (hosszú szünet → pont)
Magyar kérdő mondat felismerés
Nagybetű mondatkezdetek
Fázis 2 tervezve:
Tone control (casual → formal)
Template alkalmazás (jogi emlékeztető, orvosi lelet)
Style Personas → ld. §2.3b Style Personas architektúra (alább)
2.3b. Style Personas — Stílus-személyiség rendszer (Fázis 1.5)
Döntés (2026-04-18): A Style Personas a VibeVox LLM post-processing pipeline kiterjesztése. Tier: FREE — teljes funkcionalitás beleértve a Custom Persona-t. Indok: a stílus-horgony a legerősebb retention driver; ha valaki kialakít egy saját stílust, a 20 000 szavas free kvóta lesz az egyetlen konverziós trigger — nem a feature hiánya.
Architektúra
STT output (nyers transzkript)
│
↓ LLM Post-Processing (Groq Llama 3 8B Instant / provider-matching)
│ system_prompt = style_persona_prompt + aktív szótárak (ha van)
│ EGYETLEN API hívás — nincs extra cost, nincs extra latencia
│
↓ Stílusban átírt végleges szöveg → aktív ablakba
Kulcsarchitektúrális döntés: A Style Persona prompt és a vocabulary lista ugyanabba a system promptba kerül — nincs második LLM hívás. A cost-overhead minimális: ~50–200 extra token a persona definíciójától függően.
Beépített Style Personas (FREE — teljes hozzáférés)
Alapstílusok:
| ID | Név | Leírás | Prompt stratégia |
|---|---|---|---|
standard |
Standard | Nincs átírás — pure transcription (alapértelmezett) | LLM nem fut |
concise |
Tömör | Max. 30%-os tömörítés, lényegre törő | „Keep core meaning, remove filler and padding" |
professional |
Professzionális | Formális, magázódó, strukturált | „Rewrite formally, use proper grammar" |
friendly |
Barátságos | Közvetlen, tegeződő, meleg hangvétel | „Casual, warm, use 2nd person singular" |
executive |
Vezetői összefoglaló | Bullet points, kulcspontok kiemelve | „Extract key points as bullet list" |
Formality Conversion — multi-language (implementálva: 2026-04-18):
UI:
app/ui/tabs/style_tab.py—_FORMALITY_LANG_MAPdict + language-aware toggle A Style tab Formality szekciója az elsődleges nyelv (primary_languagesetting) alapján automatikusan a megfelelő szabályokat alkalmazza.
| ID | Trigger nyelv | Preferred forms | Tiltott formák | Gender-aware? |
|---|---|---|---|---|
hu_onozo |
Hungarian | Ön • Önnek • Önt • Önnel | maga • magának (TILTOTT) | Nem |
de_siezen |
German | Sie • Ihnen • Ihr • Ihre | — | Nem |
fr_vouvoyer |
French | vous • votre • vos | — | Nem |
es_ustedeo |
Spanish | usted • su • sus | — | Nem |
it_lei |
Italian | Lei • La • Le | — | Nem |
pl_panpani |
Polish | Pan / Pani | — | Igen |
cs_vikani |
Czech | Vy • Vám • Vás | — | Nem |
sk_vikanie |
Slovak | Vy • Vám • Vás | — | Nem |
ru_vy |
Russian | Вы • Вас • Вам | — | Nem |
nl_u |
Dutch | u • uw | — | Nem |
ro_dvs |
Romanian | Dumneavoastră | — | Nem |
pt_senhor |
Portuguese | o senhor / a senhora | — | Igen |
Magyar „maga" tilalom (2026-04-18 döntés): Az LLM prompt KIZÁRÓLAG „Ön" alakokat produkálhat. A „maga" forma régies, lekezelő — explicit tiltani kell a promptban. Minden HU formality prompt záróutasítása: „SOHA ne használd a 'maga' alakot." A tegeződő/magázódó konverzió egyedülálló CEE piacon — marketing kulcsmondat: „Diktáld úgy, ahogy kényelmes — kapod úgy, ahogy illik."
Fun / Viral stílusok (FREE — megosztást generál):
| ID | Név | Leírás | Viral potenciál |
|---|---|---|---|
yoda |
🧙 Yoda | Megfordított mondatrend, archaikus szóhasználat | 🔴 Maximális — TikTok/Twitter demo |
victorian |
👑 Viktoriánus úr | Angol arisztokrata stílus, „I daresay" fordulatok | 🟠 Magas — EN-domináns |
pirate |
🏴☠️ Kalóz | Ahoy!, Arr!, tengerész szleng | 🟠 Magas — HU+EN vicces |
news_anchor |
📺 Hírolvasó | Formális, tárgyilagos tónus | 🟡 Közepes |
hal9000 |
🤖 HAL 9000 | Hideg, precíz, kissé fenyegető AI tónus | 🟠 Magas — tech/geek közösség |
Yoda kompatibilitás CEE nyelveken: Angolból vicces, mert az SVO normát töri meg (SOV). Magyar és szláv nyelveken az erőltetett szórendfordítás + archaikus szókincs kombinációja más mechanizmussal de hasonló hatást ér el. HU — várhatóan működik. PL/CZ/SK — A/B teszttel validálandó Fázis 1.5-ben.
Custom Style Persona (FREE — saját prompt)
Felhasználói szerkesztő:
„Írj úgy, mint egy 18. századi levélíró..."
„Minden mondatot kezdj igével..."
„Maradj max. 2 mondatos, tűhegyes legyél"
„Speak as an English aristocrat would..."
Korlátok:
Max. prompt hossz: 500 karakter (UI display) / ~1000 token (feldolgozás)
Sandbox: a user prompt rendszer-promptba kerül, NEM user-üzenetbe
→ prompt injection ellen védett
Tárolás: settings.db (lokális) + Supabase szinkron (ha bejelentkezve)
→ Multi-device: a saját stílus mindenhol elérhető
Custom Persona = FREE tier (2026-04-18 döntés): Ha valaki kialakítja a saját digitális hangját, ez a legerősebb pszichológiai lock-in — a 20 000 szavas kvóta lesz a konverziós trigger, nem a feature hiánya.
Brand Safety Tiltólista (2026-04-18 — kutatás alapján formalizálva)
Forrás:
viral_style_personas_cee_analysis.md §3— The "Red Flag" Spectrum
Custom Persona UI — blokkolt tartalmak (regex + proxy content filter):
❌ Aktív politikai vezető neve (Orbán, Babiš, Fico, Kaczyński…)
→ B2B reputációs kockázat: jogi/orvosi partner elveszítése
❌ Explicit profanitás vagy szexuális tartalom
→ B2B brand kizáró, enterprise deal-breaker
❌ Etnikai csoportokat negatívan caricaturizáló instrukció
→ GDPR reputációs kockázat + CEE community backlash
Implementáció: proxy-oldali regex blocklist + LLM moderation
Effort: ~0,5 nap (blocklist regex + proxy endpoint kiegészítés)
Beépített tiltólista — SOHA nem kerülnek official built-in personaként:
❌ Aktív CEE politikusok paródiája (Orbán, Babiš, Fico)
→ Partnerség-romboló, CEE B2B jogi szegmens számára disqualifying
❌ Borat / "Eastern European Mockery" archetype
→ Anti-CEE brand — ellentmond az alap positioning-nek
❌ Gen Z Brainrot / TikTok slang
→ Gyors avulás (temporális decay) = folyamatos prompt-maintenance cost
→ Custom Persona-ként lefedhető, built-in felesleges
✅ Typowy Janusz (PL): ENGEDÉLYEZETT — in-group, kulturálisan beágyazott
✅ Tabloid Vendég / Mónika (HU): ENGEDÉLYEZETT — energia paródiája, profanitás nélkül
✅ Rytmus (SK): DÖNTÉS FÜGGŐBEN — valós személy → jogi kockázat vizsgálandó
Prompt Engineering Robustossági Szabályok (2026-04-18)
Forrás:
viral_style_personas_cee_analysis.md §1— LLM Feasibility
1. Szemantikai integritás — kötelező záró utasítás MINDEN beépített promptban:
Minden persona system prompt KELL tartalmazzon:
"Keep ALL factual content, numbers, names, and dates exactly as stated.
Do NOT add, remove, or alter any factual information."
Indok: a szemantikai inverzió (AI átírja/rövidíti a tartalmat) az AI diktáló
appok #1 churn triggerének bizonyult. ← Már implementálva a fenti BUILT_IN_PERSONAS dict-ben.
2. CEE personák — few-shot záradék kötelező (Fázis 1.5):
A Typowy Janusz prompt tartalmazzon 1 példapárt, mert Groq Llama 3
generic approximation-re esik vissza few-shot nélkül:
Példa input: "A szoftver frissítése 2 napot vett igénybe."
Példa output: "Kiedyś to było — két nap egy frissítésre?! Grażyna, hallod ezt?
Régen ez öt perc alatt ment, mert az emberek DOLGOZTAK."
3. Yoda CoT (Chain-of-Thought) szintaxis inverziónál:
A Yoda prompt már tartalmazza a lépéseket:
Step 1: Identify the main verb.
Step 2: Move the object to sentence start.
Step 3: Place subject and verb at end.
← Ez 60-70%-kal javítja az OSV-konzisztenciát komplex mondatokon (kutatás alapján).
Technikai implementáció
# style_personas.py — örököl az LLM post-processing pipeline-tól (_orchestrator.py)
BUILT_IN_PERSONAS = {
"standard": None, # LLM NEM fut
"concise": "Rewrite the following transcription concisely. Keep all meaning, remove filler and padding. Output only the rewritten text. Keep ALL factual content, numbers, names, and dates exactly as stated.",
"professional": "Rewrite the following transcription in formal, professional language. Use önöző (formal) form for Hungarian. Keep all content. Keep ALL factual content, numbers, names, and dates exactly as stated.",
"friendly": "Rewrite the following transcription in a warm, casual, tegeződő style. Keep all content. Keep ALL factual content, numbers, names, and dates exactly as stated.",
"executive": "Extract the key points from the following transcription as a concise bullet list. Keep ALL factual content, numbers, names, and dates exactly as stated.",
# ── Formality Conversion — language-aware (Style tab toggle) ─────────────
"hu_onozo": "Alakítsd át az alábbi szöveget magázódó stílusra. Kizárólag 'Ön' alakokat használj (Önnek, Önt, Önnel, Önhöz). SOHA ne használd a 'maga' szót. Minden tartalmat őrizz meg.",
"de_siezen": "Wandle den folgenden Text in eine formelle Anrede um. Verwende 'Sie', 'Ihnen', 'Ihr', 'Ihre'. Behalte alle Inhalte bei.",
"fr_vouvoyer": "Transforme le texte suivant en vouvoiement. Utilise 'vous', 'votre', 'vos'. Conserve tout le contenu.",
"es_ustedeo": "Transforma el siguiente texto al tratamiento formal. Usa 'usted', 'su', 'sus'. Conserva todo el contenido.",
"it_lei": "Trasforma il seguente testo in forma formale. Usa 'Lei', 'La', 'Le', 'Suo'. Mantieni tutto il contenuto.",
"pl_panpani": "Przekształć poniższy tekst na formę grzecznościową. Użyj formy 'Pan' lub 'Pani' (odpowiednio do kontekstu). Zachowaj całą treść.",
"cs_vikani": "Převeď následující text do vykání. Používej 'Vy', 'Vám', 'Vás'. Zachovej veškerý obsah.",
"sk_vikanie": "Preveď nasledujúci text do vykania. Použi 'Vy', 'Vám', 'Vás'. Zachovaj celý obsah.",
# ── Fun / Viral stílusok ─────────────────────────────────────────────────
"yoda": ("Rewrite the following text in the style of Yoda from Star Wars. "
"Step 1: Identify the main verb. Step 2: Move the object to sentence start. "
"Step 3: Place subject and verb at end. Use archaic phrasing. "
"Keep ALL factual content, numbers, names, and dates exactly as stated."),
"victorian": "Rewrite the following text as a Victorian English gentleman would write. Use formal, elaborate language with period-appropriate phrases. Keep ALL factual content exactly as stated.",
"pirate": "Rewrite the following text in pirate speak. Add nautical metaphors. Keep ALL factual content, numbers, names, and dates exactly as stated.",
"news_anchor": "Rewrite the following text as a professional news anchor would deliver it. Neutral, formal, declarative. Keep ALL factual content exactly as stated.",
"hal9000": "Rewrite the following text in the style of HAL 9000. Cold, precise, slightly ominous. Keep ALL factual content exactly as stated.",
# ── CEE personák (Fázis 1.5 — 2026-04-18) ───────────────────────────────
"linkedin_lunatic": (
"You are a viral LinkedIn influencer. Rewrite the user's input as a sensationalized, "
"self-congratulatory corporate post. Use single-sentence paragraphs. Inject words like "
"'leverage', 'synergy', 'deep dive', 'bandwidth', 'pivot'. Add rocket (🚀) and "
"fire (🔥) emojis. Conclude with a leadership lesson and 3 hashtags. "
"Keep ALL factual content, numbers, names, and dates exactly as stated."
),
"newsreel_1950": (
"Rewrite the text to sound like a dramatic 1950s radio news anchor. Use rapid-fire, "
"highly formal sentence structures. Include mid-century colloquialisms: 'say, buddy', "
"'swell', 'gee whiz'. Frame the information as a sensational, breaking news bulletin. "
"Keep ALL factual content exactly as stated."
),
"typowy_janusz": (
"Rewrite the text in Polish as a 'Typowy Janusz' — a complaining, provincial middle-aged "
"Polish man. Use phrases like 'Kiedyś to było...'. Complain about costs and taxes. "
"Reference your wife Grażyna or son Pjoter occasionally. Misspell common foreign loanwords "
"phonetically (e.g. 'olinkluziw' for all-inclusive). "
"Keep ALL factual content exactly as stated."
),
"moravian_slang": (
"Translate the text into highly colloquial Moravian Czech. Use 'su' instead of 'jsem'. "
"Maximize regional street slang and morphological reductions. Maintain the underlying meaning."
),
"prague_slang": (
"Translate the text into highly colloquial Prague Czech (Pražák dialect). Use 'seš' instead "
"of 'jsi'. Maximize colloquial reduction. Maintain the underlying meaning."
),
"hu_monika": (
"Rewrite the text in Hungarian in the energetic, dramatic style of a daytime tabloid TV "
"guest. Use CAPITALIZATION for emphasis, multiple exclamation marks, rhetorical questions. "
"Convey escalating emotional intensity. Do NOT use profanity. "
"Keep ALL factual content exactly as stated."
),
}
def get_llm_system_prompt(persona_id: str, vocab_list: list, user_custom_prompt: str = None) -> str | None:
"""Returns None if no LLM processing needed (standard persona + no vocab)"""
persona_prompt = user_custom_prompt or BUILT_IN_PERSONAS.get(persona_id)
if not persona_prompt and not vocab_list:
return None # LLM nem fut — regex pipeline marad
parts = []
if persona_prompt:
parts.append(persona_prompt)
if vocab_list:
parts.append(f"Additionally, correct these domain-specific terms: {', '.join(vocab_list)}")
return "\n\n".join(parts)
| Trigger kombináció | LLM fut? | System prompt tartalma |
|---|---|---|
| Standard + nincs szótár | ❌ | — (regex pipeline csak) |
| Standard + aktív szótár | ✅ | vocabulary correction only |
| Yoda + nincs szótár | ✅ | persona prompt only |
| Professional + aktív szótár | ✅ | persona + vocabulary combined |
| Custom persona + szótár | ✅ | user prompt + vocabulary combined |
Tesztelési scope: 18 persona × managed/BYOK × szótár aktív/inaktív = 36 kombináció alap
- 6 CEE persona × 4 CEE nyelv = 24 CEE-specifikus kombináció → **Összesen: 60 teszt Fejlesztési sprint: Fázis 1.5 (D+30–D+45)
Context-Aware Output Formatting — „Bet 3" (Fázis 2)
Döntés (2026-04-11 · riport: „Bet 3"): A Context-Aware Output Formatting a VibeVox mélység-moatjának következő rétege — az aktív ablak alapján adaptált szövegformázás olyan OS-szintű integráció, amelyet cloud SaaS versenytársak (Wispr, Typeless) technikailag nem tudnak replicate-elni.
Hogyan működik:
Aktív ablak detektálás (Win32 API / Linux wnck → process class)
│
↓ Alkalmazás osztályozás
│
├─ VS Code / JetBrains IDE → „Vibe Coding Mode": camelCase/PascalCase/snake_case
│ (pl. „user profile component" → `UserProfileComponent`)
│
├─ Terminal / Shell → bash szintaxis: „sudo install nginx" → `sudo apt install nginx`
│
├─ Slack / Discord / Teams → casual tone, filler preservation, emoji-toleráns
│
├─ Word / LibreOffice Writer → Document mode: auto paragraph, formal tone, heading detektálás
│
└─ Default (böngésző, egyéb) → Standard Smart Mode (filler removal + írásjel)
| Alkalmazás osztály | Process | Formázási hatás |
|---|---|---|
| VS Code / JetBrains | code, idea, pycharm |
camelCase / PascalCase / snake_case azonosítás |
| Terminal emulators | cmd, powershell, bash, fish |
shell szintaxis, sudo, git parancsok |
| Slack / Discord | Slack.exe, Discord.exe |
casual tone, nincs auto-formális írásjel |
| MS Word / LibreOffice | WINWORD.EXE, swriter |
document formázás, heading detektálás |
Implementáció (Fázis 2, D+90–D+105):
app_context_detector.py— OS-specifikus aktív ablak lekéréscontext_formatter.py— alkalmazás osztály → formázási szabályok dispatcher- Felhasználói override: minden alkalmazásnál kézzel felülírható (Settings → App Contexts)
2.5. Offline STT motor — faster-whisper + INT8 (Fázis 2)
Döntés (2026-04-11): A VibeVox offline módja a
faster-whisperkönyvtárra épül, CTranslate2 motorral, INT8 kvantálással. Ez a konfiguráció a legjobb ár/minőség/memória arányt nyújtja fogyasztói hardveren.
Miért faster-whisper, nem az OpenAI whisper csomag?
| Metrika | OpenAI whisper (FP16) |
faster-whisper (INT8) |
|---|---|---|
| Számítási motor | PyTorch | CTranslate2 (C++ alapú) |
| RAM igény (large-v3-turbo) | ~6.4 GB | ~3.0 GB |
| Sebesség | Alap | 4×+ gyorsabb |
| INT8 kvantálás | Kézi, körülményes | compute_type="int8" — 1 sor |
| Telepítési méret | ~2.5 GB (PyTorch) | ~400 MB (CTranslate2) |
Miért nem Distil-Whisper?
Distil-Whisper CEE-n: fundamentálisan alkalmatlan. A riport elemzése szerint a Distil-Whisper 60–80%-kal kevesebb paraméterrel dolgozik, mint a large-v3-turbo — a CEE agglutináló morfológia (HU) és a klaszter-gazdag fonológia (PL) kezelésére ez elégtelen.
| Metrika | Distil-Whisper large-v2 | faster-whisper large-v3-turbo (INT8) |
|---|---|---|
| Paraméterek | ~756M (50%-kal kevesebb) | ~809M (turbo-optimalizált) |
| Magyar WER (riport benchmark) | ~18–25% | ~3–5% |
| Lengyel WER | ~14–20% | ~4–6% |
| CEE morfológia kezelés | ❌ Gyenge (distillation eltávolítja a ritka token reprezentációkat) | ✅ Kiváló |
| Sebesség CEE-n | ~2.5× gyorsabb mint large-v2 | ~4× gyorsabb (INT8 kvantálás hatása) |
Következtetés: A Distil-Whisper sebességelőnye a faster-whisper INT8 kvantálással minőségromlás nélkül elérhető. Distil-Whisper a VibeVox egyetlen pipeline szintjén sem szerepel — sem offline motorként, sem fallback-ként.
INT8 kvantálás — hogyan működik?
A Whisper neurális hálózat súlyait (weights) számokként tárolja. A precizitás meghatározza a memóriaigényt:
FP32 (32 bit/szám): ~6.4 GB RAM — feleslegesen pontos CPU-n
FP16 (16 bit/szám): ~3.2 GB RAM — standard, de még sok
INT8 (8 bit/szám): ~1.6 GB RAM ← modell fájl mérete
Futtatási RAM dekompozíció (large-v3-turbo, INT8, CPU):
Modell súlyok (INT8): ~1.6 GB
Aktivációs memória (FP16): ~0.8 GB ← számítás közbeni ideiglenes tenzor
Audio buffer + tokenizer: ~0.4 GB
Python / OS overhead: ~0.2 GB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Összesen: ~3.0 GB RAM
Minőség hatás (WER delta, CEE nyelveken):
- FP16 → INT8 kvantálás: ~0.3–0.5% WER romlás — emberi fülnek érzékelhetetlen
- Üzleti következmény: nincs, a minőségi fogadalmak tarthatók
Implementáció (1 sor konfiguráció)
from faster_whisper import WhisperModel
model = WhisperModel(
"large-v3-turbo", # ~1.6 GB letöltés (egyszer, cache-elve)
device="cpu", # GPU nélkül is fut — fogyasztói laptopokon
compute_type="int8" # INT8 kvantálás: 3× kisebb RAM, 4× gyorsabb
)
segments, info = model.transcribe(
audio_file,
language="hu", # Szint 1: Primary Language PIN (nem auto-detect)
beam_size=5
)
Offline pipeline (Fázis 2)
Hang rögzítés (workers.py)
│ WAV, max 6 perc session
↓
RAM detekció (psutil) — induláskor EGYSZER, cachelve
│
├─ RAM ≥ 8 GB → Offline pipeline (lentebb)
└─ RAM < 8 GB → Cloud fallback (Deepgram/Groq) + Toast figyelmeztetés
│
↓ [Offline ág]
faster-whisper model (large-v3-turbo, INT8, CPU)
│ Lokális inferencia — hang nem hagyja el a gépet
│ Várható sebesség: ~RTF 0.3–0.6 (reáltime 1.6–3.3× sebességgel)
│
↓
post_process.py (filler removal, írásjel) — azonos a cloud pipeline-nal
│
↓
Szöveg beillesztése az aktív ablakba
│
↓
Storage: SQLite (local) — felhő szinkron opcionális (history feature)
Hardver threshold táblázat
| RAM | GPU (VRAM) | Ajánlott modell | Mód |
|---|---|---|---|
| < 8 GB | — | — | ❌ Cloud fallback (automatikus) |
| 8–15 GB | — | large-v3-turbo (INT8, CPU) | ✅ Offline Turbo |
| 16–31 GB | — | large-v3-turbo (INT8, CPU) | ✅ Offline Turbo (ajánlott sáv) |
| 32 GB+ | CPU only | large-v3-turbo (INT8) | ✅ Offline Turbo, max kényelem |
| 32 GB+ | ≥ 10 GB VRAM | large-v3 (FP16, CUDA/ROCm) | ✅ Offline Prémium (opt-in, ~10 GB VRAM) |
BYOK LTD tartalmazza az offline módot — nem addon. A per-device beállítás Supabase-ben tárolódik: az erős laptop offline Turbo-n fut, a gyenge eszköz/telefon automatikusan cloud-ra vált. Egy account, minden eszközön a megfelelő mód.
Modell letöltő UX specifikáció (Fázis 2)
In-app letöltő wizard (első offline aktiváláskor):
┌─────────────────────────────────────────────────┐
│ Offline mód beállítása │
│ │
│ Rendszer: 16 GB RAM ✅ (Elegendő) │
│ │
│ ★ AJÁNLOTT: Whisper large-v3-turbo │
│ Méret: 1.6 GB | RAM igény: ~3 GB │
│ Minőség: CEE nyelveken kiváló │
│ [████████████████░░░░] 73% ~2 perc │
│ │
│ ○ Prémium: Whisper large-v3 (csak 32 GB+ RAM) │
│ Méret: 3.1 GB | VRAM: ≥10 GB szükséges │
│ [Letöltés] │
└─────────────────────────────────────────────────┘
Jövőbeli gyorsítási útvonalak (Fázis 3+)
Miért nem most? A
faster-whisperINT8 CPU-n Fázis 2-re elegendő (hold-to-talk use case: nem real-time streaming). A GPU gyorsítás Fázis 3-ban kerül napirendre, ha a CEE user feedback latencia-panaszt jelez.
A három gyorsítási opció összehasonlítása:
| Technológia | Eszköz | RTF* | 60 mp átírása | Elérhetőség | Komplexitás |
|---|---|---|---|---|---|
faster-whisper INT8 |
CPU | ~0.4 | ~24 mp | ✅ Minden laptop | ✅ Alacsony |
faster-whisper CUDA |
NVIDIA dGPU | ~0.05 | ~3 mp | ⚠️ NVIDIA laptopok | ✅ Alacsony (auto-detect) |
whisper.cpp Vulkan |
iGPU (Intel/AMD) | ~0.1–0.15 | ~6–9 mp | 🟡 Minden modern laptop | 🔴 Magas |
RTF = Real-Time Factor (0.1 = 10× valós idő felett)
faster-whisper CUDA — Fázis 2 opcionális (alacsony effort)
Ha NVIDIA dGPU detektálva → device="cuda" automatikusan. Csak 1 sor változás:
import torch
device = "cuda" if torch.cuda.is_available() else "cpu"
model = WhisperModel("large-v3-turbo", device=device, compute_type="int8")
# Ha NVIDIA GPU van: CUDA, ha nincs: CPU — ugyanaz a kód
Implementációs cost: ~1 nap. Fázis 2-ben bekapcsolható ha a
torch+cudatoolkitdependency vállalható.
whisper.cpp + Vulkan — mi ez és miért Fázis 3?
whisper.cpp = a Whisper modell C++-ban újraírva
- Nincs Python, nincs PyTorch
- Natív bináris → minimális méret, maximális sebesség
Vulkan = alacsony szintű GPU API (Khronos, nyílt szabvány)
Összehasonlítás:
┌──────────┬────────────┬───────────────────────────┐
│ API │ Gyártó │ Fut ezen │
├──────────┼────────────┼───────────────────────────┤
│ CUDA │ NVIDIA │ Csak NVIDIA dGPU │
│ ROCm │ AMD │ Csak AMD dGPU (korl.) │
│ Metal │ Apple │ Csak Mac │
│ Vulkan │ Khronos │ NVIDIA + AMD + Intel iGPU│
└──────────┴────────────┴───────────────────────────┘
iGPU (Integrált GPU) = CPU-ba épített grafikus processzor
- MINDEN modern Intel/AMD laptopban van
- Nincs saját VRAM — a rendszer RAM-ból merít
- Intel Iris Xe (2020+) / AMD Radeon Vega (Ryzen 4000+)
Miért vonzó: 3-4× gyorsabb a CPU-nál, és minden laptopban van
Miért nem Fázis 2?
| Blokkoló | Részletek |
|---|---|
| Driver stabilitás | Intel Xe + Vulkan 2025-ben: kiszámíthatatlan crashek egyes disztribúciókon |
| Python integráció | C++ könyvtár → pywhispercpp wrapper szükséges (külső, nem hivatalos) |
| CEE WER ismeretlen | Nincs publikus benchmark iGPU + Vulkan kombináción CEE nyelveken |
| Build komplexitás | Custom CMake build + Vulkan SDK szükséges a disztribúcióhoz |
faster-whisper elég |
Hold-to-talk use case-re a CPU sebesség elfogadható |
ADR-001: On-Device STT Integration Decision (GAP-3)
Státusz: HALASZTVA — 12 hónapos deferred döntés, formalizálva 2026-04-11
Ez az ADR rögzíti, hogy a VibeVox mikor és milyen feltételekkel vezeti be a whisper.cpp + NPU/Vulkan hardware-gyorsított offline motort. A faster-whisper INT8 CPU-motor (2.5. szekció) ettől független, már eldöntött Fázis 2 funkció.
Kontextus
A VibeVox jelenleg két offline STT track-et tart nyilván:
| Track | Technológia | Fázis | Döntés |
|---|---|---|---|
| A — Szoftver-alapú | faster-whisper INT8, CPU/CUDA |
Fázis 2 (D+77) | ✅ ELDÖNTVE — implementálás folyamatban |
| B — Hardware-gyorsított | whisper.cpp + Vulkan/NPU |
Fázis 3+ | ⏸️ HALASZTVA — jelen ADR határozza meg |
Ez az ADR kizárólag a Track B döntési keretét rögzíti.
Döntés
A whisper.cpp + Vulkan/NPU integrációja halasztva. A Track A (faster-whisper) elegendő a Fázis 2 use case-re. A Track B-re való áttérés csak akkor indul, ha az alábbi triggerek MIND teljesülnek.
Triggerek — minden feltétel szükséges
1. Hardware Trigger — NPU driver stabilitás
AMD Ryzen AI (XDNA architektúra) / Intel Lunar Lake NPU
Target Q: Q3 2027 (gyártói roadmap alapján)
Mérés: 3+ egymást követő negyedévben nulla driver crash report
CEE célplatformokon (Fedora 41+, Ubuntu 26.04 LTS)
Forrás: kernel.org AMD/Intel driver changelog, LWN.net GPU hírek
2. Minőségi Trigger — CEE WER benchmark
whisper.cpp Vulkan + Large-v3-Turbo INT8
Küszöb: CEE WER ≤ 5% delta a faster-whisper CPU INT8-hoz képest
(HU + PL tesztkészleten — azonos tesztprotokollt mint D+83 A/B teszt)
Publikus: Minimum 1 reprodukálható nyilvános benchmark szükséges
Ha delta > 5%: Track B elutasítva, addig Track A marad
3. UX/Disztribúció Trigger — Flatpak kompatibilitás
Feltételek:
- Flatpak bundle méret ≤ 3 GB (modell + runtime együtt)
- Auto-update megoldható (delta package vagy külső model store)
- Flatpak sandbox: Vulkan hozzáférés konszisztensen működik
(jelenleg: --device=all szükséges, sandbox escape)
Mérés: Flathub submission teszt Fedora + Ubuntu clean install-on
4. Felhasználói Visszajelzés Trigger
Threshold: Latencia-panasz > 5% support ticketek
(kizárólag Managed Cloud + offline mode kombináltan)
Mérés: Plain.com ticket kategorizáció negyedévenként
Következmények (ha MINDEN trigger teljesül)
Aktiválás:
1. Kutatási sprint: 2 hét
→ whisper.cpp build pipeline (CMake + Vulkan SDK + Flatpak)
→ CEE WER benchmark saját tesztkészleten
→ pywhispercpp wrapper stabilitás vizsgálat
2. Fázis 3 feature:
→ Track B opcionális, opt-in UI a Track A mellé
→ "Kísérleti — NPU gyorsítás" jelölés első 2 kiadáson
3. Track A nem szűnik meg:
→ Fallback: ha NPU driver crash → automatikus Track A
Negyedéves Review Ütemezés
| Dátum | Review feladat |
|---|---|
| 2026-10-01 (Q3) | NPU driver + minőség + UX trigger státusz — első check |
| 2027-01-01 (Q4) | Lunar Lake / Ryzen AI driver release notes review |
| 2027-04-01 (Q1) | Döntési pont: triggerek teljesülnek? → Fázis 3 sprint indítás? |
| 2027-07-01 (Q2) | Ha 2027 Q1-es sprint eredményes: Fázis 3 éles implementáció |
Review kötelező elvégezni akkor is, ha nincs látható változás. A negyedéves check biztosítja, hogy nem születnek ad-hoc döntések 12 hónappal later.
2.6. Mid-Dictation Abort — ESC Hotkey Specifikáció (GAP-C5)
Döntés (2026-04-18 · GAP-C5 elfogadva): Az ESC key mid-dictation abort a keyboard-native, legkisebb súrlódású megoldás a "Scratch that" voice command-alapú Dragon-megközelítéssel szemben. Fázis 1-ben implementálandó — a becsült effort ~3 óra.
Forrás: strategic_ux_architecture_analysis.md — GAP-C5
Két fázisú abort modell
ESC = Mid-Dictation Abort
── FÁZIS A: Aktív diktálás közben (hotkey tartva) ─────────────────────
Esemény: User ESC-t nyom miközben a diktálás gombot tartja
1. workers.py → audio buffer drop (rögzített hang eldobva)
2. ui.py / live_bubble.py → Live Bubble clear (UI azonnali törlés)
3. workers.py → WebSocket kapcsolat bontva (stream severed)
4. KRITIKUS: hotkey release NEM injektál szöveget
→ inject_text() hívás blokkolt, ha abort_flag = True
abort_flag életciklus:
ESC_keydown → abort_flag = True
hotkey_release → inject_text() FeltételVizsgálat: if abort_flag → skip
hotkey_release → abort_flag = False (reset következő sessionra)
── FÁZIS B: Post-injection (szöveg már a target appban van) ──────────
Esemény: szöveg már beillesztve → user rossz volt a diktálás
Megoldás: Ctrl+Z (natív OS undo)
→ a host app undo history kezeli (Word, VS Code, stb.)
→ VibeVox NEM tart külön undo stacket
→ NEM implementálunk saját voice-based correction engine-t
UI feedback
ESC abort esetén:
→ Toast megjelenítés (1 másodperc auto-dismiss):
\"❌ Diktálás megszakítva\"
→ Sentry breadcrumb loggolás (ha opt-in):
sentry_sdk.add_breadcrumb(category=\"dictation\", message=\"dictation_aborted\", level=\"info\")
Sugallt UX pozicionálás: ESC = \"vészkijárat\" — nem hibaállapot, hanem tudatos felhasználói kontroll.
Implementációs spec (workers.py)
# Az abort_flag session-szintű állapot — a WorkerThread példányhoz kötött
class DictationWorker(QThread):
def __init__(self):
self.abort_flag = False # ← ESC lenyomáskor True
def on_esc_pressed(self):
\"\"\"Global ESC hotkey handler — csak aktív session közben aktív.\"\"\"
if self.is_recording:
self.abort_flag = True
self.stop_recording() # audio buffer drop
self.clear_live_bubble() # UI törlés
self.sever_connection() # WebSocket bontás
self.show_toast(\"❌ Diktálás megszakítva\", duration_ms=1000)
def on_hotkey_released(self):
if self.abort_flag:
self.abort_flag = False # reset jövő sessionra
return # ← inject skip
self.inject_text(self.transcript)
ESC vs. Toggle Mode: Toggle Mode-ban (ahol a gomb egyszeri nyomás indít/megállít) az ESC szemantikája azonos: a folyamatban lévő session leállítása szöveginjektálás nélkül. A hotkey_mode enum-tól független az abort logika.
2.7. Select & Capture Vocabulary Building — Globális Hotkey (GAP-C4)
Döntés (2026-04-18 · GAP-C4 elfogadva): A Select & Capture UX pattern a custom vocabulary feature Fázis 2 implementációjának kritikus belépési pontja. A Settings-alapú szótárfelvétel high-friction — ez az organikus, in-context capture módszer a power user retenciójának kulcsa.
Forrás: strategic_ux_architecture_analysis.md — GAP-C4
Hotkey specifikáció
Billentyűkombináció: Ctrl+Shift+V
Globális: működik minden alkalmazásban, miközben a VibeVox a tálcán fut
Ütközés-ellenőrzés:
✅ Windows: nem ütközik rendszer shortcut-tal
✅ Linux (X11 + Wayland): nem ütközik xdg/Gnome/KDE alapszabályokkal
⚠️ VS Code: Ctrl+Shift+V = Markdown Preview megnyitása
→ Settings → VS Code-ban override lehetséges
→ Toast figyelmeztetés: ha VS Code ablak aktív, egyedi konfig ajánlott
Teljes add-flow
1. User diktál → STT \"Supabase\"-t \"super base\"-ként hozza vissza
2. User billentyűzettel javítja: [super base] → [Supabase]
3. User kijelöli a javított szót: [Supabase] (OS clipboard tartalom)
4. User megnyomja: Ctrl+Shift+V
5. VibeVox globális hotkey listener → clipboard olvas → term = \"Supabase\"
6. Toast jelenik meg (2 másodperc):
\"✅ 'Supabase' hozzáadva az Egyéni Szótárhoz\"
7. Háttérben:
a. SQLite INSERT INTO vocabulary (term, ...) VALUES (...)
b. Supabase cloud sync (ha sync_mode = \"cloud\")
c. Groq API rolling context: következő diktálásnál az LLM post-processing
prompt tartalmazza az új szót (ha szótár aktív → LLM pipeline futtatódik)
Alternatív belépési pontok (B2B szótárcsomag import)
Tier 1 — Egyéni word-by-word (Fázis 2, alapfunkció):
Select & Capture (Ctrl+Shift+V) ← jelen szekció
Tier 2 — Bulk import (Fázis 2, B2B):
Settings → Vocabulary → Import
Formátum: .csv (term, replacement)
Newton .dic / .xml kompatibilis import wizard (Newton migration path)
Tier 3 — Iparági szótárcsomag (Fázis 2+):
Admin-telepített szótárak (jogi, orvosi, tech) — B2B admin konzol
Supabase-szinkronizált: admin egyszer veszi fel, minden user appjában megjelenik
Implementációs scope (vocabulary_manager.py + hotkey listener)
# vocabulary_manager.py — Select & Capture handler
def capture_selected_text_as_vocab_term(clipboard_text: str) -> bool:
\"\"\"
Global Ctrl+Shift+V handler.
Beolvassa a kijelölt (clipboard) szöveget, és hozzáadja a szótárhoz.
Returns True ha sikeres, False ha üres clipboard / duplikátum.
\"\"\"
term = clipboard_text.strip()
if not term or len(term) > 100: # limit: ne legyen egész mondat
show_toast(\"⚠️ Érvénytelen kijelölés — egyetlen szót vagy kifejezést jelölj ki.\")
return False
if vocabulary_db.exists(term):
show_toast(f\"ℹ️ '{term}' már szerepel a szótárban.\")
return True
vocabulary_db.insert(term)
supabase_sync.push_vocab_update(term) # aszinkron, nem blokkoló
show_toast(f\"✅ '{term}' hozzáadva az Egyéni Szótárhoz\", duration_ms=2000)
return True
# hotkey_controller.py / controller.py — globális listener regisztráció
keyboard.add_hotkey(\"ctrl+shift+v\",
lambda: capture_selected_text_as_vocab_term(pyperclip.paste()),
suppress=False)
B2B vonzat: Ez a feature a domain jargon failure (#2 churn trigger, riport szerint) közvetlen megoldása. A Select & Capture + cloud sync kombináció teszi lehetővé az irodai admin szótárkezelést: 11_Sales_B2B.md §B2B többletértékek. Az LLM post-processing pipeline (§2.1 Szint 2c) automatikusan felveszi a new term-eket a következő diktálásban.
Technológia stack
| Komponens | Technológia | Verzió |
|---|---|---|
| Web framework | FastAPI | 0.110+ |
| Runtime | Python | 3.11+ |
| Infrastruktúra | Google Cloud VPS | US régió (transit only) |
| Auth | JWT / Supabase token | — |
| Szervice manager | systemd | VibeVox-proxy.service |
Package struktúra (v1.5.x után refaktorált)
vtj_proxy/
├── __init__.py
├── config.py ← Env vars, Stripe keys, Supabase URL
├── db.py ← SQLite operations, quota tracking
├── auth.py ← JWT validation, Supabase auth
├── routes/
│ ├── transcribe.py ← /transcribe endpoint (STT routing)
│ ├── billing.py ← /webhook (Stripe events)
│ └── health.py ← /health check
└── handlers/
├── stt_router.py ← Provider-agnostik STT routing (plugin-style, sorrend cserélhető)
├── deepgram_handler.py ← Deepgram Nova-3 WebSocket (PRIMARY — live streaming, managed cloud)
├── elevenlabs_handler.py ← ElevenLabs Scribe v2 (másodlagos managed fallback — speaker diarization)
├── groq_handler.py ← Groq Whisper large-v3 (BYOK alt. / batch fallback — nincs WebSocket)
├── openai_handler.py ← OpenAI gpt-4o-transcribe (végső fallback)
└── quota_handler.py ← Free tier enforcement
STT Provider Chain — managed cloud prioritási sorrend
A stt_router.py plugin-architektúrájú — új provider beillesztése egyetlen új handler fájlt igényel, a routing logika érintése nélkül. Ez a provider lock-in elleni stratégiai döntés.
| Prioritás | Provider | Protokoll | Trigger |
|---|---|---|---|
| 1. PRIMARY | Deepgram Nova-3 | WebSocket streaming | Default — minden managed cloud session |
| 2. FALLBACK-A | ElevenLabs Scribe v2 | REST batch | Deepgram 502/503 error vagy speaker diarization request |
| 3. FALLBACK-B | Groq Whisper large-v3 | REST batch | ElevenLabs hiba |
| 4. LAST RESORT | OpenAI gpt-4o-transcribe | REST batch | Groq hiba |
| B2B PREMIUM | Azure MAI-Transcribe-1 | REST / streaming | BYOK konfigurációban — jogi/orvosi B2B szegmens |
Azure MAI-Transcribe-1 (B2B Premium — Fázis 2): Azure AI Foundry dedikált EU geo-fenced instance — 100% EU data residency törvényi elváráshoz (nem csak SCC-alapú megállapodás), jogi/orvosi B2B ügyfeleknek. ~2.8–3.2× drágább a Groq-nál, de BYOK-on a felhasználó viseli. Bekerül a BYOK provider listába Fázis 2-ben.
ElevenLabs Scribe v2: A Deepgram elsődleges managed fallbackje — kiváló speaker diarization képességei miatt különösen értékes a B2B interjú/meeting transzkripció use case-ekben (Fázis 2+ feature). REST-alapú (nem WebSocket), ezért fallback esetén az UX UI jelzi: „Backup mode — slight delay expected".
API endpoints
| Endpoint | Metódus | Leírás | Auth |
|---|---|---|---|
/transcribe |
POST | STT requests routing | JWT |
/webhook |
POST | Stripe webhook events | Stripe signature |
/health |
GET | Service health check | — |
/usage |
GET | User quota status | JWT |
Quota enforcement logika
FREE_TIER_MONTHLY_MINUTES = 180
SESSION_MAX_MINUTES = 6
# Ellenőrzési pontok:
# 1. Session indításakor: van-e kvóta?
# 2. Session alatt: 6 perces cap betartása
# 3. Hónap váltásakor: kvóta reset
VPS architektúra megjegyzések
A jelenlegi VPS US régióban van, de ez GDPR-szempontból nem probléma — a proxy nem tárol hangfelvételt, csak továbbít (transit). B2B marketing erősítés érdekében EU-ba helyezés mérlegelendő (Fázis 2).
4. Adatbázis és szinkronizáció
Helyi adatbázis (SQLite)
-- Főbb táblák:
transcription_history(
id, user_id, text, word_count, duration_sec,
created_at, synced_at, app_context
)
vocabulary(
id, user_id, term, replacement, language,
created_at, synced_at
)
usage_stats(
id, user_id, month, minutes_used, words_total,
sessions_count, last_updated
)
Supabase cloud szinkronizáció
Adatközpont: Supabase Zürich (eu-central-2) — szöveges adatok EU-ban maradnak
Technológia: PostgreSQL (Supabase managed)
Auth: Supabase Auth (JWT + Row Level Security)
Ár szintek: Free ($0) → Pro ($25/hó) — ~100K user-ig free tier elegendő
# sync.py — szinkronizáció logika (v1.5.x)
# Ismert bug: db_insert() egyenként triggereli a pruning logikát
# Megoldás: bulk insert pruning nélkül (Fázis 1 blokkolt)
async def sync_history_to_cloud():
local_records = get_unsynced_records()
# TODO: bulk insert helyett jelenleg egyenkénti insert
for record in local_records:
await supabase.insert(record) # ← pruning trigger bug
Ismert architektúra-hiba: A Supabase sync db_insert()-tel illeszti be a remote rekordokat — ez egyenként triggereli a helyi pruning logikát. Megoldás: bulk insert pruning nélkül (sync.py refactor, Fázis 1 blokkolt).
Free tier ping: A Supabase free tier 1 hét inaktivitás után szünetel. Cron ping (pl. Uptime Robot) szükséges amíg Pro-szintű bevétel nincs.
Szinkronizáció stratégia
Konfliktus kezelés: "Last write wins" — szerver elsőbbsége
Offline mód: teljes funkcionalitás SQLite-ból
Szinkron trigger: app elindításkor + minden 15 percben
4.1. Supabase Realtime Platform Limitek
Runaway reconnection loop (pl. Android Doze Mode felébredés exponential
backoff nélkül) a teljes real-time projektet felfüggesztheti — ez az
ÖSSZES felhasználó szinkronizációját leállítja (RealtimeDisabledForTenant)!
| Tier | Concurrent Connections | Messages/sec | Channel Joins/sec |
|---|---|---|---|
| Free | 200 | 100 | 100 |
| Pro ($25/hó) | 500 | 500 | 500 |
| Enterprise | 10 000+ | 2 500+ | 2 500+ |
Android-specifikus implikációk:
NEM használunk persistent WebSocket-et Android kliensen
FCM push-to-wake → WorkManager → ephemeral fetch → close
Kötelező exponential backoff MINDEN reconnection kísérletben
Default: min 5mp → max 5 perc backoff (jitter-rel)
Monitoring: Supabase dashboard „Realtime Connections" metrika
4.2. Doze Mode hatása a szinkronizációra
Doze Mode aktiválási feltétel:
Eszköz áramforrás nélkül + mozdulatlan + képernyő kikapcsolva
Desktop kliens (Windows/Linux):
Nincs Doze Mode → persistent WebSocket stabil
Sleep/hibernate → reconnect ébredéskor (exponential backoff!)
Android kliens:
Doze Mode aktív → hálózati hozzáférés felfüggesztve
WS heartbeat pinger OS által szüneteltetve → heartbeat kimarad
Szerver timeout → kapcsolat csendben bontva (nincs explicit error!)
Agresszív retry loop (backoff nélkül) → Supabase Realtime limit
EZÉRT: NEM használunk persistent WS-t Androidon
FCM high-priority data messages ÁT tudnak jutni Doze-on
→ push-to-wake → WorkManager → ephemeral fetch → close
5. Fizetési infrastruktúra
Payment stack (döntött)
Stripe (payment gateway) + Taxually (EU ÁFA compliance)
Stripe — Fázis 1 (launch blockerek):
• Kártya (Visa/Mastercard) — Fázis 1
• Natív BLIK (Lengyelország) — Fázis 1
└─ ⚠️ KÖTELEZŐ VALIDÁCIÓ: BLIK Model A (recurring billing)
A Model A lehetővé teszi az automatikus havi ismétlődő
terhelést az első engedélyezés után — manual re-auth nélkül.
Ha a Stripe BLIK NEM támogatja a Model A recurring-et,
alternatív MoR szükséges (PayU vagy Przelewy24).
Manual re-auth minden hónapban = elfogadhatatlan UX = magas
involuntary churn a lengyel piacon.
• GoPay (Csehország) — Fázis 1 (CZ launch blocker)
└─ Indoklás: 14,6M debit vs. 1,2M credit kártya CZ-ben.
GoPay nélkül a checkout „idegen és megbízhatatlan" — közvetlen
versenyhátrányt okoz a natív cseh Beey-vel szemben.
Stripe — Fázis 2:
• Barion / SimplePay (Magyarország)
• TatraPay (Szlovákia)
• qvik (Magyarország — figyelendő)
└─ MNB által 2024 őszén indított azonnali QR/deep-link fizetés.
1M+ tranzakció az első hónapokban; ingyenes felhasználóknak.
Integráció akkor, ha a Stripe vagy a választott MoR támogatja.
Taxually:
• €340/hó fix — automatikus EU ÁFA bevallás minden CEE piacra
• Már szerződött
Stripe integráció architektúra
Kliens → Stripe Checkout → Stripe Webhook (vtj_proxy/routes/billing.py)
│
┌───────────────┴──────────────┐
▼ ▼
subscription_created subscription_cancelled
→ Supabase: role = "pro" → Supabase: role = "free"
→ Email: welcome drip → Stripe: cancel_at_period_end
Pricing tier → Stripe product mapping
| Tier | Stripe product | Billing | Megjegyzés |
|---|---|---|---|
| Pro havi | prod_pro_monthly |
Recurring/month | cancel_at_period_end |
| Pro éves | prod_pro_yearly |
Recurring/year | cancel_at_period_end |
| BYOK havi | prod_byok_monthly |
Recurring/month | — |
| BYOK LTD | prod_byok_ltd |
One-time | nincs recurr. |
ÁFA kezelés
Taxually: automatikusan minden EU tagállamban
HU: 27% | PL: 23% | CZ: 21% | SK: 23% | AT/DE: 19-20%
B2B invoicing: reverse charge (nem kell ÁFA)
6. Platform-specifikus architektúrák
Windows
Technológia: Python + PySide6
Entry point: main.py
System tray: SystemTray + QMenu
Hotkey: pynput.keyboard listener (global hotkey)
Audio: pyaudio / sounddevice (WASAPI)
Installer: PyInstaller → EXE + WiX (MSI tervezett)
Floating bubble:
QWidget (frameless, always-on-top, semi-transparent)
Animation: QPropertyAnimation
Known issue: animation timer init (v1.5.3 fixed)
Linux
Technológia: Python + PySide6
Display: X11 + Wayland (XWayland fallback v1.5.x)
Audio: PipeWire (elsődleges, Fedora 34+ / Ubuntu 22.10+) / PulseAudio (legacy)
System tray: AppIndicator / StatusNotifierItem
Packages: AppImage (kész) | Flatpak (Fázis 1) | .deb/.rpm/AUR
Autostart (Fázis 1):
1. XDG Autostart: ~/.config/autostart/voicetypingbyjoe.desktop
2. SystemD user service: ~/.config/systemd/user/VibeVox.service (opcionális)
3. Flatpak: a .desktop fájl automatikusan kerül a megfelelő helyre
Wayland native (Fázis 2 — előrehozva Fázis 3-ból):
XDG Desktop Portal (mikrofon hozzáférés)
wtype (Sway/Hyprland input injection) -> ydotool (GNOME/KDE Wayland fallback)
layer-shell protocol (system tray)
Indoklás: Fedora 40+ és Ubuntu 24.04+ alapértelmezetten Wayland —
2026 végére a CEE Linux userek >50%-a Wayland-en lesz.
6.1. Linux Audio Stack Detection (K2 — Fázis 1, P0)
2026-ra a CEE Linux userek >70%-a PipeWire-en fut (Fedora 34+, Ubuntu 22.10+). A VibeVox-nek auto-detektálnia kell az audio backendet — különben a Fedora/Ubuntu userek "nem működik a mikrofon" hibát kapnak az első indításnál → azonnali uninstall.
Detektálási lánc:
# workers.py / audio_setup.py — Linux audio backend detection
import subprocess
def detect_audio_backend():
"""4 szintű audio backend detektálás."""
try:
result = subprocess.run(
['pactl', 'info'],
capture_output=True, text=True, timeout=2
)
if 'PipeWire' in result.stdout:
return 'pipewire' # Szint 1: PipeWire natív
else:
return 'pulseaudio' # Szint 2: pipewire-pulse / PulseAudio
except FileNotFoundError:
# pactl nicht vorhanden
try:
subprocess.run(['aplay', '-l'], capture_output=True, timeout=2)
return 'alsa' # Szint 3: ALSA fallback
except Exception:
return 'unknown' # Szint 4: ismeretlen -> hibaüzenet
PipeWire-specifikus hibaüzenetek (onboarding UI):
| Hibaüzenet | Felhasználói megjelenítés | Megoldás gomb |
|---|---|---|
ALSA: Unable to open slave |
"PipeWire audio service nincs elindítva" | systemctl --user restart pipewire pipewire-pulse |
Device or resource busy |
"Más alkalmazás foglalja a mikrofont" | Eszközválasztó dropdown |
pipewire-alsa hiány |
"PipeWire-ALSA bridge hiányzik" | Telepítési útmutató link |
Sandboxed Flatpak audio (PipeWire-kompatibilis manifest):
# com.voicetypingbyjoe.VoiceTypingByJoe.yaml
finish-args:
- --socket=pulseaudio # pipewire-pulse compatibility layer
# Alternatíva Fázis 2-ben (natív PipeWire Flatpak portal):
# - --socket=pipewire
- --socket=x11
- --socket=wayland
- --share=network
- --talk-name=org.freedesktop.secrets
6.2. Tiling WM Kompatibilitás (F1 — Fázis 2)
A CEE dev közösség ~15-25%-a tiling WM-et használ (i3, Sway, Hyprland, River). Ezek a véleményformáló "megmondóemberek" — ha ők ajánlják, a GNOME/KDE userek is kipróbálják.
Tesztelési mátrix:
| WM | Display szerver | System tray | Hotkey | Státusz |
|---|---|---|---|---|
| i3 | X11 | AppIndicator (i3bar plugin) | pynput global hotkey | 🟡 Tesztelendő |
| Sway | Wayland (natív) | StatusNotifierItem | pynput + XWayland | 🟡 Tesztelendő Fázis 1 |
| Hyprland | Wayland (natív) | waybar widget | pynput + XWayland | 🟡 Tesztelendő Fázis 1 |
| River | Wayland (natív) | yambar / sfwbar | pynput + XWayland | 🔴 Tesztelendő Fázis 2 |
System tray fallback tiling WM-eken:
- Ha nincs rendszertálca → floating window mód (minimális, always-on-top gyorsbillentyű ablak)
- Fázis 2: Waybar widget (
waybar-VibeVox) — StatusNotifierItem interfészen cross-WM megoldás
BYOK keyring fallback tiling WM-eken (lásd 7.2. szekció):
- DE (GNOME/KDE) → libsecret
- Tiling WM (i3/Sway/Hyprland) →
pass(ajánlott) → encrypted config (fallback)
6.3. Wayland Natív Input Injection Specifikáció (F7 — Fázis 2)
PROBLÉMA: X11-en az xdotool type/SendKeys megbízhatóan működik.
Wayland-en a biztonsági modell blokkolja a globális input injection-t.
VibeVox MEGOLDÁS (Fázis 2):
Elsődleges: wtype (Sway, Hyprland, wlroots-based WM-ek)
wtype -s 50 "szöveg" <- 50ms delay karakter közt (megbízható)
Installáció: nixpkgs, AUR, linuxbrew
Teszt: wtype "Hello" -> aktív Wayland ablakba írja
Fallback: ydotool (GNOME/KDE Wayland)
ydotool type --delay 50 "szöveg"
Szükséges: ydotoold daemon futása (systemd user service)
Kompatibilis: GNOME Wayland, KDE Plasma Wayland
Végső fallback: clipboard mód (jelenlegi MVP megoldás)
pyperclip.copy(text) + xdotool key ctrl+v
Hátránya: clipboard "pollution" (más clipboard tartalom felülírás)
Megoldás: clipboard tartalom visszaállítása paste után
Implementáció (workers.py + platform_utils.py):
1. $XDG_SESSION_TYPE == wayland detektálás
2. which wtype -> wtype elsődleges
3. which ydotool -> ydotool fallback
4. egyéb -> clipboard mód Toast-tal
6.4. Windows Disztribúció — Velopack Auto-Update Architektúra
Forrás:
velopack_deployment_analysis.md(2026-04-17) | Státusz: ✅ Velopack kész (2026-04-11), kiegészítő intézkedések integrálva
Velopack framework:
Runtime: Rust-alapú bootloader — delta patch (Zstandard algo > bsdiff)
Telepítés: %LocalAppData%\{packId}\ — adminisztrátori jog nélkül
Update: per-user silent background → UAC prompt nulla
Delta merit: kis változásnál 30 KB – 5 MB patch (teljes ~80 MB helyett)
CI/CD pipeline:
GitHub Actions → Velopack build → delta .nupkg generálás
GitHub Releases CDN → bináris hosting (nem számít REST API limitbe)
GitHub Pages → releases.stable.json manifest (SimpleWebSource)
🔴 KRITIKUS — Launch Blocker Követelmények
P0-V1: multiprocessing.freeze_support() kötelező hívás
# app/main.py — LEGELSŐ SOROK (Velopack init után, minden más import előtt!)
import velopack
velopack.App().run()
import multiprocessing
multiprocessing.freeze_support()
# EZUTÁN jön a PySide6 és minden egyéb import
Ha ez hiányzik: PyInstaller
--onefilemódban végtelen process-spawning loop → worker proceszek nyitott file handle-t tartanak acurrentkönyvtáron → Velopack directory swap MEGSZAKAD → silent update failure → churn!
P0-V2: PyInstaller --onedir mód kötelező
--onefilemódban a Velopack delta update hatástalan (teljes 80 MB bináris csere)--onedirmód → fájlszintű delta diff → 30 KB – 5 MB update CEE mobil hálózaton
P0-V3: Perzisztens adatok szegregációja
✅ HELYES ÚTVONALAK:
%AppData%\VibeVox\ → SQLite DB, settings.json, API kulcsok
%LocalAppData%\VibeVox\data\ → cache fájlok
❌ TILOS:
%LocalAppData%\{packId}\current\ → Velopack frissítéskor TELJES TÖRLÉS!
Ha SQLite fájl a
currentkönyvtárban van → minden frissítés után adatvesztés
🟠 P1 — Code Signing és Manifest Hosting
Azure Artifact Signing (~$9,99/hó = ~$120/év)
Miért NEM EV tanúsítvány ($300–559/év)?
2023 óta EV sem ad azonnali SmartScreen bypass-t
Azure Trusted Signing → ugyanolyan reputáció-képzési folyamat, 3–4× olcsóbban
CI/CD integráció: GitHub Actions natív, HSM USB token NEM szükséges
Kockázat: Azure CA rotáció (2026-március: reputáció nullázódott — MEGTÖRTÉNT!)
→ Monitoring: CA rotáció eseményre azonnali user kommunikáció szükséges
GitHub Pages Update Manifest Hosting (GitHub API rate limit bypass)
Probléma: GitHubSource (autentikáció nélkül) = 60 kérés/óra limit
B2B NAT mögötti szervezetnél több user = egy IP = megosztott limit
Kimeríthető limit → CheckForUpdatesAsync() 403 → silent update failure
Megoldás — Hybrid Bypass Architecture:
releases.stable.json → GitHub Pages (CDN, korlátlan)
.nupkg asset URL-ek → GitHub Releases CDN (nem REST API)
UpdateManager konfig → SimpleWebSource (NEM GitHubSource)
🟠 P1 — Update UX (IsDictationActive védelem)
# Global state — workers.py / controller.py
is_dictation_active: bool = False
# Update thread — NEM szakítja meg az aktív session-t
def apply_update_if_ready():
if is_dictation_active:
return # Diktálás aktív → halasztás
# Passive notification: tálca badge + "Frissítés elérhető" menüpont
# Legjobb UX: "Update on Exit" — bootloader next startup alkalmaz
# → NEM kell explicit restart logika — zero kód, maximum UX
Miért kritikus: Aktív diktálás közbeni
ApplyUpdatesAndRestart()hívás = audio stream azonnali megszakítás = #1 churn trigger audio dictation appokban
🟡 P2 — Rollback Watchdog (Fázis 2, B2B Sales Enabler)
# startup_metrics.json — crash counter watchdog
{
"consecutive_crashes": 0,
"last_successful_version": "1.2.3",
"stability_threshold_seconds": 30
}
# Induláskor: consecutive_crashes += 1
# 30 másodperccel később (stabilitás): consecutive_crashes = 0
# Ha consecutive_crashes >= 2:
# → Velopack n-1 csomag visszatöltés
# → User notification: "Az előző biztonságos verzióra visszaállítottunk"
B2B értékajánlat: Jogi irodai deployment-nél egy törött frissítés saját IT kapacitás nélkül kezelhető automatikusan. „Silent rollback — zero IT jegy szükséges."
Android (Fázis 4)
Architektúra: InputMethodService (Custom IME)
MIÉRT CUSTOM IME:
Android 16: AAPM (Advanced Protection Mode) bevezetése
→ AccessibilityService blokkolás ha nem valódi disability tool
→ isAccessibilityTool="true" hamis használata → Play Store ban
Android 17: side-loaded appoknak sincs accessibility toggle
→ "Restricted by Advanced Protection" warning
Custom IME előnyei:
→ InputConnection.commitText() → natív text injection jog
→ Nem kell accessibility jogosultság
→ Play Store policy-compliant
→ Privacy USP: "Nem accessibility exploitation — natív billentyűzet"
Paste megoldás: InputConnection.commitText()
Audio: MediaRecorder → WAV → Groq API (cloud-only)
Offline Whisper: NEM implementáljuk (large-v3 = 8GB RAM)
Szinkronizáció: FCM push-to-wake + WorkManager
MIÉRT NEM persistent WebSocket: FGS 6h quota Android 12+
FGS Enforcement (Android 15+):
dataSync + mediaProcessing típusok: max 6 óra / 24h window
Megosztott kvóta: összes dataSync FGS kumulatívan számít
Timeout: Service.onTimeout() → stopSelf() → kötelező pár mp-en belül
Crash: ha nem hív stopSelf() → RemoteServiceException (fatal!)
Re-init ban: ForegroundServiceStartNotAllowedException (kimerült kvóta)
Reset: CSAK ha user explicit előtérbe hozza az Activity-t
BOOT_COMPLETED: NEM indíthat microphone/dataSync FGS-t!
Microphone WIU (While-In-Use) korlátok:
Android 16/17: background audio hardening
WIU státusz CSAK ha app vizuálisan aktív volt az indításkor
Ha háttérből indul: AUDIOFOCUS_REQUEST_FAILED / process freeze
→ Custom IME természetesen megoldja (IME vizuálisan aktív)
Wireless mic mód:
Android app = hangfelvevő mikrofon
PC app = paste cél
Protokoll: FCM + WebSocket (session alatt)
MIÉRT WIRELESS MIC MÓD (nem clipboard sync):
Android 10+ elvette a háttér clipboard olvasási jogot
Android 12+ kötelező toast minden clipboard hozzáférésnél
KDE Connect: csak LAN (cellular → nem működik, out-of-office halott)
Phone Link: csak Windows (Linux usereknek használhatatlan)
→ A VibeVox saját cross-device protokollt épít:
Android rögzít → Groq EU → szöveg → Supabase → desktop WS
Desktop-ról: Supabase → FCM push → WorkManager → Android local DB
Előny: ISP-agnosztikus, LAN nem szükséges, WAN-on is működik
6.5. Integrációs célpontok — CEE B2B szoftverek
B2B Sales Prerequisite: Ez a szekció dokumentálja, hogy a VibeVox OS-level keyboard injection konkrétan melyik CEE jogi és orvosi szoftverrel kompatibilis. Nélküle nem hihető a B2B pitch. Tesztelés státusza szoftvercímenként jelzett.
Jogi szektor
| Szoftver | Piac | Architektúra | VibeVox injection módszer | Tesztelési státusz |
|---|---|---|---|---|
| Kleos (Wolters Kluwer) | PL, CZ, SK, HU | Web SaaS (Azure) | Browser text field — standard keyboard sim | 🟡 Elméletileg rendben |
| Praetor (Wolters Kluwer) | CZ, SK, HU | Natív .NET thick client | Windows SendKeys / xdotool — DevExpress form | 🔴 Tesztelés szükséges |
| Evolio | CZ, SK | Web + MS Word | Browser + Word interop | 🟡 Elméletileg rendben |
| SingleCase | CZ, SK | Web SaaS | Browser text field | 🟡 Elméletileg rendben |
| Jogtár (Wolters Kluwer) | HU | Web + Word plug-in | Browser + Word interop | 🟡 Elméletileg rendben |
| Amberlo | PL, CZ, SK, HU | Web SaaS + Mobile | Browser text field | 🟡 Elméletileg rendben |
| LEX / Legalis | PL | Web database | Browser search/analysis field | 🟡 Elméletileg rendben |
Orvosi szektor
| Szoftver | Piac | Architektúra | VibeVox injection módszer | Tesztelési státusz |
|---|---|---|---|---|
| mMedica (Asseco) | PL | Hibrid (Desktop + Cloud) | Windows native text field — ICD-10 form | 🔴 Tesztelés szükséges |
| ZnanyLekarz (Docplanner) | PL | Web SaaS | Browser EDM modul | 🟡 Elméletileg rendben |
| Medicus (CGM) | CZ, SK | Hibrid (Desktop + Cloud) | Windows native / browser field | 🔴 Tesztelés szükséges |
| PC DENT | CZ | Natív Windows (64-bit) | Windows form — clipboard blokkolás RISK | 🔴 KOCKÁZATOS — tesztelés szükséges |
| netDoktor | HU | Web SaaS | Browser — EESZT reporting modul | 🟡 Elméletileg rendben |
| Cloudent | HU | Web SaaS | Browser patient card + NAV invoicing | 🟡 Elméletileg rendben |
PC DENT és Praetor: Egyes natív Windows alkalmazások aktívan blokkolhatják a clipboard-ot és a harmadik fél virtual keyboard eszközöket. A VibeVox OS-level keyboard simulation ezt megkerüli (nem clipboard-ot használ), de tényleges környezetben tesztelés szükséges Fázis 1 előtt B2B sales claim-hez.
VDI/Citrix injection mechanizmus
PROBLÉMA: Más cloud diktáló eszközök audio routinggal próbálják megoldani:
Lokális mikrofon → VDI session → cloud STT → VDI szövegrouting
Ez 3 lépés, magas latencia, karakter-kiesés, audio codec probléma.
VibeVox MEGOLDÁS (OS-level):
1. Lokális OS elfogja a hangot (helyi mikrofon)
2. Hang → EU Frankfurt szerver (Groq Whisper)
3. Szöveg → xdotool/SendKeys → VDI ablakba ínjektál
A VDI session számára ez egyszerű billentyűzet Input — nem tud
különbséget tenni a VibeVox és a kézi gépelés között.
KOMPATIBILIS VDI MEGOLDÁSOK (tesztelés szükséges):
• Citrix Virtual Apps and Desktops
• VMware Horizon
• Microsoft AVD (Azure Virtual Desktop)
• RDP (Remote Desktop Protocol)
Tesztelési prioritások (Fázis 1 előtt kötelező)
| Prioritás | Szoftver | Piac | Befektetett idő |
|---|---|---|---|
| 🔴 P0 | Praetor | CZ, SK, HU | 2-3 óra trial verzióval |
| 🔴 P0 | mMedica | PL | 2-3 óra (van ingyenes demo) |
| 🟡 P1 | Medicus | CZ, SK | 2 óra |
| 🟡 P1 | PC DENT | CZ | 2 óra — clipboard blokk kockázat |
| 🟢 P2 | Kleos, netDoktor, Cloudent | HU/PL | Web-alapú, alacsony kockázat |
7. Biztonsági architektúra
Adatbiztonság rétegek
| Réteg | Megoldás |
|---|---|
| Átvitel | HTTPS / TLS 1.3 (minden API hívás) |
| Auth | Supabase Auth JWT (RS256) |
| Row-level security | Supabase RLS (minden tábla) |
| API kulcs tárolás | OS keychain / encrypted local store |
| Crashlog | Sentry (send_default_pii=False, opt-in) |
BYOK API kulcs kezelés — 4 szintű Keyring Fallback (K4)
# API kulcs tárolás — 4 szintű platform-specifikus fallback lánc:
#
# Windows: Windows Credential Manager (mindig elérhető)
#
# Linux:
# Szint 1: libsecret (GNOME Keyring / KWallet)
# - Detektálás: python-secretstorage csomag + dbus service
# - GNOME, KDE, Cinnamon, XFCE (ha gnome-keyring fut)
#
# Szint 2: pass (GNU Password Manager, GPG-titkosítva)
# - Detektálás: shutil.which('pass')
# - Ha elérhető: ajánlott opció tiling WM-en (i3/Sway/Hyprland)
# - Miért: a CEE dev közösség ~20-25%-a tiling WM-et használ
# Ők a véleményformálók — pass támogatás = trust signal
# - Implementáció: pass insert VibeVox/api-key "sk-..."
#
# Szint 3: Encrypted config fájl
# - Path: ~/.config/VibeVox/keys.enc (AES-256, user-jelszóval)
# - Opt-in figyelmeztetés: "Keyring daemon nem elérhető"
# - Setup wizardban: jelszó megadás + megerősítés
#
# Szint 4: Plaintext -> SOHA nem default
# - Csak explicit "I understand the risk" checkbox + WARNING után
# - Alkalmazásnaplóban megjelenik: SECURITY_DEGRADED event
#
# SOHA: plaintext config fájlban felhasználói beleegyezés nélkül
#
# Validáció (minden szinten egyforma):
# Minden BYOK session elején: test connection
# Hiba esetén: user értesítés + graceful fallback
Tiling WM onboarding üzenet (pass elérhetősége esetén):
"Tiling window manager felismerve (KeyringUnlockError)"
Javasolt kulcs tárolási mód: pass (GPG-titkosított)
[Beállítás most >] [Titkosított fájl >] [Részletek]
Auth flow (Managed Cloud)
1. User regisztrál/bejelentkezik → Supabase Auth
2. Supabase visszaad JWT token-t
3. Kliens minden API híváshoz Bearer token-t küld
4. Proxy validálja a token-t → quota check → STT routing
5. Stripe subscription state tükröződik a Supabase role-ban
8. Ismert technikai adósságok
| Problem | Súlyosság | Státusz | Megoldás |
|---|---|---|---|
| Supabase sync bulk insert | 🔴 Magas | Fázis 1 blokkolt | sync.py refactor |
| Wayland natív (X11 fallback) | 🟡→🔴 Emelkedő | Fázis 2 (előrehozva) | XDG Portal + wtype migráció |
| Windows floating bubble init | 🟡 Közepes | v1.5.3 fixed | Lezárva |
| Supabase free tier ping | 🟢 Alacsony | Workaround: Uptime Robot | Pro tier bevételig |
| VPS US régió (GDPR marketing) | 🟢 Alacsony | Nem blokker | EU régió mérlegelés Fázis 2 |
| Supabase dashboard konfiguráció | 🔴 Magas | ❌ Szinkronizáció NEM live | Dashboard-on engedélyezni: RLS policy, realtime channel, user table — Fázis 1 launch prerequisite |
9. Email Infrastruktúra [Email Infrastructure Analysis - #1, #2, #4 beépítve]
Platform döntés: Loops.so - natív Stripe webhook sync (Zapier nélkül), vizuális branching drip builder, $ /hó <1K kontaktig.
9.1. Backend API integráció spec
A backend-nek (proxy_server/ vagy dedikált email_service.py) a következő két Loops.so hívást kell implementálnia:
Contact létrehozás (regisztráció / Stripe webhook)
`python
POST https://app.loops.so/api/v1/contacts/create
Trigger: új regisztrációnál VAGY Stripe checkout.session.completed webhook
payload = { "email": user_email, "userId": supabase_user_id, "userGroup": "free", # "free" | "pro_monthly" | "pro_annual" | "b2b" "source": "stripe_checkout", # "registration" | "stripe_checkout" | "waitlist" "mailingLists": { "cm_onboarding": True, # Onboarding drip (30 napos szekvencia) } } `
Lifecycle esemény küldés
`python
POST https://app.loops.so/api/v1/events/send
--- Silent Churn detektálás (14 nap inaktivitás) ---
payload_churn = { "email": user_email, "eventName": "silent_churn_detected", "eventProperties": { "days_inactive": 14, "last_session_words": last_word_count, "plan": current_plan, } }
--- Havi digest (minden hónap 1-én, cron job) ---
payload_digest = { "email": user_email, "eventName": "monthly_digest", "eventProperties": { "total_words_month": monthly_word_count, "total_minutes_saved": monthly_minutes_saved, "streak_days": streak, } } `
9.2. Lifecycle esemény taxonómia
| Esemény neve | Trigger | Kiváltó logika helye | Loops flow |
|---|---|---|---|
| contact_created | Regisztráció / Stripe checkout | auth_handler.py / Stripe webhook | Onboarding drip indítás |
| first_dictation | Első sikeres STT session | workers.py -> session_complete | Day 3 email |
| onboarding_completed | Onboarding wizard 3. lépés befejezve | onboarding.py → wizard_step_3_complete | TTFD mérés: timestamp Supabase-be → Time-to-First-Dictation KPI |
| silent_churn_detected | 14 nap 0 session | Napi cron job (VPS) | Re-engagement szekvencia |
| monthly_digest | Hónap 1. napja | Havi cron job (VPS) | Havi összefoglaló |
| upgrade_to_pro | Stripe webhook | stripe_webhook_handler.py | Pro welcome |
| subscription_cancelled | Stripe webhook | stripe_webhook_handler.py | Win-back D1/D14/D45 |
| nps_survey_trigger | 30/60/90 nap anniversary | Napi cron job | NPS email |
9.3. Implementációs prioritás
| Fázis | Feladat | Prioritás |
|---|---|---|
| Fázis 0 (Launch ELOTT) | DNS beállítás (SPF, DKIM, DMARC) | P0 BLOCKER |
| Fázis 0 (Launch ELOTT) | Domain warmup terv aktiválása | P0 BLOCKER |
| Fázis 0 (Launch ELOTT) | contact_created + upgrade_to_pro API hívások backend-ben | P0 BLOCKER |
| Fázis 1 | silent_churn_detected cron job | P1 |
| Fázis 1 | monthly_digest cron job | P1 |
| Fázis 2 | nps_survey_trigger cron job | P2 |
A Loops.so API kulcs a .env fájlban LOOPS_API_KEY változóként tárolódik. Soha nem kerülhet a kliensoldali kódba (desktop app). Kizárólag a backend proxy hívja.
9.4. SHA-256 Release Hash Generálás — CI/CD spec (GAP-4)
A SHA-256 hash a letöltési oldalon erős trust signalt küld a privacy-tudatos, technikai CEE szegmensnek. CI/CD pipeline-ba integrálva automatizálható — minimális implementációs coston maximal trust gain.
# Minden release előtt futtatandó a build pipeline-ban (PyInstaller után):
sha256sum vibevox-*.exe vibevox-*.AppImage > SHA256SUMS.txt
# GitHub Actions workflow (javasolt):
# jobs.release.steps:
# - name: Generate SHA256
# run: sha256sum vibevox-${{ env.VERSION }}-win64.exe vibevox-${{ env.VERSION }}.AppImage > SHA256SUMS.txt
# - name: Upload to GitHub Release
# uses: actions/upload-release-asset@v1
# with: asset_path: ./SHA256SUMS.txt
Megjelenítés a download interstitial-on (/download/[os]/success):
vibevox-1.5.x-win64.exe SHA-256: [auto-generated hash]
vibevox-1.5.x.AppImage SHA-256: [auto-generated hash]
Implementációs cost: ~2 óra (CI script + UI elem) | Roadmap: P2 — D+7-ig
Kapcsolódó: 09_Product.md §SHA-256 Hash Követelmény · 15_Launch_Playbook.md §2.3a
§E2E Encryption Architecture — Zero-Knowledge Cloud Sync
Implementálva: 2026-04-18 (
app/encryption.pyv2 — Key Wrapping architektúra) Kompetitív moat: Wispr Flow és Typeless NEM kínál semmilyen E2E sync titkosítást. Garancia: Szerver (Supabase) SOHA nem látja a plaintext adatot. Jelszó visszaállítás: LEHETETLEN.
Architekturális döntés #1 — Sync = E2E (azonos toggle)
Döntés (2026-04-18): A cloud sync és az E2E titkosítás ugyanaz a feature — nem két külön beállítás. Nincs "titkosítatlan cloud sync" mód.
Miért?
Az eredeti "Deferred Opt-In" modell (alapból titkosítatlan szinkron, E2E opt-in) elfogadhatatlan:
- Amíg a user nem kapcsolja be az E2E-t, a marketing claim „soha nem látjuk az adataidat" nem igaz
- Átmeneti "unencrypted sync" állapot = jogszabályi és reputációs kockázat
- A user nem érti, miért kap "titkosítás kikapcsolva" warningot egy szinkronált szoftverben
A helyes modell:
Alapállapot (cloud sync kikapcsolva):
├── Adatok: CSAK lokálisan (SQLite)
├── Supabase: üres — semmi sem megy fel SOHA
└── Marketing claim: ✅ mindig igaz ("soha nem látjuk az adataidat"
— mert nincs mit látni a szerveren)
Cloud sync bekapcsolva (= E2E bekapcsolva):
├── Első bekapcsoláskor: jelszóbekérés + DEK generálás + Supabase push
├── Ezután: minden adat titkosítva megy fel — szerver csak ciphertext-et lát
└── Marketing claim: ✅ mindig igaz — szerver soha nem látja a plaintextet
Friction elemzés:
| Felhasználói csoport | Friction? | Megjegyzés |
|---|---|---|
| Cloud syncet nem akar | 0 | Sosem találkozik jelszómegadással |
| Cloud syncet bekapcsol | Alacsony — egyetlen jelszóbeállítás | Tudatos döntés, elfogadják a tradeoff-ot |
| Második eszközön nyit | Egyetlen jelszóbekérés startup-on | Azonos a jelszókezelők UX-éhez |
Architekturális döntés #2 — Kétszintes kulcs-architektúra (KEK + DEK)
Döntés (2026-04-18): Kétszintes Key Wrapping (1Password / Bitwarden modell). Ez az egyetlen elfogadható megoldás a jelszóváltoztatás skálázhatóságára.
A probléma az egyszintes modellel:
Naiv modell: password → PBKDF2 → key → MINDEN EGYES adatsor titkosítva ezzel
Jelszóváltoztatáskor → minden sort újra kell titkosítani
3 éves felhasználó, 50 000 sor → percekig tart, megszakadhat, adatvesztés kockázata
A kétszintes megoldás:
KEK (Key Encryption Key):
password → PBKDF2-HMAC-SHA256(salt, 600k iter) → KEK [32 byte, RAM-ban]
Felhasználás: CSAK a DEK titkosítására/visszafejtésére
DEK (Data Encryption Key):
os.urandom(32) — generálva EGYSZER, első cloud sync setupkor, SOHA nem változik
Felhasználás: MINDEN history/vocabulary sor titkosítása
Tárolás: AES-256-GCM(DEK, key=KEK) → Supabase user_encryption_metadata.wrapped_dek
Jelszóváltoztatás (O(1) — eszközszámtól és adatmennyiségtől FÜGGETLEN):
1. old_KEK → unwrap(wrapped_dek) → DEK
2. new_KEK = PBKDF2(new_password, SAME salt)
3. new_wrapped_dek = AES-GCM(DEK, new_KEK)
4. Supabase: user_encryption_metadata ← 1 sor írás (wrapped_dek frissítve)
History / vocabulary sorok: ÉRINTETLEN ✅
Skálázhatóság:
| Jelszóváltoztatás | Naiv modell | KEK+DEK modell |
|---|---|---|
| 5 history sor | ~1 mp | ~100ms |
| 500 history sor | ~30 mp | ~100ms |
| 50 000 history sor | ~50 perc ❌ | ~100ms ✅ |
| Hálózatkimaradás közben | Adatvesztés kockázata ❌ | Atomi művelet ✅ |
Kriptográfiai algoritmusok
| Komponens | Algoritmus | Paraméter | Indok |
|---|---|---|---|
| KEK levezetés | PBKDF2-HMAC-SHA256 | 600 000 iteráció (NIST SP 800-132, 2023) | Brute-force ellenállás ~600× nyers SHA-256-nál |
| DEK generálás | os.urandom(32) |
256 bit | Kriptográfiai minőségű véletlenszám az OS-től |
| DEK wrapping | AES-256-GCM | 256-bit KEK, 12-byte IV | Authenticated encryption — szerver nem oldhatja ki |
| Adat titkosítás | AES-256-GCM | 256-bit DEK, 12-byte IV | Minden sorhoz friss IV — nonce reuse ellen |
| Salt | os.urandom(16) |
128 bit | Egyedi userenként; Supabase-ben tárolva — nem titkos |
| Auth Tag | GCM tag (auto) | 16 byte | Bit flip → decryption fail (tamper detection) |
AES-GCM vs AES-CBC: A GCM egyszerre ad titkosítást (confidentiality) ÉS integritásvédelmet (integrity). A CBC csak titkosít — silently corrupted ciphertext-et nem észlelne. A Supabase-ben tárolt adatoknál az integritásvédelem kritikus.
Teljes adatfolyam
ELSŐ BEKAPCSOLÁS (cloud sync setup):
user jelszót ad meg
│
▼ generate_salt() + generate_dek() [os.urandom — egyszer fut le]
salt (16 byte) + DEK (32 byte)
│
▼ derive_kek(password, salt) [PBKDF2, ~0.5 másodperc]
KEK (32 byte, RAM-ban marad)
│
▼ wrap_dek(DEK, KEK) [AES-256-GCM, ~0ms]
wrapped_dek + wrapped_dek_iv
│
▼ push_encryption_meta(salt_b64, wrapped_dek, wrapped_dek_iv)
Supabase: user_encryption_metadata (1 sor)
│
▼ set_session(dek, salt) [DEK → RAM cache]
Cloud sync aktív ✅
MÁSIK ESZKÖZÖN:
user bejelentkezik Google-lel
│
▼ e2e_salt_exists() → True [pull_encryption_meta()]
Dialog: "Add meg a szinkron jelszavad"
│
▼ derive_kek(password, salt) [PBKDF2, ~0.5 másodperc]
KEK → unwrap_dek(wrapped_dek, iv, KEK) → DEK
│
▼ set_session(dek, salt)
Minden eszközön azonos DEK — szinkron aktív ✅
ADAT TITKOSÍTÁS (minden dictation push):
DEK (RAM-ból) + record JSON
│
▼ AES-256-GCM encrypt [fresh 12-byte IV minden encrypt híváshoz]
encrypted_payload: {"encrypted_data": "<b64>", "iv": "<b64>", "e2e_version": 2}
│
▼ Supabase history sor [raw_text="" + final_text="" — server nem látja a tartalmat]
JELSZÓVÁLTOZTATÁS (O(1) — adatsorok érintetlenek):
old_password → KEK_old → unwrap(wrapped_dek) → DEK [validálja a régi jelszót]
new_password → KEK_new → wrap(DEK, KEK_new) → new_wrapped_dek
Supabase: SET wrapped_dek = new_wrapped_dek [EGY sor update]
History/vocabulary sorok: ÉRINTETLEN ✅
UX flow
Első bekapcsolás (Cloud Sync toggle → ON):
Settings → Cloud Sync → [Kapcsolja be]
│
▼
┌─────────────────────────────────────────────────────────┐
│ ☁️ Cloud szinkronizáció bekapcsolása │
│ │
│ Az adataid végponttól végpontig titkosítva lesznek. │
│ Csak te férhetsz hozzájuk — mi sem látjuk őket. │
│ │
│ Állíts be egy szinkronizálási jelszót: │
│ [Jelszó ] │
│ [Jelszó megerősítés] │
│ │
│ ⚠️ Ha elveszted ezt a jelszót, az adatok nem │
│ állíthatók vissza. Jegyezd fel biztonságos helyre. │
│ │
│ [Mégsem] [🔒 Bekapcsolás] │
└─────────────────────────────────────────────────────────┘
→ setup_cloud_sync(password) hívódik
→ Supabase: 1 sor write (encryption metadata)
Második eszközön / app újraindítás (ha cloud sync konfigurálva):
Google Login sikeres
│
▼ cloud_sync_is_configured() → True
│
▼
┌─────────────────────────────────────────────────────────┐
│ 🔒 Cloud szinkronizáció titkosítva │
│ │
│ Ez a fiók titkosított cloud sync-et használ. │
│ Add meg a szinkronizálási jelszavad: │
│ │
│ [Jelszó ] │
│ │
│ [⏭ Kihagyás — csak lokálisan dolgozom] │
│ [Szinkronizálás] │
└─────────────────────────────────────────────────────────┘
→ unlock_cloud_sync(password) hívódik
→ Ha helyes: DEK → RAM, sync indul
→ Ha rossz jelszó: "Hibás jelszó" toast, ismét próbálhatja
→ Ha kihagyja: lokális adat elérhető, szinkron nem fut
Jelszóváltoztatás (Settings → Cloud Sync → Jelszó megváltoztatása):
[Régi jelszó] + [Új jelszó] + [Megerősítés]
│
▼ change_sync_password(old_pw, new_pw)
- Ha régi jelszó helyes: ~100ms → "Jelszó sikeresen megváltoztatva"
- Ha helytelen: "Hibás régi jelszó" toast
- Adatsorok: ÉRINTETLEN
Ha elfelejti a jelszót:
Settings → Cloud Sync → "Elfelejtettem a jelszavam"
▼
┌─────────────────────────────────────────────────────────┐
│ ⚠️ Jelszó visszaállítása │
│ │
│ A titkosított szerver-oldali adatokat töröljük. │
│ (Lokális adataid érintetlen maradnak.) │
│ Új jelszóval folytathatod a szinkront. │
│ │
│ [Mégsem] [Törlés és új jelszó beállítása] │
└─────────────────────────────────────────────────────────┘
→ Supabase: DELETE user_encryption_metadata + history + vocabulary
→ Lokális SQLite: érintetlen
→ setup_cloud_sync(new_password) újrafut
Supabase séma (key-wrapping)
user_encryption_metadata (
user_email text PRIMARY KEY,
salt_b64 text NOT NULL, -- PBKDF2 salt — NEM titkos
wrapped_dek text NOT NULL, -- AES-GCM(DEK, KEK) — opaque a szerver számára
wrapped_dek_iv text NOT NULL, -- 12-byte GCM nonce — NEM titkos
created_at timestamptz,
updated_at timestamptz
)
-- RLS: minden user csak a saját sorát látja/módosítja
Fájlstruktúra
app/
encryption.py ← KEK derivation, DEK generate/wrap/unwrap,
AES-GCM encrypt/decrypt, session DEK cache
sync/
encryption_meta.py ← push_encryption_meta() / pull_encryption_meta()
history.py ← DEK-aware push_history_entry + pull_history
vocabulary.py ← DEK-aware push_vocabulary + pull_vocabulary
__init__.py ← setup_cloud_sync() / unlock_cloud_sync() /
change_sync_password() / cloud_sync_is_configured()
docs/
supabase_schema.sql ← user_encryption_metadata with wrapped_dek columns
Zero-knowledge garancia (marketing claim alap)
„A jelszavad kizárólag a te fejedben él. Szervereink soha nem látják az adataidat — technikailag lehetetlen. Ha elveszted a jelszavad, az adat nem állítható vissza. Ez nem korlátozás — ez a garancia."
Technikai alap:
- Cloud sync kikapcsolt: Supabase üres — semmi nem megy a szerverre
- Cloud sync bekapcsolt: Szerver csak
wrapped_dek(opaque) + ciphertext sorokat tárol - Supabase admin sem látja a tartalmat — csak base64-kódolt opaque byte-okat
- DEK kizárólag kliens-oldalon él (RAM-ban) —
wrapped_deknélkül semmit ér wrapped_dekkizárólag a jelszóval oldható ki — jelszó soha nem hagyja el az eszközt- Jelszóváltoztatás O(1): Csak a
wrapped_dekváltozik — összes adatsor érintetlen
Kapcsolódó dokumentumok:
06_GDPR.md— Adatfolyam és sub-processor kockázatok05_Pricing.md— STT cost és margin kalkulációROADMAP.md— Sprint feladatok