- server.py / main.py no longer reference fake_room at all (no import,
no --fake-room flag, no _apply_fake_room)
- Routing decision happens at connect time in DanmakuClient.start():
room_id == 1 dynamically imports fake_room.py and patches blivedm;
any other room id returns immediately without touching fake_room
- Switching back from room 1 to another room unpatches to real Bilibili
- Production (packaged, no fake_room.py) is completely unaffected for
normal room ids; room 1 without fake_room.py raises a clear error
- Rebuild portable zip (83.9 MB)
- When room_id == 1, server/main automatically patch blivedm to connect
to fake_room.py on 127.0.0.1:8081 (bot web UI port + 1)
- Any other room id restores real Bilibili (unpatch)
- fake_room.py (gitignored, not packaged): headless fake live room with
bilibili-compatible init APIs (/x/web-interface/nav, /room/v1/Room/get_info,
/xlive/web-room/v1/index/getDanmuInfo) and WS /sub protocol (AUTH/HEARTBEAT/
SEND_MSG_REPLY), plus stdin/HTTP /emit control for danmaku/gift/blind box/
guard/super chat/enter/follow
- Verified end-to-end: all events flow through blivedm and render rules
(gift -> 感谢由Baka投喂的小电视, blind box, guard, super chat, custom
danmaku template, enter room)
- Drop 'like' event from rules, handler and web UI (Bilibili like messages
are not reliably delivered as INTERACT_WORD_V2 msg_type=6)
- Keep enter_room / follow / interact_other
- event_rules.json rewritten without like key
- build.py keeps BUILD_DIR = dist/portable
Probe results: AquesTalk1 rejects U+FF01 !, U+300C/D 「」, U+30FB ・,
U+3000 full-width space with error 105; only 、。?〜ー are safe.
User templates containing ! (e.g. 卧槽!、是{uname}!...) now render
correctly: synthesize() final pass replaces any char outside the safe
kana/punctuation set with a 、 pause.
Verified: custom template full pipeline -> WAV 103316 bytes, no 105.
Rebuild portable zip (80.8 MB)
- _on_danmaku renders via event_text(rules, 'danmaku', ...) like all other
events; hardcoded {uname}说、 {msg} format removed
- Drop message_format param from DanmakuHandler/DanmakuClient/server/main
- api_rules_post mutates the shared rules dict in place (clear+update)
instead of rebinding, so running handlers pick up new templates
immediately without restarting TTS
- UI save toast: '规则已保存并即时生效'
- Verified: custom template 卧槽!、是{uname}!、他说、 {msg} works;
save-then-next-danmaku uses new template without restart
- Login/config/rules/status cards fully localized
- Event rule labels, buttons, placeholders and hints in Chinese
- Keep English only in code comments and API internals
- TTSBridge.synthesize wraps stdin/stdout request-response in asyncio.Lock;
concurrent calls previously caused 'readuntil() called while another
coroutine is already waiting' and ENOENT (temp dir deleted while bridge
still reading input.txt)
- TTSService.start/stop guarded by lifecycle lock to prevent race from
rapid Start clicks creating duplicate bridge/worker/danmaku connections
- Verified: 20 concurrent synthesize calls all succeed with correct WAV
- Rebuild portable zip (83.8 MB)
Root cause: AquesTalk_Synthe silently drops all text after a space.
English segments previously joined with spaces (word gap), so anything
after the first space was silent. Replace all spaces with 、 (Japanese
comma pause) which AquesTalk supports natively.
- PUNCT_MAP maps space -> 、
- convertEnglishSegment joins words with 、
- synthesize collapses consecutive pauses, strips residual spaces
Verified: 'Actually这个proposal是非常creative的' WAV 19316 -> 79196 bytes
- Add phonemize (MIT) rule-based G2P as second fallback tier
- IPA phoneme -> katakana CV-syllable transcription table
- proposal -> プラポーザル, bilibili -> バイリーバイリー (no more letter-spelling)
- Letter spelling kept as last resort only
- Bridge logs SYNTH IN/OUT to stderr; tts.py drains stderr to Python logs
so conversion results are visible in the server log
- Rebuild portable zip (83.8 MB)