Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
d2c9858
add user timestamping feature
chenosaurus Feb 11, 2026
4d4027d
attach timestamp in example
chenosaurus Feb 11, 2026
b0d3c04
fix the latency calcs
chenosaurus Feb 12, 2026
90083c3
cleanup display overlays
chenosaurus Feb 12, 2026
f84fae3
rename flag
chenosaurus Feb 12, 2026
03083a0
add e2ee options
chenosaurus Feb 12, 2026
dd62177
display simulcast state
chenosaurus Feb 12, 2026
a742917
Merge branch 'main' into dc/feature/user_timestamp
chenosaurus Feb 12, 2026
d1b0d5c
use a mapping of rtp timestamp to user timestamp on subscriber side too
chenosaurus Feb 13, 2026
f68b83e
move the subscriber user timestamp handler to internal to clean up API
chenosaurus Feb 13, 2026
22f93d9
remove UserTimestamp store in favor of simple map to track ts
chenosaurus Feb 16, 2026
58eef75
Merge branch 'main' into dc/feature/user_timestamp
chenosaurus Feb 17, 2026
32b7278
use chrono crate instead of custom format func
chenosaurus Feb 17, 2026
63c68aa
remove comment
chenosaurus Feb 17, 2026
a60654f
change update to 2hz
chenosaurus Feb 17, 2026
867e295
remove last_user_timestamp
chenosaurus Feb 18, 2026
5a1ba5a
update readme
chenosaurus Feb 18, 2026
dde7de6
cargo fmt
chenosaurus Feb 18, 2026
eecec0e
remove unused callback reference
chenosaurus Feb 18, 2026
aa1cdb6
make the rtp lookup map insertion & removal more robust
chenosaurus Feb 18, 2026
2a52bbe
use new option for payload trailer features to enable timestamping
chenosaurus Mar 3, 2026
38734f4
remove timestamp logs
chenosaurus Mar 3, 2026
eea46e1
remove noisy logs
chenosaurus Mar 4, 2026
1c779a2
lint
chenosaurus Mar 4, 2026
6f172c1
update TrackPublishOptions in livekit-ffi
chenosaurus Mar 4, 2026
de9cd2b
adding the PayloadTrailerFeatures to the ffi protos
chenosaurus Mar 4, 2026
d40b41d
attach parser transformer always
chenosaurus Mar 7, 2026
f20a93e
add frame id to trailer
chenosaurus Mar 7, 2026
57a7f74
fix parsing. Explicitly set simulcast fps to 30.
chenosaurus Mar 7, 2026
d940542
remove debug outputs
chenosaurus Mar 10, 2026
f7120e2
output better encode stats
chenosaurus Mar 10, 2026
91283fa
simplify stats
chenosaurus Mar 10, 2026
a8412fb
add timestamp on video frame option
chenosaurus Mar 11, 2026
6ab6250
add timestamp burn mod
chenosaurus Mar 11, 2026
790d254
move to TLV trailer format
chenosaurus Mar 11, 2026
8c2a96f
add changeset & add more details to subscriber example for timing
chenosaurus Mar 11, 2026
86fdd78
actually add changeset
chenosaurus Mar 12, 2026
c7ba053
Merge branch 'main' into dc/feature/user_timestamp
chenosaurus Mar 13, 2026
339f886
generated protobuf
github-actions[bot] Mar 13, 2026
10b9220
rename to packet trailer
chenosaurus Mar 13, 2026
716374f
Merge branch 'dc/feature/user_timestamp' of github.com:livekit/rust-s…
chenosaurus Mar 15, 2026
351780f
use packet trailer features for enabling specific trailers
chenosaurus Mar 23, 2026
aa99c37
revert local changes
chenosaurus Mar 23, 2026
b9cc8f1
Merge branch 'main' into dc/feature/user_timestamp
chenosaurus Mar 23, 2026
c3f44e8
add frame ID to ffi
chenosaurus Mar 23, 2026
d995159
cargo fmt
chenosaurus Mar 23, 2026
79cabbf
fix typo in changeset
chenosaurus Mar 23, 2026
278c925
update readme
chenosaurus Mar 24, 2026
f27d3d5
remove unused crates
chenosaurus Mar 24, 2026
17c076b
add new() to VideoFrame with defaults for frame_id & user_timestamp_u…
chenosaurus Mar 24, 2026
28502fa
update changeset & remove debug logs
chenosaurus Mar 24, 2026
4689d97
fix rendering when packet trailer feature is not populated
chenosaurus Mar 26, 2026
516b338
put frame metadata into FrameMetadata struct
chenosaurus Mar 26, 2026
1f18f0f
update VideoFrame to use FrameMetadata
chenosaurus Mar 26, 2026
b311d94
change user_timestamp to u64
chenosaurus Mar 26, 2026
8bc4779
cargo fmt
chenosaurus Mar 26, 2026
b6747fa
generated protobuf
github-actions[bot] Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .changeset/add_support_for_frame_level_packet_trailer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
livekit: minor
livekit-protocol: minor
livekit-api: minor
livekit-wakeword: no changelog additions
soxr-sys: no changelog additions
webrtc-sys-build: no changelog additions
webrtc-sys: minor
livekit-ffi: minor
yuv-sys: no changelog additions
libwebrtc: minor
imgproc: no changelog additions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: I think "no changelog additions" still triggers a release for those packages. You can just remove the lines for unaffected packages.

