Conversation
chenosaurus
commented
Apr 14, 2026
- Add support for packet trailer features (user timestamp, frame ID).
- Add new web worker for packet trailer parsing.
- update example/demo to have options to enable packet trailer & render the parsed metadata.
- Unit tests for packet trailer parsing.
…ryptor for performance
|
size-limit report 📦
|
| // Disabling it for Chrome based browsers until the API has stabilized | ||
| !isChromiumBased() | ||
| !isChromiumBased() && | ||
| !ptPreProcessed |
There was a problem hiding this comment.
I'm not sure I follow why this is being checked for here, can you elaborate on the intention behind it?
| @@ -0,0 +1,198 @@ | |||
| export const PACKET_TRAILER_MAGIC = Uint8Array.from([ | |||
There was a problem hiding this comment.
have you considered signalling packet-trailer presence as part of the publication info instead of relying on checking every frame on every publication for the magic bytes?
There was a problem hiding this comment.
There is already support on track publication to declare which packet trailer features are available on the track. It's exposed to the subscriber in TrackInfo. I have updated all place to check TrackInfo before attaching transformer.
| if (typeof metadata.rtpTimestamp === 'number') { | ||
| return metadata.rtpTimestamp; | ||
| } | ||
| if (typeof metadata.timestamp === 'number') { |
There was a problem hiding this comment.
what is this referring to? I don't see a timestamp value on getMetadata here
There was a problem hiding this comment.
is it intentional that this file lives in the /e2ee folder? 👀
There was a problem hiding this comment.
no, that's a mistake. Moved.
|
|
||
| export const version = v; | ||
| export const protocolVersion = 16; | ||
| export const protocolVersion = 17; |
There was a problem hiding this comment.
The related protocol PR talks about stripping the trailer on the SFU side, but I don't think bumping protocolVersion is enough: what happens if a client with protocolVersion 17 doesn't have the trailer worker set?
There was a problem hiding this comment.
^ This is probably my biggest question as well.
It sort of sounds like you want a "feature" you can communicate support of unrelated to a protocol / client version. I recently wrote a note about this in the context of the in flight rpc protocol updates here: #1832 (comment)
Keeping in mind we haven't discussed mechanically how this pattern would work yet (ie, new fields in ParticipantInfo, something in the JoinResponse, etc?), I think if you did something like that then the SFU could know if packet trailer processing is enabled on the client independent of the protocol version and opt to strip or not strip conditionally.
Thoughts on that proposal?
There was a problem hiding this comment.
The packet trailer transform is lightweight enough to run on the main thread, we can as a backup attach the transform automatically (when worker is not passed in) when we see any tracks that declared packet trailer features in its TrackInfo. That would always work and avoid having to change any signaling to the SFU.
There was a problem hiding this comment.
The packet trailer transform is lightweight enough to run on the main thread
If this is the case, is there a reason why it shouldn't always be run on the main thread then rather than having the optional worker?
There was a problem hiding this comment.
see response on a later comment, it's possible to attach the packet trailer transformer directly to the transceiver in the main thread to avoid the issue of worker not being initialized. However, we should try to use the worker whenever possible to not have to process frames in the main thread.
| } catch { | ||
| // best-effort: never break the media pipeline if trailer parsing fails | ||
| } |
There was a problem hiding this comment.
question: Is it worth at least logging something here to make it clear that a failure happened?
| } catch { | ||
| // getMetadata() might not be available | ||
| } |
There was a problem hiding this comment.
suggestion: Another place where it might be worth logging
| * When E2EE is active, the E2EE FrameCryptor worker handles trailer | ||
| * extraction directly (before decryption), so this manager only creates | ||
| * the extractor/metadata cache — no separate insertable-streams pipeline | ||
| * is needed. |
There was a problem hiding this comment.
question: I'm not sure I understand why this packet trailer logic exists both in the e2ee worker and in the new packet trailer worker. Can you shed some light on why you made this decision? Does it have to do with the goal of encrypting the packet payload and trailer separately so the SFU can strip out the trailer without that process requiring decrypting a single large block?
I don't have enough context to be incredibly confident in this suggestion, but if you can't attach multiple transforms which run in series there might be some value in adding some sort of "stream transform composer" layer above both this and the e2ee manager which would connect a series of transforms together and allows each to fully own their respective responsibilities.
There was a problem hiding this comment.
The main reason is each track transceiver can only have a single transform attached, so if e2ee is enabled, we can't also attach the packetTrailer transform worker. Thus the need to have the same logic inside e2ee for parsing packet trailers if both features are enabled.
I think your suggestion makes sense but would mean a much bigger refactor where e2eeManager & e2ee worker needs to be replaced by a more generic frameTransformManager & a new worker that can handle both e2ee & packetTrailer.
| /** | ||
| * @experimental | ||
| * Options for enabling packet trailer extraction on received video tracks. | ||
| * Packet trailers carry frame-level metadata such as user timestamps and frame IDs. | ||
| */ | ||
| packetTrailer?: PacketTrailerOptions; | ||
|
|
There was a problem hiding this comment.
thought: After this gets eventually is merged, you may want to add a todo for yourself to wire this through in components-js in a similar way to what we recently did for encryption, see here for more info: livekit/components-js#1317
|
|
||
| export const version = v; | ||
| export const protocolVersion = 16; | ||
| export const protocolVersion = 17; |
There was a problem hiding this comment.
^ This is probably my biggest question as well.
It sort of sounds like you want a "feature" you can communicate support of unrelated to a protocol / client version. I recently wrote a note about this in the context of the in flight rpc protocol updates here: #1832 (comment)
Keeping in mind we haven't discussed mechanically how this pattern would work yet (ie, new fields in ParticipantInfo, something in the JoinResponse, etc?), I think if you did something like that then the SFU could know if packet trailer processing is enabled on the client independent of the protocol version and opt to strip or not strip conditionally.
Thoughts on that proposal?