- 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)