You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: true streaming, lipsync, character presets, runtime config
- Replace fake streaming with real token-by-token streaming using
===META=== marker to separate reply text from emotion/action JSON
- Add lipsync mouth animation driven by time-based viseme loop in
TTSService; CyberAvatar renders mouth mesh that syncs with TTS
- Ship 4 character presets (lively-assistant, serious-advisor,
cute-companion, pro-service) with backend-side prompt mapping;
frontend sends only characterId to avoid prompt injection
- Add runtime API endpoint override in settings drawer config tab,
persisted in localStorage and reapplied on startup via
ServicesProvider, taking precedence over env config
- Localize new settings UI sections (zh-CN + en)
Tests: +18 frontend, +3 backend (274 frontend / 40 backend total)
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+22Lines changed: 22 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
10
10
## [Unreleased]
11
11
12
+
### 🎭 Streaming & Lipsync
13
+
14
+
-**True streaming dialogue** — Replaced fake streaming in the Python backend with real token-by-token streaming. The LLM now outputs plain reply text first, followed by a `===META===` marker line carrying the emotion/action JSON, so users see tokens appear as the LLM generates them instead of after the full response completes.
15
+
-**Lipsync mouth animation** — Added a `mouthOpen` state channel driven by a time-based viseme loop in `TTSService` (≈16Hz sinusoidal + noise simulation). The procedural `CyberAvatar` now renders a mouth mesh that opens and closes in sync with TTS playback, and `onSpeakEnd` cleanly resets the mouth to closed.
16
+
17
+
### 🧑🎤 Character Presets
18
+
19
+
-**Built-in character presets** — Shipped 4 character personas (`lively-assistant`, `serious-advisor`, `cute-companion`, `pro-service`) with backend-side system prompt mapping. The frontend only sends a `characterId`; the backend controls the prompt to avoid injection. A preset selector is now available in the settings drawer's basic tab.
20
+
-**`characterId` in dialogue metadata** — `buildDialogueRequestMeta` now carries an optional `characterId` field, and `useChatStream` forwards the active preset from `digitalHumanStore` on every streaming turn.
21
+
22
+
### ⚙️ Runtime Configuration
23
+
24
+
-**Runtime API endpoint override** — Added a `config` tab in the settings drawer for overriding the dialogue backend base URL and fallback endpoints at runtime. The override is persisted in `localStorage` and reapplied on app startup via `ServicesProvider`, taking precedence over `VITE_API_BASE_URL` env config. A reset button restores the env defaults.
25
+
26
+
### 🧪 Tests
27
+
28
+
- Added `lipsync.test.ts` (7 tests) covering `mouthOpen` clamping, TTS callback wiring, and the viseme loop start/stop lifecycle.
- Extended `dialogueRequestMeta.test.ts` with `characterId` inclusion/omission cases.
32
+
- Extended backend `test_dialogue_service.py` with a `CharacterPresetTest` class (3 tests) verifying character prompt selection, unknown-id fallback, and default behavior.
33
+
12
34
### ✨ Runtime Capabilities
13
35
14
36
- Added structured dialogue request metadata so language preference, speech configuration, and recent vision context travel together with each chat turn
0 commit comments