fix(voice): keep published codecs inside the opt-in policy (#2422)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-03 15:06:48 +02:00
1 parent 2426a5769d
commit 902dd60ff9
51 files changed
+1032 -313

No files matched your search

+7 -2
View File
@@ -44,9 +44,14 @@ source edits in this package.
OpenH264 software profile.
8. **Media publishing defaults** (`src/room/defaults.ts`, `src/room/utils.ts`, `src/room/track/options.ts`)
Prefers AV1, then HEVC/H.265, H.264, VP9, and VP8 according to actual
sender capabilities; pairs advanced codecs with H.264 backup simulcast; and
Falls back to H.264, then VP9, VP8, AV1, and HEVC/H.265 according to actual
sender capabilities, pairs advanced codecs with H.264 backup simulcast, and
uses maintain-resolution screen-share defaults with a 4K60-ready bitrate cap.
The order puts AV1 and HEVC last because both are opt-in in Fluxer, so a
fallback inside `publishTrack` must not land on a codec the user did not
enable. Fluxer picks the codec itself before publishing, so this list only
applies when the client overrides the request, such as the reconnect
republish that runs outside Fluxer's own flows.
9. **High-fidelity Opus SDP munging** (`src/room/PCTransport.ts`)
Forces Opus RED/FEC, stereo signaling, 10 ms packet time, no DTX, and a
@@ -4,12 +4,13 @@
import {describe, expect, it} from 'vitest';
import {defaultVideoCodec, publishDefaults, roomOptionDefaults} from './defaults.ts';
import {BackupCodecPolicy} from './track/options.ts';
import {selectPreferredVideoCodec} from './utils.ts';
describe('Fluxer media publish defaults', () => {
it('defaults new video publishes to the advanced codec path with H.264 backup', () => {
expect(defaultVideoCodec).toBe('av1');
it('defaults new video publishes to an opt-in-safe codec with H.264 backup', () => {
expect(defaultVideoCodec).toBe('h264');
expect(publishDefaults).toMatchObject({
videoCodec: 'av1',
videoCodec: 'h264',
backupCodec: {codec: 'h264'},
backupCodecPolicy: BackupCodecPolicy.SIMULCAST,
degradationPreference: 'maintain-resolution',
@@ -18,6 +19,12 @@ describe('Fluxer media publish defaults', () => {
});
});
it('falls back away from the opt-in codecs before reaching them', () => {
expect(selectPreferredVideoCodec()).toBe('h264');
expect(selectPreferredVideoCodec()).not.toBe('av1');
expect(selectPreferredVideoCodec()).not.toBe('h265');
});
it('keeps original screen-share publishing at a 4K60-ready transport ceiling', () => {
expect(publishDefaults.screenShareEncoding).toMatchObject({
maxBitrate: 20_000_000,
@@ -6,7 +6,7 @@ import DefaultReconnectPolicy from './DefaultReconnectPolicy.ts';
import type {AudioCaptureOptions, TrackPublishDefaults, VideoCaptureOptions} from './track/options.ts';
import {AudioPresets, BackupCodecPolicy, ScreenSharePresets, VideoPresets} from './track/options.ts';
export const defaultVideoCodec = 'av1';
export const defaultVideoCodec = 'h264';
export const publishDefaults: TrackPublishDefaults = {
audioPreset: AudioPresets.music,
@@ -45,12 +45,19 @@ describe('video codec capability helpers', () => {
});
});
it('uses the advanced publish ladder from real sender capabilities', () => {
it('keeps the opt-in codecs last even when sender capabilities offer them', () => {
setSenderCapabilities(['video/VP8', 'video/H264', 'video/VP9', 'video/H265', 'video/AV1']);
expect(supportsAV1()).toBe(true);
expect(supportsH265()).toBe(true);
expect(supportsVP9()).toBe(true);
expect(selectPreferredVideoCodec()).toBe('av1');
expect(selectPreferredVideoCodec()).toBe('h264');
});
it('falls back to VP9 then VP8 before any opt-in codec', () => {
setSenderCapabilities(['video/VP8', 'video/VP9', 'video/H265', 'video/AV1']);
expect(selectPreferredVideoCodec()).toBe('vp9');
setSenderCapabilities(['video/VP8', 'video/H265', 'video/AV1']);
expect(selectPreferredVideoCodec()).toBe('vp8');
});
it('treats legacy AV1X as AV1 and falls through to HEVC when AV1 is absent', () => {
@@ -32,7 +32,7 @@ import type {ChatMessage, LiveKitReactNativeInfo, TranscriptionSegment} from './
const separator = '|';
export const ddExtensionURI = 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension';
const preferredPublishVideoCodecs: ReadonlyArray<VideoCodec> = ['av1', 'h265', 'h264', 'vp9', 'vp8'];
const preferredPublishVideoCodecs: ReadonlyArray<VideoCodec> = ['h264', 'vp9', 'vp8', 'av1', 'h265'];
export function unpackStreamId(packed: string): Array<string> {
const parts = packed.split(separator);