Minor Changes
-
Create the publisher data channels as negotiated (fixed IDs) in single peer connection mode when the server supports it (protocol 18), saving the data channel open round trip. Falls back to in-band channels against older servers. - #2160 (@lukasIO)
-
Split
RoomintoCoreRoomplus extensions.createRoom(options, [extensions])fromlivekit-client/corebuilds a room with only the extensions an application needs;e2ee,frameMetadataanddataStreamstake their options directly.Room.dispose()releases a room for good. Video publishing (camera, screen share, simulcast, SVC, backup codecs) is thevideoextension; receiving video stays in core. The newlivekit-client/coreentry (ESM only, experimental) exportsCoreRoomand the extensions.simulateParticipantsand the legacy chat messages are extensions too; the core entry does not offer legacy chat. - #2141 (@lukasIO)
Patch Changes
-
If the server disconnects the participant while
room.connect()is still waiting for the transports (e.g. aDUPLICATE_IDENTITYleave), the connection attempt is now cancelled. Previously it kept waiting untilpeerConnectionTimeout, then failed over to another region and rejoined with the same token after the room had already emittedDisconnected;room.disconnect()could not stop it because the room already looked disconnected. - #2177 (@tobelesa) -
Cancel an incoming data stream when its reader stops early (an aborted
signal, abreakout offor await, or a read error), so the stream is unregistered and later packets for it are dropped instead of buffering until the trailer arrives. A reader can no longer resume a stream after leaving its iteration early. - #2168 (@1egoman) -
Conform placeholder fmtp for codecs without an fmtp line - #2182 (@eleboucher)
-
add datatrack data channel to sync state info - #2159 (@lukasIO)
-
Fix data packet decryption after the sender ratchets its key:
DataCryptornow retries with the ratcheted key instead of the stored one - #2188 (@ninglinLiu) -
Mark data track unpublished after republish fail - #2170 (@1egoman)
-
Fix an unhandled promise rejection when the signal passed to
dataTracks.getDeferred()aborts, even though the caller catches the rejected promise. - #2156 (@Abhishek-B-R) -
Stop playing a remote audio track in Chrome once it is detached. - #2234 (@murilo-teleo)
-
Fix a memory leak where a
Roomwas never garbage collected after the application dropped it. - #2222 (@1egoman) -
Keep the H.264 PPS id readable in E2EE keyframes, so that Chrome no longer drops keyframes from encoders such as Intel Quick Sync - #2181 (@lukasIO)
-
fix(e2ee): keep the encryption state of received tracks per track - #2246 (@lukasIO)
-
fix(e2ee): track the local encryption state separately from remote participants - #2245 (@lukasIO)
-
Speed up the emulation prevention step for encrypted H.264 and H.265 frames.
writeRbspnow returns the input unchanged when no byte needs escaping, and otherwise copies runs of bytes instead of building a JS array. The output does not change. - #2184 (@lukasIO) -
Stop
Room.getLocalDevices()without a kind from callinggetUserMediawhen every device is already listed with a label. - #2232 (@RaphaelFakhri) -
Ignore a late participant update for an older session of a remote participant, so it no longer removes or replaces the participant's current session in
room.remoteParticipants. - #2229 (@Brian-1812) -
Follow a full reconnect that happens during the initial connection (e.g. after the server moves a client off dead UDP) instead of timing out on the closed transports and tearing down the recovered session. The room stays
Connectingwhile a resume, a restart or a browser offline event happens insideconnect()and emits noSignalReconnecting,ReconnectingorReconnected. Also stop polling the transports after the connection timeout, and reject an already-aborted transport wait as cancelled instead of leaving it pending. - #2135 (@rafaelhutter) -
Limit each remote participant to 500 concurrently open incoming data streams by default. Headers for new streams beyond the limit are dropped with an error log, so a participant can no longer exhaust a receiver's memory by opening streams it never closes. The limit can be changed with the
dataStream.maxOpenStreamsPerParticipantroom option. - #2214 (@1egoman) -
Fixes an issue where if a data stream runs into a terminal error, any packets delivered afterwards will be treated as if the stream doesn't exist (and not throw a sync error) - #2167 (@1egoman)
-
Apply the
peerConnectionTimeoutconnect option to the negotiation deadline - #2189 (@ninglinLiu) -
Fix the microphone pre-connect buffer never starting when
preConnectBufferis passed via publish options. - #2252 (@1egoman) -
fix published type declarations for consumers with
skipLibCheck: falseorexactOptionalPropertyTypes- #2175 (@lukasIO) -
Stop a disconnected
SignalClientfrom logging a spurious "ping timeout triggered" warning 15 s afterroom.disconnect(). - #2239 (@Brian-1812) -
Stop logging
error reading from signal streamat error level when the signal socket was closed by the client or replaced; the read failure is now logged at debug level with the ignored close - #2192 (@ninglinLiu) -
The debug log for a ratcheted E2EE key no longer includes the ratchet result, so the chain key and the new key material stay out of the console and out of log extensions. - #2213 (@lukasIO)
-
Keep
engine.pendingReconnectaccurate across reconnect attempts. A failed attempt no longer clears the handle of the retry it just scheduled (which madependingReconnectreadfalsewhile a retry was pending), and the flag now clears as soon as the reconnect timer is cleared. Buffered room events are also flushed when the engine finishes restarting if the room already reports connected. - #2193 (@1egoman) -
Emit
Reconnectedonce and keep room metadata and recording changes when a full reconnect fails over to another region - #2165 (@lukasIO) -
Fix dynacast never pausing video layers on React Native: save sender encodings before skipping the stats monitor - #2163 (@davidliu)
-
Wait for the first frame of a screen share before reading its dimensions, so its simulcast layers are announced at the size the capture delivers instead of the requested resolution. - #2217 (@CSantosM)
-
Ignore signal messages received after the WebSocket is closed on React Native - #2173 (@davidliu)
-
fix(room): skip a deferred track the server stopped sending - #2225 (@lukasIO)
-
Keep the mid to track id mapping of the current publisher answer when an answer to an older offer or an answer with an empty mapping arrives in single peer connection mode, so remote tracks whose
trackevent fires later are no longer dropped - #2196 (@ninglinLiu) -
If
room.disconnect()runs during the signal join, the connection attempt now rejects as cancelled instead of with aTypeError. A stale connection attempt no longer closes the engine of a newer connection or disconnects the room. - #2151 (@lukasIO) -
Fix
TokenSourcecaching: a failed fetch no longer leaves the previous response cached under the new options, andparticipantAttributesis compared by content - #2198 (@ninglinLiu) -
Document that
RemoteTrackPublication.videoQualityreturns the quality requested withsetVideoQuality(). It does not show the layer that adaptive stream or network bandwidth selects. - #2220 (@Brian-1812) -
Reject
WebSocketStream.openedwhen the socket closes before it opens, so that a failed, timed-out or aborted signal (re)connect on React Native no longer holds the connection lock. - #2179 (@sarankumar1325)