Environment
- @livekit/react-native 2.10.2 AND 2.11.0 (both reproduce)
- @livekit/react-native-webrtc 144.0.0 AND 144.1.0 (both reproduce)
- livekit-client 2.18.9 / 2.19.1
- RN 0.81.5, New Architecture, Expo SDK 54
- Publisher: iPhone, iOS 26. Subscriber: Samsung (Exynos), OMX.Exynos.vp8.dec
- Self-hosted LiveKit server 1.11.0; shared-key E2EE via RNKeyProvider({sharedKey:true}) + RNE2EEManager
Symptom
In a 2-peer E2EE call, video published by the iPhone renders black on the Android
subscriber. Audio works both ways, data channel works, and the REVERSE direction
(Android-published video on the iPhone) works. With E2EE disabled, video works both
ways. Key is correct/symmetric (reverse direction decrypts). Codec-independent:
forcing VP8, H264, and VP9 all reproduce identically.
Decisive getStats (Android subscriber, iPhone video track)
bytesReceived and packetsReceived climb normally (megabytes, thousands of packets —
the SFU forwards fine), but:
- framesReceived climbs, framesDropped ≈ framesReceived, framesDecoded = 0,
keyFramesDecoded = 1, pliCount = 0, frameWidth/Height = undefined.
Frames are assembled then dropped before decode → the decrypted bitstream is
structurally invalid for the decoder. frameCryptionStateChanged reports ok
(AES-GCM auth passes), so the corruption is in framing/unencrypted-byte handling,
not the cipher.
Suspected cause
Divergence between the iOS encrypt path and the Android decrypt path in the number of
unencrypted leading bytes left on a video frame (the codec/keyframe header). Audio
(single-packet frames) is unaffected; only multi-packet video frames break, in the
iOS→Android direction only.
Repro
2 devices (iOS publisher + Android subscriber), shared-key E2EE, any video codec.
Happy to provide a minimal repro or full logs.
Environment
Symptom
In a 2-peer E2EE call, video published by the iPhone renders black on the Android
subscriber. Audio works both ways, data channel works, and the REVERSE direction
(Android-published video on the iPhone) works. With E2EE disabled, video works both
ways. Key is correct/symmetric (reverse direction decrypts). Codec-independent:
forcing VP8, H264, and VP9 all reproduce identically.
Decisive getStats (Android subscriber, iPhone video track)
bytesReceived and packetsReceived climb normally (megabytes, thousands of packets —
the SFU forwards fine), but:
keyFramesDecoded = 1, pliCount = 0, frameWidth/Height = undefined.
Frames are assembled then dropped before decode → the decrypted bitstream is
structurally invalid for the decoder. frameCryptionStateChanged reports
ok(AES-GCM auth passes), so the corruption is in framing/unencrypted-byte handling,
not the cipher.
Suspected cause
Divergence between the iOS encrypt path and the Android decrypt path in the number of
unencrypted leading bytes left on a video frame (the codec/keyframe header). Audio
(single-packet frames) is unaffected; only multi-packet video frames break, in the
iOS→Android direction only.
Repro
2 devices (iOS publisher + Android subscriber), shared-key E2EE, any video codec.
Happy to provide a minimal repro or full logs.