1
0

feat: add ephemeral webcam faces and adaptive screens

This commit is contained in:
2026-08-11 22:38:56 -07:00
parent 3326d2e6d0
commit d4859b33c6
17 changed files with 1107 additions and 11 deletions
+135 -1
View File
@@ -1,6 +1,8 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
DEFAULT_SCREEN_SHARE_ENCODING_POLICY,
applyScreenShareEncodingPolicy,
createRemoteOfficeMedia,
type MediaAuthorizationDecision,
type RemoteMediaTimers,
@@ -21,9 +23,40 @@ class FakeTrack {
readonly kind = "video";
readyState: MediaStreamTrackState = "live";
stopped = 0;
contentHint = "";
private readonly settings: MediaTrackSettings;
constructor(settings: MediaTrackSettings = { width: 3_840, height: 2_160, frameRate: 60 }) {
this.settings = settings;
}
getSettings(): MediaTrackSettings { return { ...this.settings }; }
stop(): void { this.stopped += 1; this.readyState = "ended"; }
}
class FakeSender {
readonly writes: RTCRtpSendParameters[] = [];
private readonly rejectWrites: boolean;
private readonly supported: boolean;
constructor(rejectWrites = false, supported = true) {
this.rejectWrites = rejectWrites;
this.supported = supported;
}
getParameters(): RTCRtpSendParameters {
if (!this.supported) throw new Error("getParameters unsupported");
return {
encodings: [{}],
degradationPreference: "balanced",
headerExtensions: [],
codecs: [],
rtcp: { cname: "fake", reducedSize: false },
transactionId: "fake",
};
}
async setParameters(value: RTCRtpSendParameters): Promise<void> {
if (this.rejectWrites) throw new DOMException("unsupported", "NotSupportedError");
this.writes.push(structuredClone(value));
}
}
class FakeStream {
readonly tracks: FakeTrack[];
constructor(tracks: FakeTrack[]) { this.tracks = tracks; }
@@ -48,9 +81,15 @@ class FakePeer {
readonly remote: RTCSessionDescriptionInit[] = [];
readonly ice: (RTCIceCandidateInit | null)[] = [];
readonly transceivers: string[] = [];
readonly senders: FakeSender[] = [];
closed = 0;
addTrack(track: MediaStreamTrack): RTCRtpSender { this.added.push(track); return {} as RTCRtpSender; }
addTrack(track: MediaStreamTrack): RTCRtpSender {
this.added.push(track);
const sender = new FakeSender();
this.senders.push(sender);
return sender as unknown as RTCRtpSender;
}
addTransceiver(kind: string): RTCRtpTransceiver { this.transceivers.push(kind); return {} as RTCRtpTransceiver; }
async createOffer(): Promise<RTCSessionDescriptionInit> { return { type: "offer", sdp: "presenter-offer" }; }
async createAnswer(): Promise<RTCSessionDescriptionInit> { return { type: "answer", sdp: "viewer-answer" }; }
@@ -176,6 +215,41 @@ async function settle(): Promise<void> {
await new Promise<void>((resolve) => setTimeout(resolve, 0));
}
describe("screen share sender policy", () => {
it("caps a 4K sender at the explicit 720p/15 bandwidth contract", async () => {
const track = new FakeTrack();
const sender = new FakeSender();
const result = await applyScreenShareEncodingPolicy(
track as unknown as MediaStreamTrack,
sender as unknown as RTCRtpSender,
);
assert.deepEqual(result, { contentHintApplied: true, senderParametersApplied: true });
assert.equal(track.contentHint, "detail");
assert.equal(DEFAULT_SCREEN_SHARE_ENCODING_POLICY.maximumWidth, 1_280);
assert.equal(DEFAULT_SCREEN_SHARE_ENCODING_POLICY.maximumHeight, 720);
assert.deepEqual(sender.writes[0]?.encodings, [{
maxBitrate: 1_500_000,
maxFramerate: 15,
scaleResolutionDownBy: 3,
}]);
assert.equal(sender.writes[0]?.degradationPreference, "maintain-resolution");
});
it("falls back without throwing when a browser rejects sender parameters", async () => {
const track = new FakeTrack();
const rejected = await applyScreenShareEncodingPolicy(
track as unknown as MediaStreamTrack,
new FakeSender(true) as unknown as RTCRtpSender,
);
assert.deepEqual(rejected, { contentHintApplied: true, senderParametersApplied: false });
const unsupported = await applyScreenShareEncodingPolicy(
track as unknown as MediaStreamTrack,
{} as RTCRtpSender,
);
assert.deepEqual(unsupported, { contentHintApplied: true, senderParametersApplied: false });
});
});
describe("remote office media presenter", () => {
it("requires opt-in, publishes one caller track, and keeps credentials in authenticated POST bodies", async () => {
const presenterTrack = new FakeTrack();
@@ -210,6 +284,7 @@ describe("remote office media presenter", () => {
await settle();
assert.equal(peers.length, 1);
assert.equal(peers[0]?.added[0], presenterTrack as unknown as MediaStreamTrack);
assert.equal(peers[0]?.senders[0]?.writes[0]?.encodings[0]?.maxFramerate, 15);
assert.equal(video.autoplay, false);
assert.equal(video.muted, true);
const signal = calls.find((call) => call.url.endsWith("/signal"));
@@ -229,9 +304,68 @@ describe("remote office media presenter", () => {
assert.equal(JSON.stringify(media.state()).includes("private-presenter-grant"), false);
await media.stop();
assert.equal(presenterTrack.stopped, 0, "caller-owned capture track survives stop");
assert.equal(presenterTrack.contentHint, "", "caller-owned track metadata is restored on stop");
assert.equal(peers[0]?.closed, 1);
});
it("applies the bounded sender policy independently to late-joining viewers", async () => {
const first = { participantId: "viewer-first", role: "viewer" as const };
const late = { participantId: "viewer-late", role: "viewer" as const };
const peers: FakePeer[] = [];
const fetcher: typeof fetch = async (input, init = {}) => {
const body = JSON.parse(String(init.body)) as Record<string, unknown>;
const ice = iceResponse(input, body);
if (ice) return ice;
if (String(input).endsWith("/join")) {
return Response.json(grant("screen-share-create-grant", String(body.requestId), "presenter", [first]), { status: 201 });
}
if (String(input).endsWith("/events")) {
return sse([
grant("screen-share-resume-grant", String(body.requestId), "presenter", [first]),
{
type: "screen-share-participants",
protocolVersion: 1,
sequence: 2,
timestampMs: NOW + 1,
sessionId: "share-session",
binding: BINDING,
participants: [first, late],
leaseExpiresAtMs: NOW + 60_000,
},
]);
}
return new Response(null, { status: 204 });
};
const track = new FakeTrack();
const media = createRemoteOfficeMedia({
role: "presenter",
binding: BINDING,
authenticatedFetch: fetcher,
now: () => NOW,
peerConnectionFactory: () => {
const peer = new FakePeer();
peers.push(peer);
return peer as unknown as RTCPeerConnection;
},
});
await media.startPresenter({
consent: { authorized: true, optedIn: true },
stream: new FakeStream([track]) as unknown as MediaStream,
video: new FakeVideo() as unknown as HTMLVideoElement,
});
await settle();
assert.equal(peers.length, 2);
for (const peer of peers) {
assert.equal(peer.added[0], track as unknown as MediaStreamTrack);
assert.equal(peer.senders[0]?.writes.length, 1);
assert.equal(peer.senders[0]?.writes[0]?.encodings[0]?.maxBitrate, 1_500_000);
assert.equal(peer.senders[0]?.writes[0]?.encodings[0]?.scaleResolutionDownBy, 3);
}
await media.stop();
assert.equal(track.stopped, 0);
assert.equal(track.contentHint, "");
});
it("tears down failed peers and rebuilds them from a resumed participant snapshot", async () => {
const timers = new FakeTimers();
const peers: FakePeer[] = [];