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

@@ -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);