-
Clause-boundary streaming in
llama-service(llama-service.cpp): LLaMA now triggers TTS synthesis at commas, semicolons, and German dash patterns (em-dash, en-dash,-) in addition to sentence-end punctuation. Reduces perceived time-to-first-audio by ~100–200 ms. Early-streaming guard raised toMAX_EARLY_STREAM_CHUNKS = 4(was 2) to accommodate multi-chunk sentences. -
Neural G2P for German (
neural-g2p.h,neural-g2p.mm): NewNeuralG2Pclass loads a DeepPhonemizer German checkpoint exported to CoreML (de_g2p.mlmodelc). Kokoro and Matcha engines use it when--g2p neuralis set; espeak-ng remains the fallback for other languages and when the model is absent. TheG2PBackendenum (AUTO,NEURAL,ESPEAK) is defined in the sharedneural-g2p.hheader consumed by all engine services.- Export script:
scripts/export_g2p_model.py— downloads DeepPhonemizer German checkpoint, converts to CoreML, savesde_g2p.mlmodelc+ vocab files tobin/models/g2p/.
- Export script:
-
Prosody state carryover in Kokoro (
kokoro-service.cpp):KokoroPipeline::synthesize()now acceptsprev_ref_s/ref_s_outparameters. Theref_s_outtensor (256-dim style vector) from chunk N is stored inCallContext::last_ref_sand fed asref_sinput to chunk N+1's duration model. Intonation continuity across synthesized chunks is preserved without any CoreML model re-export. Thread-safe: each call worker owns its ownref_scopy. -
VITS2 engine (
vits2-service.cpp,libpiper/): New TTS engine using Piper TTS via thelibpiperC API (ONNX Runtime 1.22). Docks intotts-serviceon cmd port 13175. Supports German Piper voice models (.onnx+.onnx.json).libpiperis compiled as a static library; ONNX Runtime dylib is bundled at@executable_path.- Model setup script:
scripts/setup_vits2_models.py— downloadsde_DE-thorsten-high.onnxand config tobin/models/vits2-german/.
- Model setup script:
-
Matcha-TTS engine (
matcha-service.cpp): New TTS engine based on Matcha-TTS (flow-matching) + HiFi-GAN, both exported to CoreML. ODE flow is baked into a static CoreML graph (10 Euler steps unrolled at export time). Docks intotts-serviceon cmd port 13176. Three bucketed flow models (3s/5s/10s). Supports neural G2P for German vianeural-g2p.h.- Export script:
scripts/export_matcha_models.py— exports text encoder, baked ODE flow, HiFi-GAN vocoder, and vocabulary tobin/models/matcha-german/coreml/.
- Export script:
-
Port constants (
tts-common.h):kVITS2EngineCmdPort = 13175,kMatchaEngineCmdPort = 13176. -
Dashboard: per-engine TTS config (
frontend.cpp,frontend-ui.h,javascript.h,database.h):- Four new REST endpoints:
GET/POST /api/tts/engine_config,GET /api/tts/available_voices,GET /api/tts/available_g2p. - VITS2 and Matcha config panels in the service detail view (Voice, G2P, Language dropdowns + Save button with async status feedback).
- Language-switch lifecycle: changing language triggers per-engine preset computation, stops incompatible engines, and restarts the active engine — all in a detached thread so the HTTP response is returned immediately.
- Engine
disabled_reasonfield: greyed-out UI when no compatible model directory is installed for the selected language. - Settings persisted in SQLite:
tts_engine_config_{engine}_{voice|g2p|lang}. Defaults: kokoro=df_eva/auto/de, neutts=default/espeak/de, vits2=default/auto/de, matcha=default/auto/de. - Input validation:
langallowlisted against known codes;voice/g2p_backendrestricted to[A-Za-z0-9._-].
- Four new REST endpoints:
libpiper/CMakeLists.txt:add_library(piper SHARED …)→add_library(piper STATIC …)to satisfy the project's static-linking policy.database.hseed: AddedVITS2_ENGINE(bin/vits2-service) andMATCHA_ENGINE(bin/matcha-service) rows alongside existing engine entries.frontend.cppservice vectors:all_svcsandtts_svcsnow includeVITS2_ENGINEandMATCHA_ENGINE. Engine dispatch inrun_test_setup_async()andSET_LOG_LEVELhandler extended from 2-way to 4-way.
- Generic TTS stage (
bin/tts-service): new pipeline node sitting between LLaMA and OAP that owns the interconnect sockets (ServiceType::TTS_SERVICE, base port 13140) and a dedicated engine dock on port 13143. Concrete TTS engines are no longer pipeline nodes — they connect as dock clients. - Engine-dock protocol (loopback-only TCP on 13143): engines open a TCP connection, send one-line JSON HELLO
{"name":..., "sample_rate":24000, "channels":1, "format":"f32le"}, and receiveOK\norERR <reason>\n. After OK, frames are tag-prefixed (0x01=Packet,0x02= mgmt + optional payload).127.0.0.1-only; HELLO name constrained to[A-Za-z0-9_-]{1..32}. - Single-slot, last-connect-wins state machine: at most one engine is active. A new engine completing HELLO triggers a swap — the dock sends
CUSTOM SHUTDOWNto the outgoing engine, aCUSTOM FLUSH_TTSto OAP, and switches the slot. Old-engine TCP close is bounded at 2 s before force-close. GET /api/tts/statusREST endpoint returning{"engine":"kokoro"},{"engine":"neutts"}, or{"engine":null}.- Per-engine cmd ports: Kokoro engine on 13144, NeuTTS engine on 13174 (was 13142 for both before — they shared the pipeline slot).
- Frontend service table:
TTS_SERVICE(dock),KOKORO_ENGINE(binarykokoro-service),NEUTTS_ENGINE(binaryneutts-service). Dashboard pipeline node shows the currently docked engine under the TTS node, queried from/api/tts/status. - SPEECH_IDLE warm-up: LLaMA, Kokoro, NeuTTS, and OAP now each implement a
prewarm_call(call_id)path that the dock invokes by forwarding SPEECH_IDLE to the active engine. Eliminates several lazy-init hot spots on the first TTS frame of a turn. - PacketTrace latency fields:
t_engine_out/t_oap_inmonotonic timestamps for the engine→OAP hop, enabling the median ≤ 2 ms / p99 ≤ 5 ms forwarding-budget verification.
ServiceTyperenamed:KOKORO_SERVICE→TTS_SERVICE(wire value5preserved forPacketTracecompatibility).NEUTTS_SERVICEremoved.service_type_to_stringandPacketTrace::service_type_nameupdated ("KOK"→"TTS";"NEU"dropped).- Upstream / downstream topology:
LLAMA_SERVICE → TTS_SERVICE → OAP_SERVICE. Engines are not part of the chain. - Engine lifecycle: Kokoro / NeuTTS use the new header-only
EngineClienthelper (tts-engine-client.h) instead ofInterconnectNode. OnCUSTOM SHUTDOWNthe engine joins synthesis workers, releases model handles, and callsstd::_Exit(0). - Kokoro / NeuTTS max utterance buffer: bumped from 10 s to 120 s of PCM (covers worst-case multi-chunk LLaMA responses).
/api/switch_ttsREST endpoint and frontendhandle_switch_ttshandler. Operators switch engines by starting the desired engine process — the dock handles the swap transparently.InterconnectNode::set_downstream_override/clear_downstream_override/pause_downstream/resume_downstreamand the correspondingdownstream_override_/downstream_paused_state.- LLaMA
SET_TTS:KOKORO/SET_TTS:NEUTTScmd-port handlers — redundant now that the downstream resolves toTTS_SERVICE. - Kokoro
check_tts_exclusion()startup dance — the single-slot dock is the sole arbiter. - NeuTTS
ServiceType::NEUTTS_SERVICEport block (13170–13172).
- Dock
std::terminateon engine disconnect: the disconnect path reset the slot without joining its recv/ping threads. Replaced with an off-hot-path watcher thread that joins and closes the fd (tracked inswap_watchers_soshutdown()joins them on dock exit). - Engine self-join deadlock on
CUSTOM SHUTDOWN: the SHUTDOWN handler ran on theEngineClientthread and tried to join itself. Replaced withshutdown_all_calls()followed by a clean shutdown sequence; the engine tears down all per-call state before exiting. - macOS Keychain TLS key-fetch hang in headless contexts:
prodigy_tls::get_interconnect_key()moved to a file-based store (bin/ic_key.bin, chmod 600). Unblocks every encrypted interconnect on first call.
- SQLite readonly database error: Resolved
flush_log_queue: insert failed: attempt to write a readonly databasewhen started frombin/directory. Database path is now resolved to an absolute path based on project root. Addedsqlite3_db_readonly()check after open — emits a clear fatal error with the resolved path instead of silently failing every 500ms. - CWD resolution: Improved
main()chdir logic to handle all invocation paths:bin/frontend,./bin/frontend,cd bin && ./frontend, absolute paths, and symlinks. Falls back with clear error ifbin/frontendis not found at the resolved project root. - Test binaries gracefully skip when dependencies are unavailable:
test_integrationusesGTEST_SKIP()when pipeline services are not running;test_kokoro_cpptests 2-4 skip when model files are missing. Previously these timed out or failed with unhelpful errors. - Test runner output parsing: Verified compatibility between gtest output format and
check_test_status()/handle_test_log()parsing logic. - Pipeline test script: Verified
run_pipeline_test.pylog message patterns and API endpoint calls match current implementation.
- SQL query guard hardened:
is_read_only_query()now strips SQL comments (--and/* */) before keyword checking to prevent comment-based bypass. AddedLOAD_EXTENSIONsubstring check. - Extension loading disabled:
sqlite3_db_config(SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 0)called ininit_database()to disable extension loading at runtime. - popen input sanitized:
kill_ghost_processes()validatesbinary_nameagainst[a-zA-Z0-9_.-]regex before passing topopen(). Invalid names are silently rejected. - JSON escape handling: Added
\b(backspace) and\f(form-feed) escape cases toextract_json_string(). - Local-only binding documented: Added inline comment at
mg_http_listencall documenting the127.0.0.1security assumption.
- Dead code: Removed
is_service_running_unlocked()— was never called anywhere in the codebase.
- C++ magic numbers replaced: All numeric literals in the event loop, log infrastructure, and test runners extracted to
static constexprnamed constants with descriptive names and unit suffixes (e.g.,LOG_FLUSH_INTERVAL_MS,UDP_BUFFER_SIZE,SERVICE_CHECK_INTERVAL_S). - JS magic numbers replaced: All 45+
setInterval/setTimeoutnumeric literals extracted to a named-constants block at the top of the JS section (e.g.,POLL_STATUS_MS,DELAY_SERVICE_REFRESH_MS,SIP_MAX_LINES). - Navigation restructured: Sidebar reorganized into logical sections: Dashboard (default) > Pipeline (Services, Live Logs) > Testing (Tests) > Configuration (Models, Database, Credentials). The Tests page contains four tabs: Component Tests, Pipeline Tests, Tools, and Test Results.
- Dashboard is now the default page (was previously Tests).
- Page transitions: Changed from
display:none/blocktoggle to CSSvisibility/opacity/pointer-eventsanimation for smoother transitions..hiddenclass retained for inline element toggling. - Tests page split into tabs: Component Tests, Pipeline Tests, Tools, and Test Results organized as tabs with a summary status bar. Test panels are now collapsible. Formerly "Beta Tests"; Test Runner and standalone Test Results pages removed.
- Dashboard page: Pipeline visualization with horizontal node chain showing live service status. Metric cards (Services Online, Running Tests, Tests Passed, Uptime) with count-up animation. Activity feed showing recent log entries. Quick action buttons (Start All, Stop All, Restart Failed). Overall health badge (Healthy/Degraded/Offline).
- Dashboard API endpoint (
GET /api/dashboard): Returns combined JSON with service statuses, recent logs, test summary, uptime, and pipeline topology. - Test Results page: Aggregated test results with summary metric cards, Chart.js trend chart (with zoom plugin), filter bar (test type, date range), and sortable results table.
- Test Results Summary API endpoint (
GET /api/test_results_summary): Queries multiple DB tables (service_test_runs, whisper_accuracy_tests, model_benchmark_runs, iap_quality_tests) and returns unified results with summary statistics. - CSS design system: Comprehensive custom properties for gradients (
--wt-gradient-*), shadows (--wt-shadow-*), surfaces (--wt-surface-*), and chart colors (--wt-chart-*). New component classes for pipeline nodes, metric cards, collapsible panels, and beta test tabs. - Responsive breakpoints:
@media (max-width:1024px)for tablet layout,@media (max-width:768px)for mobile (icon-only sidebar). - Dark theme overrides:
[data-bs-theme="dark"]rules for pipeline hero, nodes, cards, and surfaces. - Animations:
slideIn,countPulse,flowPulsekeyframe animations for dashboard elements. - Documentation: Added
docs/frontend-guide.md(user-facing) anddocs/frontend-architecture.md(developer/maintenance) covering all new features and architecture.