diff --git a/packages/client/src/Call.ts b/packages/client/src/Call.ts index aa16820c1..a2007f758 100644 --- a/packages/client/src/Call.ts +++ b/packages/client/src/Call.ts @@ -92,7 +92,7 @@ import { ReconnectDetails } from './gen/video/sfu/event/events'; import { ClientDetails, Codec, - PublishOptions, + PublishOption, TrackType, WebsocketReconnectStrategy, } from './gen/video/sfu/models/models'; @@ -204,7 +204,7 @@ export class Call { private readonly dispatcher = new Dispatcher(); private clientPublishOptions?: ClientPublishOptions; - private initialPublishOptions?: PublishOptions; + private initialPublishOptions?: PublishOption[]; private statsReporter?: StatsReporter; private sfuStatsReporter?: SfuStatsReporter; private dropTimeout: ReturnType | undefined; @@ -803,7 +803,9 @@ export class Call { clientDetails, fastReconnect: performingFastReconnect, reconnectDetails, - preferredCodec: this.getPreferredCodec(publishingCapabilitiesSdp), + preferredPublishOptions: this.getPreferredCodec( + publishingCapabilitiesSdp, + ), }); this.initialPublishOptions = publishOptions; @@ -836,7 +838,7 @@ export class Call { connectionConfig, clientDetails, statsOptions, - publishOptions: this.initialPublishOptions!, + publishOptions: this.initialPublishOptions || [], closePreviousInstances: !performingMigration, }); } @@ -906,20 +908,25 @@ export class Call { * This is an experimental client feature and subject to change. * @internal */ - private getPreferredCodec = (sdp: string): Codec | undefined => { + private getPreferredCodec = (sdp: string): PublishOption[] => { const { preferredCodec } = this.clientPublishOptions || {}; - if (!preferredCodec) return; + if (!preferredCodec) return []; const codec = findCodec(`video/${preferredCodec}`); - if (!codec) return; + if (!codec) return []; const { clockRate, mimeType, sdpFmtpLine } = codec; - return Codec.create({ - name: preferredCodec, // e.g. 'vp9' - fmtp: sdpFmtpLine || '', - clockRate: clockRate, - payloadType: getPayloadTypeForCodec(sdp, mimeType, sdpFmtpLine), - }); + return [ + PublishOption.create({ + trackType: TrackType.VIDEO, + codec: Codec.create({ + name: preferredCodec, // e.g. 'vp9' + fmtp: sdpFmtpLine || '', + clockRate: clockRate, + payloadType: getPayloadTypeForCodec(sdp, mimeType, sdpFmtpLine), + }), + }), + ]; }; /** @@ -960,7 +967,7 @@ export class Call { connectionConfig: RTCConfiguration; statsOptions: StatsOptions; clientDetails: ClientDetails; - publishOptions: PublishOptions; + publishOptions: PublishOption[]; closePreviousInstances: boolean; }) => { const { diff --git a/packages/client/src/gen/video/sfu/event/events.ts b/packages/client/src/gen/video/sfu/event/events.ts index a51e701c1..4ac6478bf 100644 --- a/packages/client/src/gen/video/sfu/event/events.ts +++ b/packages/client/src/gen/video/sfu/event/events.ts @@ -3,29 +3,25 @@ // @generated from protobuf file "video/sfu/event/events.proto" (package "stream.video.sfu.event", syntax proto3) // tslint:disable import { MessageType } from '@protobuf-ts/runtime'; -import { - CallEndedReason, - CallGrants, - CallState, - ClientDetails, - Codec, - ConnectionQuality, - Error as Error$, - GoAwayReason, - ICETrickle as ICETrickle$, - Participant, - ParticipantCount, - PeerType, - Pin, - PublishOption, - PublishOptions, - TrackInfo, - TrackType, - TrackUnpublishReason, - WebsocketReconnectStrategy, -} from '../models/models'; +import { CallEndedReason } from '../models/models'; +import { GoAwayReason } from '../models/models'; +import { CallGrants } from '../models/models'; +import { Codec } from '../models/models'; +import { ConnectionQuality } from '../models/models'; +import { CallState } from '../models/models'; import { TrackSubscriptionDetails } from '../signal_rpc/signal'; - +import { TrackInfo } from '../models/models'; +import { ClientDetails } from '../models/models'; +import { TrackUnpublishReason } from '../models/models'; +import { Participant } from '../models/models'; +import { TrackType } from '../models/models'; +import { ParticipantCount } from '../models/models'; +import { PeerType } from '../models/models'; +import { WebsocketReconnectStrategy } from '../models/models'; +import { Error as Error$ } from '../models/models'; +import { Pin } from '../models/models'; +import { PublishOption } from '../models/models'; +import { ICETrickle as ICETrickle$ } from '../models/models'; /** * SFUEvent is a message that is sent from the SFU to the client. * @@ -508,9 +504,9 @@ export interface JoinRequest { */ reconnectDetails?: ReconnectDetails; /** - * @generated from protobuf field: stream.video.sfu.models.Codec preferred_codec = 9; + * @generated from protobuf field: repeated stream.video.sfu.models.PublishOption preferred_publish_options = 9; */ - preferredCodec?: Codec; + preferredPublishOptions: PublishOption[]; } /** * @generated from protobuf message stream.video.sfu.event.ReconnectDetails @@ -577,9 +573,9 @@ export interface JoinResponse { */ fastReconnectDeadlineSeconds: number; /** - * @generated from protobuf field: stream.video.sfu.models.PublishOptions publish_options = 4; + * @generated from protobuf field: repeated stream.video.sfu.models.PublishOption publish_options = 4; */ - publishOptions?: PublishOptions; + publishOptions: PublishOption[]; } /** * ParticipantJoined is fired when a user joins a call @@ -1313,7 +1309,13 @@ class JoinRequest$Type extends MessageType { kind: 'message', T: () => ReconnectDetails, }, - { no: 9, name: 'preferred_codec', kind: 'message', T: () => Codec }, + { + no: 9, + name: 'preferred_publish_options', + kind: 'message', + repeat: 1 /*RepeatType.PACKED*/, + T: () => PublishOption, + }, ]); } } @@ -1421,7 +1423,8 @@ class JoinResponse$Type extends MessageType { no: 4, name: 'publish_options', kind: 'message', - T: () => PublishOptions, + repeat: 1 /*RepeatType.PACKED*/, + T: () => PublishOption, }, ]); } diff --git a/packages/client/src/gen/video/sfu/models/models.ts b/packages/client/src/gen/video/sfu/models/models.ts index f8849e39b..a2edbbadc 100644 --- a/packages/client/src/gen/video/sfu/models/models.ts +++ b/packages/client/src/gen/video/sfu/models/models.ts @@ -5,7 +5,6 @@ import { MessageType } from '@protobuf-ts/runtime'; import { Struct } from '../../../google/protobuf/struct'; import { Timestamp } from '../../../google/protobuf/timestamp'; - /** * CallState is the current state of the call * as seen by an SFU. @@ -194,15 +193,6 @@ export interface VideoLayer { */ quality: VideoQuality; } -/** - * @generated from protobuf message stream.video.sfu.models.PublishOptions - */ -export interface PublishOptions { - /** - * @generated from protobuf field: repeated stream.video.sfu.models.PublishOption codecs = 1; - */ - codecs: PublishOption[]; -} /** * @generated from protobuf message stream.video.sfu.models.PublishOption */ @@ -1103,24 +1093,6 @@ class VideoLayer$Type extends MessageType { */ export const VideoLayer = new VideoLayer$Type(); // @generated message type with reflection information, may provide speed optimized methods -class PublishOptions$Type extends MessageType { - constructor() { - super('stream.video.sfu.models.PublishOptions', [ - { - no: 1, - name: 'codecs', - kind: 'message', - repeat: 1 /*RepeatType.PACKED*/, - T: () => PublishOption, - }, - ]); - } -} -/** - * @generated MessageType for protobuf message stream.video.sfu.models.PublishOptions - */ -export const PublishOptions = new PublishOptions$Type(); -// @generated message type with reflection information, may provide speed optimized methods class PublishOption$Type extends MessageType { constructor() { super('stream.video.sfu.models.PublishOption', [ diff --git a/packages/client/src/rtc/Publisher.ts b/packages/client/src/rtc/Publisher.ts index 7765512cd..bfe2f1059 100644 --- a/packages/client/src/rtc/Publisher.ts +++ b/packages/client/src/rtc/Publisher.ts @@ -5,7 +5,6 @@ import { import { PeerType, PublishOption, - PublishOptions, TrackInfo, TrackType, VideoLayer, @@ -25,7 +24,7 @@ import { TargetResolutionResponse } from '../gen/shims'; import { withoutConcurrency } from '../helpers/concurrency'; export type PublisherConstructorOpts = BasePeerConnectionOpts & { - publishOptions: PublishOptions; + publishOptions: PublishOption[]; }; /** @@ -49,7 +48,7 @@ export class Publisher extends BasePeerConnection { private readonly unsubscribeChangePublishOptions: () => void; private unsubscribeCodecNegotiationComplete?: () => void; - private publishOptions: PublishOptions; + private publishOptions: PublishOption[]; /** * Constructs a new `Publisher` instance. @@ -90,11 +89,10 @@ export class Publisher extends BasePeerConnection { ({ publishOption }) => { withoutConcurrency('publisher.changePublishOptions', async () => { if (!publishOption) return; - this.publishOptions.codecs = this.publishOptions.codecs.map( - (option) => - option.trackType === publishOption.trackType - ? publishOption - : option, + this.publishOptions = this.publishOptions.map((option) => + option.trackType === publishOption.trackType + ? publishOption + : option, ); if (this.isPublishing(publishOption.trackType)) { this.switchCodec(publishOption); @@ -539,8 +537,9 @@ export class Publisher extends BasePeerConnection { }; private getPublishOptionFor = (trackType: TrackType) => { - const options = this.publishOptions.codecs; - const publishOption = options.find((o) => o.trackType === trackType); + const publishOption = this.publishOptions.find( + (option) => option.trackType === trackType, + ); if (!publishOption) { throw new Error(`No publish options found for ${TrackType[trackType]}`); }