refactor(voice): remove screen share codec renegotiation (#2417)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-03 04:46:11 +02:00
1 parent f5f60c66e7
commit c97bc53342
80 files changed
+1360 -4726

No files matched your search

@@ -1,70 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {describe, expect, it} from 'vitest';
import {
decodeVoiceEngineV2CodecGossip,
encodeVoiceEngineV2CodecGossip,
VOICE_ENGINE_V2_CODEC_GOSSIP_TOPIC,
} from './codecGossip';
import type {VoiceEngineV2CodecGossipMessage} from './types';
describe('voice engine v2 codec gossip wire protocol', () => {
it('exposes a stable topic', () => {
expect(VOICE_ENGINE_V2_CODEC_GOSSIP_TOPIC).toBe('fluxer.codec.v1');
});
it('round-trips a capability message', () => {
const message: VoiceEngineV2CodecGossipMessage = {
kind: 'codec.capability',
supportedVideoCodecs: ['av1', 'vp9', 'h264', 'vp8'],
};
const decoded = decodeVoiceEngineV2CodecGossip(encodeVoiceEngineV2CodecGossip(message));
expect(decoded).toEqual(message);
});
it('round-trips a viewing message', () => {
const message: VoiceEngineV2CodecGossipMessage = {
kind: 'codec.viewing',
source: 'screen',
watching: true,
supportedVideoCodecs: ['h264', 'vp8'],
};
const decoded = decodeVoiceEngineV2CodecGossip(encodeVoiceEngineV2CodecGossip(message));
expect(decoded).toEqual(message);
});
it('decodes from a raw ArrayBuffer payload', () => {
const bytes = encodeVoiceEngineV2CodecGossip({kind: 'codec.capability', supportedVideoCodecs: ['av1']});
const buffer = new ArrayBuffer(bytes.byteLength);
new Uint8Array(buffer).set(bytes);
expect(decodeVoiceEngineV2CodecGossip(buffer)).toEqual({kind: 'codec.capability', supportedVideoCodecs: ['av1']});
});
it('rejects malformed and adversarial payloads as null', () => {
expect(decodeVoiceEngineV2CodecGossip('not json')).toBeNull();
expect(decodeVoiceEngineV2CodecGossip('123')).toBeNull();
expect(decodeVoiceEngineV2CodecGossip(JSON.stringify({kind: 'other'}))).toBeNull();
expect(decodeVoiceEngineV2CodecGossip(JSON.stringify({kind: 'codec.capability'}))).toBeNull();
expect(
decodeVoiceEngineV2CodecGossip(JSON.stringify({kind: 'codec.capability', supportedVideoCodecs: ['fake']})),
).toBeNull();
expect(
decodeVoiceEngineV2CodecGossip(
JSON.stringify({kind: 'codec.viewing', source: 'mic', watching: true, supportedVideoCodecs: []}),
),
).toBeNull();
expect(
decodeVoiceEngineV2CodecGossip(
JSON.stringify({kind: 'codec.viewing', source: 'camera', watching: 'yes', supportedVideoCodecs: []}),
),
).toBeNull();
});
it('rejects an oversized codec list', () => {
const tooMany = JSON.stringify({
kind: 'codec.capability',
supportedVideoCodecs: ['av1', 'av1', 'av1', 'av1', 'av1', 'av1', 'av1', 'av1', 'av1'],
});
expect(decodeVoiceEngineV2CodecGossip(tooMany)).toBeNull();
});
});
@@ -1,75 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import assert from 'node:assert/strict';
import type {VoiceEngineV2CodecGossipMessage, VoiceEngineV2VideoCodec} from './types';
export const VOICE_ENGINE_V2_CODEC_GOSSIP_TOPIC = 'fluxer.codec.v1';
const KNOWN_VIDEO_CODECS: ReadonlySet<string> = new Set(['', 'vp8', 'vp9', 'h264', 'h265', 'av1']);
const VIDEO_CODECS_CAP = 8;
function isVideoCodec(value: unknown): value is VoiceEngineV2VideoCodec {
return typeof value === 'string' && KNOWN_VIDEO_CODECS.has(value);
}
function normalizeSupportedVideoCodecs(value: unknown): Array<VoiceEngineV2VideoCodec> | null {
if (!Array.isArray(value)) return null;
if (value.length > VIDEO_CODECS_CAP) return null;
const codecs: Array<VoiceEngineV2VideoCodec> = [];
for (const entry of value) {
if (!isVideoCodec(entry)) return null;
codecs.push(entry);
}
return codecs;
}
export function encodeVoiceEngineV2CodecGossip(message: VoiceEngineV2CodecGossipMessage): Uint8Array {
assert.ok(message != null, 'encodeVoiceEngineV2CodecGossip message must not be null');
assert.ok(message.kind === 'codec.capability' || message.kind === 'codec.viewing', 'unknown gossip message kind');
return new TextEncoder().encode(JSON.stringify(message));
}
export function decodeVoiceEngineV2CodecGossip(
payload: ArrayBuffer | ArrayBufferView | string,
): VoiceEngineV2CodecGossipMessage | null {
const text = typeof payload === 'string' ? payload : decodeUtf8(payload);
if (text === null) return null;
let parsed: unknown;
try {
parsed = JSON.parse(text);
} catch {
return null;
}
if (typeof parsed !== 'object' || parsed === null) return null;
const candidate = parsed as Record<string, unknown>;
if (candidate.kind === 'codec.capability') {
const supportedVideoCodecs = normalizeSupportedVideoCodecs(candidate.supportedVideoCodecs);
if (supportedVideoCodecs === null) return null;
return {kind: 'codec.capability', supportedVideoCodecs};
}
if (candidate.kind === 'codec.viewing') {
if (candidate.source !== 'camera' && candidate.source !== 'screen') return null;
if (typeof candidate.watching !== 'boolean') return null;
const supportedVideoCodecs = normalizeSupportedVideoCodecs(candidate.supportedVideoCodecs);
if (supportedVideoCodecs === null) return null;
return {
kind: 'codec.viewing',
source: candidate.source,
watching: candidate.watching,
supportedVideoCodecs,
};
}
return null;
}
function decodeUtf8(payload: ArrayBuffer | ArrayBufferView): string | null {
try {
const view =
payload instanceof ArrayBuffer
? new Uint8Array(payload)
: new Uint8Array(payload.buffer, payload.byteOffset, payload.byteLength);
return new TextDecoder('utf-8', {fatal: false}).decode(view);
} catch {
return null;
}
}
@@ -42,7 +42,6 @@ import type {
VoiceEngineV2InboundVideoTrackSubscription,
VoiceEngineV2LifecycleReason,
VoiceEngineV2LiveKitRoomState,
VoiceEngineV2LocalStreamSource,
VoiceEngineV2MicrophoneOptions,
VoiceEngineV2NativeAudioTapOptions,
VoiceEngineV2NativeCaptureFrame,
@@ -62,7 +61,6 @@ import type {
VoiceEngineV2Stats,
VoiceEngineV2TimerOptions,
VoiceEngineV2Track,
VoiceEngineV2VideoCodec,
VoiceEngineV2WatchedStream,
VoiceEngineV2WatchedStreamKey,
} from './types';
@@ -237,31 +235,6 @@ export type VoiceEngineV2Event =
| {type: 'room.trackUnpublished'; trackSid: string}
| {type: 'room.trackMuted'; trackSid: string}
| {type: 'room.trackUnmuted'; trackSid: string}
| {
type: 'codecNegotiation.overrideSetRequested';
source: VoiceEngineV2LocalStreamSource;
codec: VoiceEngineV2VideoCodec | null;
}
| {type: 'codecNegotiation.localCapabilityChanged'; supportedVideoCodecs: Array<VoiceEngineV2VideoCodec>}
| {
type: 'codecNegotiation.streamRegistered';
source: VoiceEngineV2LocalStreamSource;
streamIdentity: string;
preferredCodec: VoiceEngineV2VideoCodec;
}
| {type: 'codecNegotiation.streamUnregistered'; source: VoiceEngineV2LocalStreamSource}
| {
type: 'codecNegotiation.viewerChanged';
source: VoiceEngineV2LocalStreamSource;
viewerIdentity: string;
watching: boolean;
supportedVideoCodecs: Array<VoiceEngineV2VideoCodec>;
}
| {
type: 'codecNegotiation.remoteCapabilityChanged';
identity: string;
supportedVideoCodecs: Array<VoiceEngineV2VideoCodec>;
}
| {type: 'watchedStream.watchRequested'; stream: VoiceEngineV2WatchedStream}
| {type: 'watchedStream.unwatchRequested'; stream: VoiceEngineV2WatchedStreamKey}
| {type: 'watchedStreams.replaced'; streams: Array<VoiceEngineV2WatchedStream>}
@@ -1,10 +1,5 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export {
decodeVoiceEngineV2CodecGossip,
encodeVoiceEngineV2CodecGossip,
VOICE_ENGINE_V2_CODEC_GOSSIP_TOPIC,
} from './codecGossip';
export type {VoiceEngineV2Command, VoiceEngineV2CommandType} from './commands';
export {getVoiceEngineV2CommandResourceKey, getVoiceEngineV2CommandTypeResourceKey} from './commands';
export type {
@@ -24,9 +19,6 @@ export type {
VoiceEngineV2CameraEncodingOptions,
VoiceEngineV2CameraOptions,
VoiceEngineV2Capabilities,
VoiceEngineV2CodecGossipMessage,
VoiceEngineV2CodecNegotiationState,
VoiceEngineV2CodecStreamNegotiation,
VoiceEngineV2ConnectionModel,
VoiceEngineV2ConnectionQuality,
VoiceEngineV2ConnectionStatus,
@@ -86,7 +78,6 @@ export type {
VoiceEngineV2SendStats,
VoiceEngineV2Stats,
VoiceEngineV2StatsSample,
VoiceEngineV2StreamNegotiationProjection,
VoiceEngineV2TimerOptions,
VoiceEngineV2Track,
VoiceEngineV2TrackKind,
@@ -676,41 +676,6 @@ export interface VoiceEngineV2WatchedStreamKey {
export type VoiceEngineV2LocalStreamSource = 'camera' | 'screen';
export interface VoiceEngineV2CodecStreamNegotiation {
source: VoiceEngineV2LocalStreamSource;
streamIdentity: string;
preferredCodec: VoiceEngineV2VideoCodec;
negotiatedCodec: VoiceEngineV2VideoCodec;
constrainedBy: string | null;
viewers: Record<string, VoiceEngineV2VideoCodec | null>;
}
export interface VoiceEngineV2CodecNegotiationState {
overrides: Partial<Record<VoiceEngineV2LocalStreamSource, VoiceEngineV2VideoCodec>>;
localSupportedVideoCodecs: Array<VoiceEngineV2VideoCodec>;
remoteSupportedVideoCodecs: Record<string, Array<VoiceEngineV2VideoCodec>>;
streams: Record<string, VoiceEngineV2CodecStreamNegotiation>;
}
export interface VoiceEngineV2StreamNegotiationProjection {
source: VoiceEngineV2LocalStreamSource;
streamIdentity: string;
negotiatedCodec: VoiceEngineV2VideoCodec;
preferredCodec: VoiceEngineV2VideoCodec;
constrainedBy: string | null;
renegotiating: boolean;
viewerCount: number;
}
export type VoiceEngineV2CodecGossipMessage =
| {kind: 'codec.capability'; supportedVideoCodecs: Array<VoiceEngineV2VideoCodec>}
| {
kind: 'codec.viewing';
source: VoiceEngineV2LocalStreamSource;
watching: boolean;
supportedVideoCodecs: Array<VoiceEngineV2VideoCodec>;
};
export interface VoiceEngineV2InboundVideoTrackSubscription {
participantSid: string;
participantIdentity?: string;