Realtime voice: Korean live transcript renders U+FFFD replacement characters (Frameless/AVAS path)

Open 💬 0 comments Opened Jul 24, 2026 by lidge-jun

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, framework 150.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

  1. 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.
  2. codex-rs realtime chain (source audit @ 4462b9dee). The sideband is consumed via tungstenite Message::Text (protocol-validated UTF-8); transcript deltas are parsed with serde as_str (protocol_common.rs::parse_transcript_delta_event); app-server thread/realtime/transcript/delta notifications are serde Strings end to end; the app renderer concatenates strings. No lossy decode exists in any inspectable hop.
  3. Public GA Realtime WS API. I streamed synthesized Korean speech (24 kHz PCM16 mono) to wss://api.openai.com/v1/realtime?model=gpt-realtime with gpt-4o-transcribe input transcription. All 25 conversation.item.input_audio_transcription.delta events and the .completed transcript 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

  1. Open a realtime voice conversation in the Codex desktop app.
  2. Speak Korean (a TTS sample is enough — I used macOS say with a ko_KR voice at 24 kHz).
  3. 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.

View original on GitHub ↗