All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.7.32 - 2026-02-16
- fix full_reconnect downgrade & don't ignore Leave messages (#893)
- turn single peerconnection off by default (#897)
- ensure signal connections times out properly and retries (#895)
- added Single Peer Connection support to Rust (#888)
- set the simulcast codec & layers (#891)
0.7.31 - 2026-02-10
- don't use clamp as the ultimate_kbps can be lower than 300 (#886)
- pre-connect the publisher PC when an RPC handler is registered (#880)
0.7.30 - 2026-02-09
- fix the RPC race condition (#865)
- update proto & fix CI (#871)
- Use workspace dependencies & settings (#856)
- Upgrade protocol to v1.44.0 (#857)
- Expose participant's permission to ffi layer (#824)
0.7.29 - 2026-01-15
- ensure Room.creation_time is ms (#822)
- try setting x-google-start-bitrate for vp9 (#820)
0.7.28 - 2025-12-19
- (ParticipantInfo) export kind details (#813)
0.7.27 - 2025-12-17
- Handle server initiated mute request (#812)
0.7.26 - 2025-12-04
- (connector) initial service impl (#790)
- fix mute/unmute events for LocalTrack. (#799)
- Add RoomEvent::TokenRefreshed (#803)
0.7.25 - 2025-11-20
- perform full reconnect if resume fails (#792)
- E2E RPC tests (#769)
- Remove unused dependencies (#761)
0.7.24 - 2025-10-27
- Expose set video quality (#759)
0.7.23 - 2025-10-23
- add h265 codec support (#762)
0.7.22 - 2025-10-22
- License check (#746)
- Remove participant check for data packets (#757)
- clamp connection timeout and fixed the comment (#748)
- put examples in root Cargo workspace (#731)
0.7.21 - 2025-10-13
- (e2ee) add data channel encryption (#708)
- fix some potential audio issues, clean up the code a bit, and suppress some warnings (#737)
- do not log 'signal client closed: "stream closed"' on disconnect (#727)
0.7.20 - 2025-10-03
- updated the following local packages: libwebrtc
0.7.19 - 2025-09-29
- apply original participant fields in data messages (#709)
- Implement Display and Error for RpcError (#719)
- Fix intermittently failing E2E reliability test (#718)
- Do not modify raw packets (#714)
- Add send_bytes method (#691)
- Disable opus red for e2ee enabled clients (#706)
- Upgrade protocol to v1.41.0 (#703)
0.7.18 - 2025-09-09
0.7.17 - 2025-09-03
- updated the following local packages: livekit-api, libwebrtc
0.7.16 - 2025-07-31
- updated the following local packages: livekit-api
0.7.15 - 2025-07-16
- remove published tracks when the room is closed (#677)
0.7.14 - 2025-06-23
audio_frame_msdidn't work expectedly (#671)
0.7.13 - 2025-06-17
- Expose room updates, support MoveParticipant (protocol 15) (#662)
0.7.12 - 2025-06-11
- fix duration overflow (#654)
- Remove debouncer when fast_publish is enabled (#649)
- High-level data streams API
- Low-level data stream packet events
- Revert the RPC change, need more robust way
- Move RPC handlers to room
- Add audio filter support
- Fix a dependency issue with an older version of the libwebrtc crate
- Support for track subscription permissions
- Add an API to set buffer_amount_low_threshold for DataChannel
- Update RoomInfo to contain buffer_amount_low_threshold for DataChannel
- Wait for the buffered amount to become low before sending data during publish_data for Reliable Data Channel
- bump
- Fixed deadlock with nested RPC calls
- bump libwebrtc to m125
- Rename user facing APIs for Packet Trailer to Frame Metadata.
- Upgrade protocol to v1.48.0
- fix: escalate to full reconnect if connection failed during a resume - #1175 (@davidzhao)
webrtc-sys no longer links against glib-2.0/gobject-2.0/gio-2.0 by default.
Breaking: Wayland screen sharing now requires the glib-main-loop feature on livekit (or libwebrtc).
- Add track publishing doc example
- Fix silent subscription failures in single-pc mode when the SFU reuses an existing empty transceiver for a new remote track. Also make
RtpTransceiver::mid()safe to call on transceivers that haven't been negotiated yet — libwebrtc is built with-fno-exceptions, sostd::optional::value()aborted the process instead of throwing. - Add
LK_DISABLE_NVDECto bypass NVIDIA NVDEC decoder registration when the environment variable is set. - return DeviceNotFound when device is not there for set_recording_devi… - #1155 (@xianshijing-lk)
This includes a minor breaking change for libwebrtc: RtpParameters now
contains additional RTP sender state that must be preserved when round-tripping
through set_parameters().
- Fix NVIDIA encoder I420 uploads to copy each plane using its actual source stride, avoiding chroma corruption when source frames use padded YUV planes. Also fix the
local_videopublisher reusing mutable I420 frame storage after handing frames to WebRTC. - Reject oversized data messages before they break the data channel.
- Add per-publication video encoder backend selection. Add a video encoder backend availability query. Remove
LIVEKIT_PREFERRED_HW_ENCODERin favor of per-publication backend selection.
- Add rpc max_round_trip_latency and move to builder pattern - #1127 (@1egoman)
- [allow(dead_code)] for dead function in room module - #1128 (@stephen-derosa)
- Send publisher offer with join request to accelerate connection - #996 (@cnderrauber)
- bump protocol to v1.46.4 - #1121 (@lukasIO)
- Add native video pipeline timing instrumentation for local video measurements, exposing local publish and subscribe timing through async streams and subscriber overlay GPU upload and receive-to-GPU latency metrics through explicit timing observers.
- Introduce pipeline options for remote data tracks, support multiple in-flight frames.
- Filter internal data streams out of livekit-ffi interface - #1112 (@1egoman)
Android requires ContextUtils.initialize(applicationContext) before WebRTC audio components can be created. This change:
- Adds
livekit_ffi_initialize_android_context()C FFI function for Unity and other FFI consumers - Uses
CreateAndroidAudioDeviceModule()instead of genericCreateAudioDeviceModule()on Android - Handles empty device GUIDs on Android (falls back to index 0)
- Documents Android-specific limitations: single default device, no app-level device selection
Platform notes:
- Android device enumeration returns only one "default" device with empty name/GUID
- Audio routing (speaker/earpiece/Bluetooth) is controlled by Android's AudioManager, not WebRTC
- Bugfix: Always emit Disconnected on engine close - #1096 (@MaxHeimbrock)
- Support for large RPC messages using data streams - #1013 (@1egoman)
- feat: add scalability mode for AV1/VP9. - #1076 (@cloudwebrtc)
- Add
LIVEKIT_PREFERRED_HW_ENCODERto prefernvencorvaapihardware video encoding when both are available. - Relocate unrelated types out of
livekit-protocol
This PR introduces platform audio device management via WebRTC's Audio Device Module (ADM).
- ADM Proxy: New
AdmProxyclass that switches between Dummy ADM (synthetic mode) and Platform ADM (real audio I/O) - PlatformAudio API: High-level Rust API for microphone capture and speaker playout with AEC/AGC/NS
- Device enumeration: List and select recording/playout devices by index or GUID
- Mode switching: Seamlessly switch between synthetic mode (FFI callbacks) and platform mode (native speakers) while audio is active
- FFI platform audio support: Expose platform audio device enumeration and selection through
livekit-ffi - Audio processing: Configure echo cancellation, noise suppression, and auto gain control with platform-specific defaults (hardware on iOS, software elsewhere)
| Mode | Recording | Playout | Use Case |
|---|---|---|---|
| Synthetic | NativeAudioSource | Dummy ADM + FFI | Unity audio, agents |
| Platform | Platform ADM mic | Platform ADM speakers | VoIP with AEC |
// Create PlatformAudio for microphone/speaker access
let audio = PlatformAudio::new()?;
// Enumerate and select devices
for i in 0..audio.recording_devices() as u16 {
println!("Mic {}: {}", i, audio.recording_device_name(i));
}
audio.set_recording_device(0)?;
// Create audio track for publishing
let track = LocalAudioTrack::create_audio_track("mic", audio.rtc_source());- fix: Sync inner.enabled state for E2EE manager. - #1073 (@cloudwebrtc)
- Upgrade protocol to v1.45.8
- Bump
rustls-webpkito 0.103.13, addressing GHSA-82j2-j2ch-gfr8 - Fix missing
libwebrtc.jarfor Android builds, harden build scripts - fix: derive
simulcastedfrom non-deprecated TrackInfo fields - #1052 (@cloudwebrtc) - fix race in download_webrtc to reduce flaky build - #1047 (@hechen-eng)
- Improve WebRTC build scripts and add external_audio_source patch - #1053 (@xianshijing-lk)
- support SimulateScenario through FFI to improve testing - #1069 (@davidzhao)
- TEL-464: reduce redundant resampling in audio filter - #1019 (@hechen-eng)
##890 by @chenosaurus
- Add support to attach/parse frame level timestamps & frame ID to VideoTracks as a custom payload trailer.
- Breaking change in VideoFrame API, must include
frame_metadataor use VideoFrame::new().
- Add device-info crate and send device_info to telemetry - #982 (@maxheimbrock)
- Fix data track packet format issue breaking E2EE
- Fix unbound send queue that can cause latency in data track messages - #1032 (@chenosaurus)
- Fix for raw stream drop called from non tokio thread like Unity .NET GC - #1016 (@MaxHeimbrock)
- Initial support for data tracks
##956 by @xianshijing-lk
Before this PR, it uses an unbounded buffer for video stream, that will cause multiple problems: 1, video will be lagged behind if rendering is slow or just wake up from background 2, it will be out of sync with audio
This PRs provides options to set a bounded buffer for video stream, and use 1 buffer as the default option.
- Expose participant active event, state, and joined at
- Upgrade to thiserror 2
##921 by @onestacked
This PR uses this webrtc-sdk PR to configure the KDF.
I've tested this with https://codeberg.org/esoteric_programmer/matrix-jukebox and it is compatible with Element Call.
Fixed: #796
- Add disconnectReason to Room::close
- End-to-end testing for video streams
- Fix H.264 codec matching
##945 by @xianshijing-lk
##955 by @s-hamdananwar
When a participant connects with canSubscribe=false in their token, the server sends subscriber_primary=false in the JoinResponse and does not send a subscriber offer. This results in wait_pc_connection timing out as it is expecting a subscriber PC even when the publisher PC is primary. This PR will skip waiting for subscriber PC when subscriber_primary=false.
##952 by @MaxHeimbrock
Adds os_info crate as dependency and sends the data for client connections.
##847 by @SchmErik
##914 by @xianshijing-lk