Realtime voice: Korean live transcript renders U+FFFD replacement characters (Frameless/AVAS path)
Summary
In the Codex desktop app's realtime voice conversation, Korean live transcripts intermittently render U+FFFD replacement characters where a Hangul syllable should be. Example: 가볍게 얘기핼봐요 renders as 가볍게 ��기핼봐요.
One 3-byte Hangul syllable (얘 = U+C598 = EC 96 98) becoming exactly two U+FFFD is the signature of lossy UTF-8 decoding of a byte sequence that was split at a EC 96 | 98-style boundary. Somewhere in the voice transcript path, bytes are being decoded at a chunk boundary instead of as complete UTF-8.
Environment
- Codex desktop app (bundled codex
0.146.0-alpha.3.1, framework150.0.7871.128), macOS arm64 - ChatGPT auth; realtime voice via call-create + sideband WebSocket (Frameless/AVAS,
intent=quicksilver&architecture=avas)
What I ruled out, with evidence
- Local proxy relay (opencodex, transparent sideband relay). A regression test driving Korean text frames, binary UTF-8 frames, and ~1.3 MB large frames through the relay passes byte-identically in both directions. Relay does not touch frame contents.
- codex-rs realtime chain (source audit @
4462b9dee). The sideband is consumed via tungsteniteMessage::Text(protocol-validated UTF-8); transcript deltas are parsed with serdeas_str(protocol_common.rs::parse_transcript_delta_event); app-serverthread/realtime/transcript/deltanotifications are serde Strings end to end; the app renderer concatenates strings. No lossy decode exists in any inspectable hop. - Public GA Realtime WS API. I streamed synthesized Korean speech (24 kHz PCM16 mono) to
wss://api.openai.com/v1/realtime?model=gpt-realtimewithgpt-4o-transcribeinput transcription. All 25conversation.item.input_audio_transcription.deltaevents and the.completedtranscript came back as clean Korean with zero U+FFFD — the public pipeline handles multibyte delta boundaries correctly.
Conclusion
Every client-side and public-API hop is Unicode-safe, so the corruption is introduced either:
- in the internal Frameless/AVAS input-transcription delta pipeline (server side, distinct from the public GA pipeline I tested), or
- in the bundled realtime consumer in the desktop app (which is newer than the public codex-rs source I could audit).
Reproduction
- Open a realtime voice conversation in the Codex desktop app.
- Speak Korean (a TTS sample is enough — I used macOS
saywith ako_KRvoice at 24 kHz). - Watch the live transcript; Hangul syllables sporadically appear as
��pairs mid-stream.
Ask
Please check the Frameless/AVAS input-transcription delta path for byte-level chunking followed by lossy UTF-8 decode. If it helps, I have an env-gated frame tap on the local relay (per-frame direction/kind/byte-length/U+FFFD-context, no payloads) that can attribute the corruption to upstream vs client from one real voice session — happy to share a capture.