@livedigital/client 3.48.0 → 3.49.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/constants/encodings.d.ts +3 -3
- package/dist/constants/encodings.ts +3 -3
- package/dist/engine/handlers/ChannelAudioObserverEventHandler.d.ts +3 -1
- package/dist/engine/handlers/ChannelAudioObserverMissingProducerRestorer.d.ts +10 -0
- package/dist/engine/handlers/MediaEventHandler.d.ts +0 -1
- package/dist/engine/index.d.ts +7 -4
- package/dist/engine/network/DatachannelHeartbeater.d.ts +2 -2
- package/dist/engine/network/NetworkTransportPolicyManager.d.ts +22 -0
- package/dist/engine/network/index.d.ts +10 -8
- package/dist/index.d.ts +2 -0
- package/dist/index.es.js +2 -2
- package/dist/index.js +2 -2
- package/dist/inversify.tokens.d.ts +3 -1
- package/dist/types/network.d.ts +6 -6
- package/package.json +2 -3
- package/src/ClientMetaProvider.ts +0 -41
- package/src/EnhancedEventEmitter.ts +0 -75
- package/src/config/ConfigService.ts +0 -66
- package/src/constants/common.ts +0 -85
- package/src/constants/encodings.ts +0 -26
- package/src/constants/events.ts +0 -126
- package/src/constants/mutex.ts +0 -6
- package/src/constants/stats.ts +0 -1
- package/src/constants/videoConstrains.ts +0 -21
- package/src/engine/CallState.ts +0 -19
- package/src/engine/ChannelStateSynchronizer/ChannelStateSynchronizer.ts +0 -448
- package/src/engine/ChannelStateSynchronizer/types.ts +0 -22
- package/src/engine/EventsQueue.ts +0 -255
- package/src/engine/IntegrationsService.ts +0 -163
- package/src/engine/LocalMutex.ts +0 -45
- package/src/engine/Logger.ts +0 -234
- package/src/engine/MyPeer.ts +0 -25
- package/src/engine/Peer.ts +0 -602
- package/src/engine/PeerConsumer.ts +0 -276
- package/src/engine/PeerProducer.ts +0 -50
- package/src/engine/Peers.ts +0 -150
- package/src/engine/PeersStorage.ts +0 -45
- package/src/engine/RemotePeerTracks.ts +0 -73
- package/src/engine/WIDHandler.ts +0 -166
- package/src/engine/WebRTCStats/ConnectionStatsManager.ts +0 -31
- package/src/engine/WebRTCStats/InboundTrackStatsManager.ts +0 -51
- package/src/engine/WebRTCStats/OutboudTrackStatsManager.ts +0 -51
- package/src/engine/WebRTCStats/StatsHandler.ts +0 -80
- package/src/engine/WebRTCStats/TransportsStatsProvider.ts +0 -123
- package/src/engine/WebRTCStats/types.ts +0 -20
- package/src/engine/analyticsApiClient/LogApi.ts +0 -24
- package/src/engine/analyticsApiClient/MetricsApi.ts +0 -30
- package/src/engine/analyticsApiClient/helper.ts +0 -88
- package/src/engine/analyticsApiClient/index.ts +0 -42
- package/src/engine/analyticsApiClient/types.ts +0 -33
- package/src/engine/handlers/ChannelAudioObserverEventHandler.ts +0 -177
- package/src/engine/handlers/ChannelEventHandler.ts +0 -268
- package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyCheckResult.ts +0 -31
- package/src/engine/handlers/ChannelStateSyncEventHandler/ChannelStateConsistencyChecker.ts +0 -146
- package/src/engine/handlers/ChannelStateSyncEventHandler/consts.ts +0 -7
- package/src/engine/handlers/ChannelStateSyncEventHandler/index.ts +0 -342
- package/src/engine/handlers/ChannelStateSyncEventHandler/types.ts +0 -21
- package/src/engine/handlers/MediaEventHandler.ts +0 -273
- package/src/engine/index.ts +0 -793
- package/src/engine/media/index.ts +0 -574
- package/src/engine/media/producer/PendingClosureProducerStorage.ts +0 -37
- package/src/engine/media/producer/ProducerCloseManager.ts +0 -115
- package/src/engine/media/streamEffects/ProcessorsCache.ts +0 -41
- package/src/engine/media/streamEffects/audio/AudioTrackProcessor.ts +0 -7
- package/src/engine/media/streamEffects/audio/asdk/ASDKTrackProcessor.ts +0 -275
- package/src/engine/media/streamEffects/audio/asdk/atsrb.d.ts +0 -36
- package/src/engine/media/streamEffects/audio/asdk/errorBus.d.ts +0 -47
- package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionAudioWorkletNode.ts +0 -35
- package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionNodeProvider.ts +0 -44
- package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionScriptProcessorNode.ts +0 -69
- package/src/engine/media/streamEffects/audio/noiseSuppression/RNNoiseTrackProcessor.ts +0 -134
- package/src/engine/media/streamEffects/audio/noiseSuppression/WasmModuleCompiler.ts +0 -9
- package/src/engine/media/streamEffects/video/esdk/TrackProcessor.ts +0 -386
- package/src/engine/media/streamEffects/video/esdk/components/component.d.ts +0 -35
- package/src/engine/media/streamEffects/video/esdk/components/countdown/countdown.d.ts +0 -27
- package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/doubleSlideRect.d.ts +0 -33
- package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/horizontalMirror.d.ts +0 -29
- package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/leftTextbox.d.ts +0 -31
- package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/slideBold.d.ts +0 -41
- package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/animatedBox.d.ts +0 -59
- package/src/engine/media/streamEffects/video/esdk/components/lower-third/collection/twoSideRects/twoSlideRects.d.ts +0 -27
- package/src/engine/media/streamEffects/video/esdk/components/lower-third/lowerThird.d.ts +0 -83
- package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlayScreen.d.ts +0 -40
- package/src/engine/media/streamEffects/video/esdk/components/overlay-screen/overlaySprite.d.ts +0 -10
- package/src/engine/media/streamEffects/video/esdk/components/stickers/stickerSprite.d.ts +0 -51
- package/src/engine/media/streamEffects/video/esdk/components/stickers/stickers.d.ts +0 -54
- package/src/engine/media/streamEffects/video/esdk/components/utils/positionHelper.d.ts +0 -14
- package/src/engine/media/streamEffects/video/esdk/components/waterMark/waterMark.d.ts +0 -20
- package/src/engine/media/streamEffects/video/esdk/tsvb.d.ts +0 -187
- package/src/engine/media/streamEffects/video/esdk/utils/errorBus.d.ts +0 -42
- package/src/engine/media/tracks/DefaultAudioTrack.ts +0 -178
- package/src/engine/media/tracks/DefaultBaseTrack.ts +0 -592
- package/src/engine/media/tracks/DefaultVideoTrack.ts +0 -301
- package/src/engine/media/tracks/MediaStreamTrackManager.ts +0 -50
- package/src/engine/media/tracks/PeerTrack.ts +0 -558
- package/src/engine/network/DataChannelsManager.ts +0 -164
- package/src/engine/network/DatachannelHeartbeater.ts +0 -122
- package/src/engine/network/SignalingHeartbeater.ts +0 -55
- package/src/engine/network/index.ts +0 -961
- package/src/engine/signalingApiClient/SignalingApiClient.ts +0 -95
- package/src/engine/signalingApiClient/api.ts +0 -2289
- package/src/engine/system/index.ts +0 -221
- package/src/errors/AlreadyConnectedError.ts +0 -11
- package/src/errors/AlreadyCreatedError.ts +0 -11
- package/src/errors/ForbiddenError.ts +0 -11
- package/src/errors/InvalidPayloadError.ts +0 -11
- package/src/errors/InvalidRequestError.ts +0 -11
- package/src/errors/LivedigitalSDKError.ts +0 -15
- package/src/errors/NeedJoinFirstError.ts +0 -11
- package/src/errors/NotFoundError.ts +0 -11
- package/src/errors/OperationError.ts +0 -47
- package/src/errors/RequestError.ts +0 -11
- package/src/errors/TimeoutError.ts +0 -11
- package/src/errors/TooManyRequestsError.ts +0 -11
- package/src/errors/UnauthorizedError.ts +0 -11
- package/src/errors/UnsupportedError.ts +0 -15
- package/src/errors/signalingApiErrorMapper.ts +0 -143
- package/src/helpers/appDataValidator.ts +0 -21
- package/src/helpers/browser.ts +0 -37
- package/src/helpers/channelMessageConverter.ts +0 -124
- package/src/helpers/common.ts +0 -96
- package/src/helpers/datetime.ts +0 -11
- package/src/helpers/errors.ts +0 -25
- package/src/helpers/filterStatsCodecs.ts +0 -3
- package/src/helpers/loader.ts +0 -59
- package/src/helpers/media.ts +0 -57
- package/src/helpers/peer.ts +0 -19
- package/src/helpers/randomString.ts +0 -18
- package/src/helpers/retry.ts +0 -74
- package/src/index.ts +0 -171
- package/src/inversify.config.ts +0 -333
- package/src/inversify.factories.ts +0 -191
- package/src/inversify.tokens.ts +0 -42
- package/src/proto/.gitkeep +0 -0
- package/src/proto/generated/channel/channel_activity_confirmation_time.ts +0 -110
- package/src/proto/generated/channel/channel_management_event.ts +0 -213
- package/src/proto/generated/channel/channel_produce_permissions.ts +0 -171
- package/src/proto/generated/channel/channel_state.ts +0 -94
- package/src/proto/generated/channel/channel_state_short.ts +0 -282
- package/src/proto/generated/channel_message/channel_event.ts +0 -401
- package/src/proto/generated/channel_message/channel_message.ts +0 -139
- package/src/proto/generated/channel_message/media_event.ts +0 -290
- package/src/proto/generated/consumer/consumer.ts +0 -167
- package/src/proto/generated/google/protobuf/struct.ts +0 -588
- package/src/proto/generated/google/protobuf/timestamp.ts +0 -229
- package/src/proto/generated/peer/peer.ts +0 -430
- package/src/proto/generated/peer/peer_group.ts +0 -48
- package/src/proto/generated/peer/peer_role.ts +0 -48
- package/src/proto/generated/producer/producer.ts +0 -204
- package/src/proto/generated/producer/producer_kind.ts +0 -48
- package/src/proto/generated/producer/producer_label.ts +0 -78
- package/src/proto/generated/producer/producer_spatial_layer_request.ts +0 -116
- package/src/proto/generated/transport/transport_connection_timeout.ts +0 -156
- package/src/proto/generated/transport/transport_connection_timeout_reason.ts +0 -48
- package/src/proto/generated/transport/transport_direction.ts +0 -48
- package/src/types/channelAudioObserver.ts +0 -34
- package/src/types/channelStateSyncronizer.ts +0 -22
- package/src/types/client.ts +0 -27
- package/src/types/common.ts +0 -399
- package/src/types/container.ts +0 -31
- package/src/types/engine.ts +0 -97
- package/src/types/media.ts +0 -146
- package/src/types/mediasoup.ts +0 -10
- package/src/types/network.ts +0 -10
- package/src/types/streamEffects.ts +0 -23
|
@@ -1,592 +0,0 @@
|
|
|
1
|
-
import type { types } from 'mediasoup-client';
|
|
2
|
-
import { serializeError } from 'serialize-error';
|
|
3
|
-
import type { ParsedOutboundAudioStreamStats, ParsedOutboundVideoStreamStats } from 'webrtc-issue-detector';
|
|
4
|
-
import type Media from '..';
|
|
5
|
-
import { INTERNAL_CLIENT_EVENTS } from '../../../constants/events';
|
|
6
|
-
import EnhancedEventEmitter from '../../../EnhancedEventEmitter';
|
|
7
|
-
import OperationError from '../../../errors/OperationError';
|
|
8
|
-
import filterStatsCodecs from '../../../helpers/filterStatsCodecs';
|
|
9
|
-
import { isVp9 } from '../../../helpers/media';
|
|
10
|
-
import {
|
|
11
|
-
type BaseTrackInfo,
|
|
12
|
-
type EncoderConfig,
|
|
13
|
-
type PrepareProducerEncodingsParams,
|
|
14
|
-
TrackLabel,
|
|
15
|
-
type TrackOutboundStats,
|
|
16
|
-
type TrackProduceParams,
|
|
17
|
-
} from '../../../types/common';
|
|
18
|
-
import type { InternalObserverEvents } from '../../../types/engine';
|
|
19
|
-
import type {
|
|
20
|
-
BaseTrack, BaseTrackDependenciesParams, BaseTrackParams, ProducerAppData,
|
|
21
|
-
} from '../../../types/media';
|
|
22
|
-
import type Logger from '../../Logger';
|
|
23
|
-
import type { MyPeer } from '../../MyPeer';
|
|
24
|
-
import type Network from '../../network';
|
|
25
|
-
import OutboundTrackStatsManager from '../../WebRTCStats/OutboudTrackStatsManager';
|
|
26
|
-
import type StatsHandler from '../../WebRTCStats/StatsHandler';
|
|
27
|
-
import type MediaStreamTrackManager from './MediaStreamTrackManager';
|
|
28
|
-
import type LocalMutex from '../../LocalMutex';
|
|
29
|
-
import { MutexKey } from '../../../constants/mutex';
|
|
30
|
-
import type ProducerCloseManager from '../producer/ProducerCloseManager';
|
|
31
|
-
|
|
32
|
-
type BaseTrackConstructorParams = BaseTrackParams & BaseTrackDependenciesParams;
|
|
33
|
-
|
|
34
|
-
export interface LoggerContext {
|
|
35
|
-
label: TrackLabel;
|
|
36
|
-
id: string;
|
|
37
|
-
kind: types.MediaKind;
|
|
38
|
-
producerId: string | undefined;
|
|
39
|
-
paused: boolean;
|
|
40
|
-
published: boolean;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const STATS_MAX_ATTEMPTS = 5;
|
|
44
|
-
const STATS_ATTEMPT_DELAY = 150;
|
|
45
|
-
|
|
46
|
-
class DefaultBaseTrack implements BaseTrack {
|
|
47
|
-
#mediaStreamTrack: MediaStreamTrack;
|
|
48
|
-
|
|
49
|
-
#originalTrack?: MediaStreamTrack;
|
|
50
|
-
|
|
51
|
-
protected encoderConfig: EncoderConfig = {};
|
|
52
|
-
|
|
53
|
-
private producer?: types.Producer<ProducerAppData>;
|
|
54
|
-
|
|
55
|
-
private label: TrackLabel = TrackLabel.Unknown;
|
|
56
|
-
|
|
57
|
-
readonly #myPeer: MyPeer;
|
|
58
|
-
|
|
59
|
-
readonly #media: Media;
|
|
60
|
-
|
|
61
|
-
readonly #network: Network;
|
|
62
|
-
|
|
63
|
-
readonly #producerCloseManager: ProducerCloseManager;
|
|
64
|
-
|
|
65
|
-
readonly logger: Logger;
|
|
66
|
-
|
|
67
|
-
readonly #internalEventEmitter: EnhancedEventEmitter<InternalObserverEvents>;
|
|
68
|
-
|
|
69
|
-
readonly #constraints: MediaStreamConstraints;
|
|
70
|
-
|
|
71
|
-
readonly #mediaStreamTrackManager: MediaStreamTrackManager;
|
|
72
|
-
|
|
73
|
-
readonly #eventEmitter: EnhancedEventEmitter;
|
|
74
|
-
|
|
75
|
-
#stopTrackOnPause = true;
|
|
76
|
-
|
|
77
|
-
readonly #mutex: LocalMutex;
|
|
78
|
-
|
|
79
|
-
#webrtcStatsManager: OutboundTrackStatsManager;
|
|
80
|
-
|
|
81
|
-
readonly #statsHandler: StatsHandler;
|
|
82
|
-
|
|
83
|
-
constructor(params: BaseTrackConstructorParams) {
|
|
84
|
-
const {
|
|
85
|
-
mediaStreamTrack,
|
|
86
|
-
internalEventEmitter,
|
|
87
|
-
constraints,
|
|
88
|
-
mediaStreamTrackManager,
|
|
89
|
-
media,
|
|
90
|
-
myPeer,
|
|
91
|
-
network,
|
|
92
|
-
producerCloseManager,
|
|
93
|
-
mutex,
|
|
94
|
-
loggerFactory,
|
|
95
|
-
loggerNamespace,
|
|
96
|
-
statsHandler,
|
|
97
|
-
} = params;
|
|
98
|
-
this.#mediaStreamTrack = mediaStreamTrack;
|
|
99
|
-
this.#internalEventEmitter = internalEventEmitter;
|
|
100
|
-
this.#constraints = constraints;
|
|
101
|
-
this.#mediaStreamTrackManager = mediaStreamTrackManager;
|
|
102
|
-
this.#eventEmitter = new EnhancedEventEmitter();
|
|
103
|
-
this.logger = loggerFactory(loggerNamespace);
|
|
104
|
-
this.#mutex = mutex;
|
|
105
|
-
this.#media = media;
|
|
106
|
-
this.#myPeer = myPeer;
|
|
107
|
-
this.#network = network;
|
|
108
|
-
this.#producerCloseManager = producerCloseManager;
|
|
109
|
-
this.#statsHandler = statsHandler;
|
|
110
|
-
this.#webrtcStatsManager = new OutboundTrackStatsManager({
|
|
111
|
-
track: mediaStreamTrack,
|
|
112
|
-
statsHandler,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
get videoWebRTCStats(): ParsedOutboundVideoStreamStats | undefined {
|
|
117
|
-
return this.#webrtcStatsManager.videoWebRTCStats;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
get audioWebRTCStats(): ParsedOutboundAudioStreamStats | undefined {
|
|
121
|
-
return this.#webrtcStatsManager.audioWebRTCStats;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
get logCtx(): LoggerContext {
|
|
125
|
-
return {
|
|
126
|
-
label: this.getLabel(),
|
|
127
|
-
id: this.id,
|
|
128
|
-
kind: this.kind,
|
|
129
|
-
producerId: this.producerId,
|
|
130
|
-
paused: this.isPaused,
|
|
131
|
-
published: this.isPublished,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
get observer(): EnhancedEventEmitter {
|
|
136
|
-
return this.#eventEmitter;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
get mediaStreamTrack(): MediaStreamTrack {
|
|
140
|
-
return this.#mediaStreamTrack;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
get originalTrack(): MediaStreamTrack | undefined {
|
|
144
|
-
return this.#originalTrack;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
get id(): string {
|
|
148
|
-
return this.mediaStreamTrack.id;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
get kind(): types.MediaKind {
|
|
152
|
-
return this.mediaStreamTrack.kind as types.MediaKind;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
get producerId(): string | undefined {
|
|
156
|
-
return this.producer?.id;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
get isPublished(): boolean {
|
|
160
|
-
return this.producer
|
|
161
|
-
? !this.producer.closed
|
|
162
|
-
: false;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
get isPaused(): boolean {
|
|
166
|
-
return this.producer?.paused ?? false;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
get internalEventEmitter(): EnhancedEventEmitter<InternalObserverEvents> {
|
|
170
|
-
return this.#internalEventEmitter;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
getLabel(): TrackLabel {
|
|
174
|
-
return this.label;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
setLabel(label: TrackLabel): void {
|
|
178
|
-
this.label = label;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
setEncoderConfig(encoderConfig: EncoderConfig): void {
|
|
182
|
-
this.encoderConfig = encoderConfig;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
getEncoderConfig(): EncoderConfig {
|
|
186
|
-
return this.encoderConfig;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
setProducer(producer: types.Producer): void {
|
|
190
|
-
this.producer = producer as types.Producer<ProducerAppData>;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
setStopTrackOnPause(value: boolean): void {
|
|
194
|
-
if (this.isPublished) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
this.#stopTrackOnPause = value;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
getProducer(): types.Producer | undefined {
|
|
202
|
-
return this.producer;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
protected setOriginalTrack(): void {
|
|
206
|
-
this.#originalTrack = this.mediaStreamTrack;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async closeProducer(stopTrack = true): Promise<void> {
|
|
210
|
-
const release = await this.#mutex.lock(MutexKey.CloseProducer);
|
|
211
|
-
|
|
212
|
-
if (!this.producer) {
|
|
213
|
-
release();
|
|
214
|
-
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const { producerId } = this;
|
|
219
|
-
|
|
220
|
-
if (producerId) {
|
|
221
|
-
await this.#producerCloseManager.close(this.getLabel(), producerId);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
this.producer.close();
|
|
225
|
-
this.producer = undefined;
|
|
226
|
-
|
|
227
|
-
if (stopTrack) {
|
|
228
|
-
this.stopMediaStreamTrack();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
release();
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
async setPriority(priority: RTCPriorityType): Promise<void> {
|
|
235
|
-
if (!this.producer) {
|
|
236
|
-
this.logger.warn('setPriority()', {
|
|
237
|
-
priority,
|
|
238
|
-
reason: 'Not published yet',
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
await this.producer.setRtpEncodingParameters({ priority });
|
|
245
|
-
this.logger.debug('setPriority()', {
|
|
246
|
-
label: this.getLabel(),
|
|
247
|
-
priority,
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
stopMediaStreamTrack(): void {
|
|
252
|
-
this.mediaStreamTrack.stop();
|
|
253
|
-
this.mediaStreamTrack.dispatchEvent(new Event('ended'));
|
|
254
|
-
this.stopOriginalTrack();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
protected stopOriginalTrack(): void {
|
|
258
|
-
if (this.#originalTrack) {
|
|
259
|
-
this.#originalTrack.stop();
|
|
260
|
-
this.#originalTrack = undefined;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
async produce({
|
|
265
|
-
encodings,
|
|
266
|
-
codecOptions,
|
|
267
|
-
preferredCodec,
|
|
268
|
-
transformParams,
|
|
269
|
-
keyFrameRequestDelay,
|
|
270
|
-
}: TrackProduceParams): Promise<void> {
|
|
271
|
-
if (!this.#myPeer.canPublish) {
|
|
272
|
-
this.logger.error('produce()', { message: 'Not enough access to produce' });
|
|
273
|
-
throw new OperationError('not_enough_access', new Error('Not enough access to produce'));
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (this.producer) {
|
|
277
|
-
throw new OperationError('track_already_produced', new Error('Track already produced'));
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
try {
|
|
281
|
-
await this.#producerCloseManager.ensureNoPending(this.getLabel());
|
|
282
|
-
|
|
283
|
-
// if you perform transport.produce while you switching to VPN,
|
|
284
|
-
// it will cause an irreversible failure in the formation m-section of the SDP. Mediasoup bug?
|
|
285
|
-
// TODO: find a solution to the problem
|
|
286
|
-
await this.#network.ping();
|
|
287
|
-
|
|
288
|
-
const { rtpCapabilities: { codecs } } = this.#media.mediasoupDevice;
|
|
289
|
-
const codec = codecs?.find((c) => c.mimeType.toLowerCase() === `${ this.kind }/${ preferredCodec }`);
|
|
290
|
-
const maxSpatialLayer = 0;
|
|
291
|
-
// We start with max layer if possible and then reduce to proper layer (to have ability to calc max layer)
|
|
292
|
-
const preparedEncodings = this.prepareProducerEncodings({
|
|
293
|
-
codec,
|
|
294
|
-
encodings: encodings ?? [],
|
|
295
|
-
maxSpatialLayer: (encodings ?? []).length - 1,
|
|
296
|
-
});
|
|
297
|
-
const appData: ProducerAppData = {
|
|
298
|
-
trackTransformParams: transformParams,
|
|
299
|
-
peerId: String(this.#myPeer.id),
|
|
300
|
-
label: this.getLabel(),
|
|
301
|
-
maxSpatialLayer,
|
|
302
|
-
encodings: preparedEncodings,
|
|
303
|
-
codecOptions,
|
|
304
|
-
preferredCodec,
|
|
305
|
-
codec,
|
|
306
|
-
keyFrameRequestDelay,
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
const producer = await this.#network.sendTransport?.produce<ProducerAppData>({
|
|
310
|
-
track: this.mediaStreamTrack,
|
|
311
|
-
encodings: preparedEncodings,
|
|
312
|
-
codecOptions,
|
|
313
|
-
codec,
|
|
314
|
-
stopTracks: false,
|
|
315
|
-
disableTrackOnPause: true,
|
|
316
|
-
zeroRtpOnPause: true,
|
|
317
|
-
appData,
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
if (!producer) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const sender = producer.rtpSender;
|
|
325
|
-
const isSafari = (): boolean => /Safari/i.test(navigator.userAgent);
|
|
326
|
-
|
|
327
|
-
if (encodings && sender && isSafari()) {
|
|
328
|
-
const params = sender.getParameters();
|
|
329
|
-
encodings.forEach(({ maxBitrate, scaleResolutionDownBy }, index) => {
|
|
330
|
-
if (params.encodings[index]) {
|
|
331
|
-
params.encodings[index].maxBitrate = maxBitrate;
|
|
332
|
-
params.encodings[index].scaleResolutionDownBy = scaleResolutionDownBy;
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
await sender.setParameters(params);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
this.setProducer(producer);
|
|
340
|
-
|
|
341
|
-
if ((this.producer as unknown as types.Producer<ProducerAppData>)?.track?.id !== this.#mediaStreamTrack.id) {
|
|
342
|
-
this.logger.info('Producer initialized with old track, updating', {
|
|
343
|
-
oldTrackId: (this.producer as unknown as types.Producer<ProducerAppData>)?.track?.id,
|
|
344
|
-
newTrackId: this.#mediaStreamTrack.id,
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
await this.replaceTrack(this.#mediaStreamTrack);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
if (this.kind === 'video') {
|
|
351
|
-
if (encodings && sender && codec && isVp9(codec.mimeType) && !isSafari()) {
|
|
352
|
-
await sender.setParameters({
|
|
353
|
-
...sender.getParameters(),
|
|
354
|
-
encodings: this.prepareProducerEncodings({ encodings, codec, maxSpatialLayer }),
|
|
355
|
-
});
|
|
356
|
-
} else {
|
|
357
|
-
await producer.setMaxSpatialLayer(maxSpatialLayer);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
await this.#network.setProducerMaxSpatialLayer(producer.id, maxSpatialLayer);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (this.kind === 'audio') {
|
|
364
|
-
await this.setPriority('high');
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
this.logger.debug('produce()', { track: this.logCtx, encodings, codecOptions });
|
|
368
|
-
} catch (error) {
|
|
369
|
-
this.logger.error('produce()', { error, track: this.logCtx });
|
|
370
|
-
throw new OperationError('track_publish_failed', error);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
async publish(): Promise<void> {
|
|
375
|
-
await this.produce({});
|
|
376
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackProduced, this);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
async unpublish(stopTrack = true): Promise<void> {
|
|
380
|
-
try {
|
|
381
|
-
if (stopTrack) {
|
|
382
|
-
this.stopMediaStreamTrack();
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackUnproduced, this);
|
|
386
|
-
|
|
387
|
-
if (this.producer) {
|
|
388
|
-
await this.closeProducer();
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
this.logger.debug('unpublish()', { track: this.logCtx });
|
|
392
|
-
} catch (error) {
|
|
393
|
-
this.logger.error('unpublish()', { error });
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
private async pauseRemoteProducer(producerId: string): Promise<void> {
|
|
398
|
-
await this.#network.pauseRemoteProducer(producerId);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
private async resumeRemoteProducer(producerId: string): Promise<void> {
|
|
402
|
-
await this.#network.resumeRemoteProducer(producerId);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
protected async mute(stopTrackOnPauseCallback?: () => void): Promise<void> {
|
|
406
|
-
const release = await this.#mutex.lock(MutexKey.Mute);
|
|
407
|
-
|
|
408
|
-
if (!this.producer) {
|
|
409
|
-
this.logger.warn('pause()', { message: 'Track is not published', track: this.logCtx });
|
|
410
|
-
release();
|
|
411
|
-
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
try {
|
|
416
|
-
this.producer.pause();
|
|
417
|
-
this.logger.debug('pause()', { track: this.logCtx });
|
|
418
|
-
|
|
419
|
-
if (this.#stopTrackOnPause) {
|
|
420
|
-
stopTrackOnPauseCallback?.();
|
|
421
|
-
this.#mediaStreamTrack.stop();
|
|
422
|
-
this.stopOriginalTrack();
|
|
423
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackClosed, this);
|
|
424
|
-
await this.pauseRemoteProducer(this.producer.id);
|
|
425
|
-
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
await this.pauseRemoteProducer(this.producer.id);
|
|
430
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackPaused, this);
|
|
431
|
-
} catch (error) {
|
|
432
|
-
this.logger.error('pause()', { error, track: this.logCtx });
|
|
433
|
-
await this.#media.deleteTrack(this);
|
|
434
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackFailed, this);
|
|
435
|
-
throw new OperationError('track_pause_failed', error);
|
|
436
|
-
} finally {
|
|
437
|
-
release();
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
public async resume(): Promise<void> {
|
|
442
|
-
const release = await this.#mutex.lock(MutexKey.Resume);
|
|
443
|
-
|
|
444
|
-
if (!this.producer) {
|
|
445
|
-
this.logger.warn('resume()', { message: 'Track is not published', track: this.logCtx });
|
|
446
|
-
release();
|
|
447
|
-
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
try {
|
|
452
|
-
this.logger.debug('resume()', { track: this.logCtx });
|
|
453
|
-
|
|
454
|
-
if (this.#stopTrackOnPause) {
|
|
455
|
-
await this.reopenMediaStreamTrack();
|
|
456
|
-
await this.resumeProducer();
|
|
457
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackReopened, this);
|
|
458
|
-
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
await this.resumeProducer();
|
|
463
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackResumed, this);
|
|
464
|
-
} catch (error) {
|
|
465
|
-
this.logger.error('resume()', { error, track: this.logCtx });
|
|
466
|
-
throw new OperationError('track_resume_failed', error);
|
|
467
|
-
} finally {
|
|
468
|
-
release();
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
async getInfo(): Promise<BaseTrackInfo> {
|
|
473
|
-
const {
|
|
474
|
-
width, height, frameRate, aspectRatio,
|
|
475
|
-
} = this.#mediaStreamTrack.getSettings();
|
|
476
|
-
|
|
477
|
-
return {
|
|
478
|
-
trackId: this.#mediaStreamTrack.id,
|
|
479
|
-
readyState: this.#mediaStreamTrack.readyState,
|
|
480
|
-
kind: this.kind,
|
|
481
|
-
label: this.label,
|
|
482
|
-
width,
|
|
483
|
-
height,
|
|
484
|
-
frameRate,
|
|
485
|
-
aspectRatio,
|
|
486
|
-
paused: this.isPaused,
|
|
487
|
-
trackOutboundStats: await this.getStats(),
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
async getStats(): Promise<TrackOutboundStats | undefined> {
|
|
492
|
-
try {
|
|
493
|
-
return {
|
|
494
|
-
producerId: this.producer?.id,
|
|
495
|
-
codec: this.producer?.rtpParameters.codecs.find((codec) => filterStatsCodecs(codec)),
|
|
496
|
-
dtlsState: this.producer?.rtpSender?.transport?.state,
|
|
497
|
-
rtcStats: await this.getOutboundRTPStreamStats(),
|
|
498
|
-
};
|
|
499
|
-
} catch (error) {
|
|
500
|
-
this.logger.debug('getStats()', { error });
|
|
501
|
-
|
|
502
|
-
return undefined;
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
async replaceTrack(track: MediaStreamTrack): Promise<void> {
|
|
507
|
-
try {
|
|
508
|
-
this.#mediaStreamTrack = track;
|
|
509
|
-
this.internalEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackReopened, this);
|
|
510
|
-
this.observer.safeEmit('track-changed', { track });
|
|
511
|
-
await this.producer?.replaceTrack({ track });
|
|
512
|
-
this.#webrtcStatsManager = new OutboundTrackStatsManager({
|
|
513
|
-
track,
|
|
514
|
-
statsHandler: this.#statsHandler,
|
|
515
|
-
});
|
|
516
|
-
} catch (error) {
|
|
517
|
-
this.logger.warn('replaceTrack()', { error });
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
private async resumeProducer(): Promise<void> {
|
|
522
|
-
if (!this.producer) {
|
|
523
|
-
this.logger.debug('resumeProducer()', { message: 'Track not produced yet', track: this.logCtx });
|
|
524
|
-
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
await this.resumeRemoteProducer(this.producer.id);
|
|
529
|
-
this.producer.resume();
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
private async reopenMediaStreamTrack(): Promise<void> {
|
|
533
|
-
const track = await this.#mediaStreamTrackManager.createMediaStreamTrack({
|
|
534
|
-
label: this.label,
|
|
535
|
-
constraints: this.#constraints,
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
this.#mediaStreamTrack = track;
|
|
539
|
-
await this.producer?.replaceTrack({ track });
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
private prepareProducerEncodings(
|
|
543
|
-
params: PrepareProducerEncodingsParams,
|
|
544
|
-
): RTCRtpEncodingParameters[] {
|
|
545
|
-
const { encodings, codec, maxSpatialLayer } = params;
|
|
546
|
-
|
|
547
|
-
// for VP9 can use only one item in encodings array
|
|
548
|
-
return encodings && encodings.length > 1 && codec && isVp9(codec.mimeType)
|
|
549
|
-
? [encodings[maxSpatialLayer] || encodings[0]]
|
|
550
|
-
: encodings;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
private async getOutboundRTPStreamStats(): Promise<RTCOutboundRtpStreamStats> {
|
|
554
|
-
return await new Promise((resolve, reject) => {
|
|
555
|
-
const getRTCStatsReport = async (attempt = 0): Promise<void> => {
|
|
556
|
-
if (!this.producer) {
|
|
557
|
-
throw new Error('Producer is missed');
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
try {
|
|
561
|
-
const rtcStatsReport = await this.producer.getStats();
|
|
562
|
-
const outboundRTPStreamStats: RTCOutboundRtpStreamStats = Array.from(rtcStatsReport.values())
|
|
563
|
-
.find((stat) => stat.type === 'outbound-rtp');
|
|
564
|
-
|
|
565
|
-
if (!outboundRTPStreamStats && attempt < STATS_MAX_ATTEMPTS) {
|
|
566
|
-
setTimeout(async () => await getRTCStatsReport(attempt + 1), STATS_ATTEMPT_DELAY);
|
|
567
|
-
|
|
568
|
-
return;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
if (attempt >= STATS_MAX_ATTEMPTS && !outboundRTPStreamStats) {
|
|
572
|
-
reject(new Error('OutboundRTPStreamStat not exist'));
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
resolve(outboundRTPStreamStats);
|
|
576
|
-
} catch (error) {
|
|
577
|
-
reject(new Error('Can not get RTCStatsReport'));
|
|
578
|
-
this.logger.debug('getOutboundRTPStreamStats()', { error });
|
|
579
|
-
}
|
|
580
|
-
};
|
|
581
|
-
|
|
582
|
-
getRTCStatsReport().catch((error: unknown) => {
|
|
583
|
-
this.logger.debug('Error executing getRTCStatsReport', {
|
|
584
|
-
case: 'DefaultBaseTrack',
|
|
585
|
-
error: serializeError(error),
|
|
586
|
-
});
|
|
587
|
-
});
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
export default DefaultBaseTrack;
|