---

# Add support for frame level packet trailer

#890 by @chenosaurus

- Add support to attach/parse frame level timestamps & frame ID to VideoTracks as a custom payload trailer.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion examples/local_video/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "local_video"
version = "0.1.0"
version = "0.2.0"
edition.workspace = true
publish = false

Expand Down Expand Up @@ -41,6 +41,7 @@ wgpu = { workspace = true }
winit = { workspace = true, features = [ "android-native-activity" ] }
parking_lot = { workspace = true, features = ["deadlock_detection"] }
anyhow = { workspace = true }
chrono = "0.4"
bytemuck = { version = "1.16", features = ["derive"] }

nokhwa = { version = "0.10", default-features = false, features = ["output-threaded"] }
Expand Down
70 changes: 64 additions & 6 deletions examples/local_video/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,38 @@ Publisher usage:
--url https://your.livekit.server \
--api-key YOUR_KEY \
--api-secret YOUR_SECRET

# publish with a user timestamp attached to every frame
cargo run -p local_video -F desktop --bin publisher -- \
--camera-index 0 \
--room-name demo \
--identity cam-1 \
--attach-timestamp

# publish with timestamp burned into the video and a frame ID in the packet trailer
cargo run -p local_video -F desktop --bin publisher -- \
--camera-index 0 \
--room-name demo \
--identity cam-1 \
--attach-timestamp \
--burn-timestamp \
--attach-frame-id

# publish at a custom resolution and framerate
cargo run -p local_video -F desktop --bin publisher -- \
--camera-index 0 \
--width 1920 \
--height 1080 \
--fps 60 \
--room-name demo \
--identity cam-1

# publish with end-to-end encryption
cargo run -p local_video -F desktop --bin publisher -- \
--camera-index 0 \
--room-name demo \
--identity cam-1 \
--e2ee-key my-secret-key
```

List devices usage:
Expand All @@ -38,9 +70,17 @@ List devices usage:
```

Publisher flags (in addition to the common connection flags above):
- `--camera-index <n>`: Camera index to use (default: `0`). Use `--list-cameras` to see available indices.
- `--width <px>`: Desired capture width (default: `1280`).
- `--height <px>`: Desired capture height (default: `720`).
- `--fps <n>`: Desired capture framerate (default: `30`).
- `--h265`: Use H.265/HEVC encoding if supported (falls back to H.264 on failure).
- `--simulcast`: Publish simulcast video (multiple layers when the resolution is large enough).
- `--max-bitrate <bps>`: Max video bitrate for the main (highest) layer in bits per second (e.g. `1500000`).
- `--attach-timestamp`: Attach the current wall-clock time (microseconds since UNIX epoch) as the user timestamp on each published frame. The subscriber can display this to measure end-to-end latency.
- `--burn-timestamp`: Burn the attached timestamp into the video frame as a visible overlay. Has no effect unless `--attach-timestamp` is also set.
- `--attach-frame-id`: Attach a monotonically increasing frame ID to each published frame via the packet trailer. The subscriber displays this in the timestamp overlay when `--display-timestamp` is used.
- `--e2ee-key <key>`: Enable end-to-end encryption with the given shared key. The subscriber must use the same key to decrypt.

Subscriber usage:
```
Expand All @@ -55,13 +95,31 @@ Subscriber usage:
--api-key YOUR_KEY \
--api-secret YOUR_SECRET

# subscribe to a specific participant's video only
cargo run -p local_video -F desktop --bin subscriber -- \
--room-name demo \
--identity viewer-1 \
--participant alice
# subscribe to a specific participant's video only
cargo run -p local_video -F desktop --bin subscriber -- \
--room-name demo \
--identity viewer-1 \
--participant alice

# display timestamp overlay (requires publisher to use --attach-timestamp)
cargo run -p local_video -F desktop --bin subscriber -- \
--room-name demo \
--identity viewer-1 \
--display-timestamp

# subscribe with end-to-end encryption (must match publisher's key)
cargo run -p local_video -F desktop --bin subscriber -- \
--room-name demo \
--identity viewer-1 \
--e2ee-key my-secret-key
```

Subscriber flags (in addition to the common connection flags above):
- `--participant <identity>`: Only subscribe to video tracks from the specified participant.
- `--display-timestamp`: Show a top-left overlay with frame ID, the publisher's timestamp, the subscriber's current time, and the computed end-to-end latency. Timestamp fields require the publisher to use `--attach-timestamp`; frame ID requires `--attach-frame-id`.
- `--e2ee-key <key>`: Enable end-to-end decryption with the given shared key. Must match the key used by the publisher.

Notes:
- `--participant` limits subscription to video tracks from the specified participant identity.
- If the active video track is unsubscribed or unpublished, the app clears its state and will automatically attach to the next matching video track when it appears.
- For E2EE to work, both publisher and subscriber must specify the same `--e2ee-key` value. If the keys don't match, the subscriber will not be able to decode the video.
- The timestamp overlay updates at ~2 Hz so the latency value is readable rather than flickering every frame.
Loading
Loading