@livedigital/client 3.48.0 → 3.49.0
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/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,574 +0,0 @@
|
|
|
1
|
-
import { inject, injectable } from 'inversify';
|
|
2
|
-
import { Device, type types } from 'mediasoup-client';
|
|
3
|
-
import { serializeError } from 'serialize-error';
|
|
4
|
-
import ConfigService, { ProcessedParams } from '../../config/ConfigService';
|
|
5
|
-
import { SCREEN_SHARING_SIMULCAST_ENCODINGS, WEBCAM_SIMULCAST_ENCODINGS } from '../../constants/encodings';
|
|
6
|
-
import { CLIENT_EVENTS } from '../../constants/events';
|
|
7
|
-
import { SpatialLayer, VIDEO_CONSTRAINS } from '../../constants/videoConstrains';
|
|
8
|
-
import EnhancedEventEmitter from '../../EnhancedEventEmitter';
|
|
9
|
-
import OperationError from '../../errors/OperationError';
|
|
10
|
-
import { detectHandlerName } from '../../helpers/media';
|
|
11
|
-
import { TOKEN } from '../../inversify.tokens';
|
|
12
|
-
import {
|
|
13
|
-
CreateCameraVideoTrackOptions,
|
|
14
|
-
CreateMicrophoneAudioTrackOptions,
|
|
15
|
-
CreateScreenMediaOptions,
|
|
16
|
-
CreateTracksPayload,
|
|
17
|
-
CreateVideoTrackParams,
|
|
18
|
-
ProducerRequestMaxSpatialLayer,
|
|
19
|
-
TrackLabel,
|
|
20
|
-
TransformParams,
|
|
21
|
-
} from '../../types/common';
|
|
22
|
-
import type { AudioTrackFactory, VideoTrackFactory } from '../../types/container';
|
|
23
|
-
import {
|
|
24
|
-
AudioTrack,
|
|
25
|
-
BaseTrack,
|
|
26
|
-
BaseTrackParams,
|
|
27
|
-
InitEffectsSDKParams,
|
|
28
|
-
TrackWithEncodings,
|
|
29
|
-
VideoTrack,
|
|
30
|
-
} from '../../types/media';
|
|
31
|
-
import { IntegrationsService } from '../IntegrationsService';
|
|
32
|
-
import Logger from '../Logger';
|
|
33
|
-
import SignalingApiClient from '../signalingApiClient/SignalingApiClient';
|
|
34
|
-
import { ASDKTrackProcessor } from './streamEffects/audio/asdk/ASDKTrackProcessor';
|
|
35
|
-
import { ProcessorsCache } from './streamEffects/ProcessorsCache';
|
|
36
|
-
import EffectsSDKTrackProcessor from './streamEffects/video/esdk/TrackProcessor';
|
|
37
|
-
import DefaultAudioTrack from './tracks/DefaultAudioTrack';
|
|
38
|
-
import DefaultVideoTrack from './tracks/DefaultVideoTrack';
|
|
39
|
-
import MediaStreamTrackManager from './tracks/MediaStreamTrackManager';
|
|
40
|
-
|
|
41
|
-
export interface DenoiserFallbackContext {
|
|
42
|
-
reason: string;
|
|
43
|
-
options?: CreateMicrophoneAudioTrackOptions;
|
|
44
|
-
error?: Error;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
@injectable()
|
|
48
|
-
class Media {
|
|
49
|
-
public isDeviceLoaded = false;
|
|
50
|
-
|
|
51
|
-
private device?: Device;
|
|
52
|
-
|
|
53
|
-
private readonly tracks = new Map<TrackLabel, BaseTrack>();
|
|
54
|
-
|
|
55
|
-
readonly #logger: Logger;
|
|
56
|
-
|
|
57
|
-
readonly #effectsSDKParams: InitEffectsSDKParams | null = null;
|
|
58
|
-
|
|
59
|
-
#effectsSDKInitialized = false;
|
|
60
|
-
|
|
61
|
-
readonly #effectsProcessors = new Map<string, EffectsSDKTrackProcessor>();
|
|
62
|
-
|
|
63
|
-
#denoiserInitializing = false;
|
|
64
|
-
|
|
65
|
-
#denoiserFallbacked = false;
|
|
66
|
-
|
|
67
|
-
#denoiser: ProcessedParams['denoiser'];
|
|
68
|
-
|
|
69
|
-
constructor(
|
|
70
|
-
@inject(TOKEN.Config) private readonly config: ConfigService,
|
|
71
|
-
@inject(TOKEN.LoggerFactory) private readonly loggerFactory: (namespace: string) => Logger,
|
|
72
|
-
@inject(TOKEN.AudioTrackFactory) private readonly audioTrackFactory: AudioTrackFactory,
|
|
73
|
-
@inject(TOKEN.ClientEventEmitter) private readonly clientEventEmitter: EnhancedEventEmitter,
|
|
74
|
-
@inject(TOKEN.IntegrationsService) private readonly integrationsService: IntegrationsService,
|
|
75
|
-
@inject(TOKEN.ProcessorsCache) private readonly processorsCache: ProcessorsCache,
|
|
76
|
-
@inject(TOKEN.VideoTrackFactory) private readonly videoTrackFactory: VideoTrackFactory,
|
|
77
|
-
@inject(TOKEN.MediaStreamTrackManager) private readonly mediaStreamTrackManager: MediaStreamTrackManager,
|
|
78
|
-
@inject(TOKEN.SignalingApiClient) private readonly signalingApiClient: SignalingApiClient,
|
|
79
|
-
) {
|
|
80
|
-
const effectsSDKParams = this.config.get('effectsSDKParams');
|
|
81
|
-
|
|
82
|
-
this.#denoiser = this.config.get('denoiser');
|
|
83
|
-
|
|
84
|
-
this.#logger = this.loggerFactory('Media');
|
|
85
|
-
this.#effectsSDKParams = effectsSDKParams ?? null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
get mediasoupDevice(): Device {
|
|
89
|
-
this.device ??= this.createDevice();
|
|
90
|
-
|
|
91
|
-
return this.device;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
get effectsSDKInitialized(): boolean {
|
|
95
|
-
return this.#effectsSDKInitialized;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
get effectsSDKParams(): InitEffectsSDKParams | null {
|
|
99
|
-
return this.#effectsSDKParams;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
getTrack(label: TrackLabel): BaseTrack | undefined {
|
|
103
|
-
return this.tracks.get(label);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async loadDevice(routerRtpCapabilities: types.RtpCapabilities): Promise<void> {
|
|
107
|
-
if (!this.isDeviceLoaded) {
|
|
108
|
-
await this.mediasoupDevice.load({ routerRtpCapabilities });
|
|
109
|
-
this.isDeviceLoaded = true;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
getTrackCodec(track: TrackWithEncodings): types.RtpCodecCapability | undefined {
|
|
114
|
-
const { rtpCapabilities, rtpCapabilities: { codecs } } = this.mediasoupDevice;
|
|
115
|
-
|
|
116
|
-
if (!codecs) {
|
|
117
|
-
this.#logger.error('getTrackCodec()', { label: track.getLabel, rtpCapabilities });
|
|
118
|
-
|
|
119
|
-
return undefined;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return codecs.find((c) => c.mimeType.toLowerCase() === `${ track.kind }/${ track.getPreferredCodec() }`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private createTracks({ constraints, mediaStreamTracks }: CreateTracksPayload): BaseTrack[] {
|
|
126
|
-
return mediaStreamTracks.map((mediaStreamTrack) => {
|
|
127
|
-
const params: Omit<BaseTrackParams, 'loggerNamespace'> = {
|
|
128
|
-
mediaStreamTrack,
|
|
129
|
-
constraints,
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
let track: DefaultAudioTrack | DefaultVideoTrack | undefined = undefined;
|
|
133
|
-
|
|
134
|
-
if (mediaStreamTrack.kind === 'audio') {
|
|
135
|
-
track = this.audioTrackFactory({
|
|
136
|
-
...params,
|
|
137
|
-
loggerNamespace: 'AudioTrack',
|
|
138
|
-
});
|
|
139
|
-
} else {
|
|
140
|
-
track = this.videoTrackFactory({
|
|
141
|
-
...params,
|
|
142
|
-
loggerNamespace: 'VideoTrack',
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
this.#logger.debug('createTrack() track created', {
|
|
147
|
-
trackId: track.id,
|
|
148
|
-
kind: track.kind,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
return track as unknown as BaseTrack;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async createUserMediaTracks(constraints: MediaStreamConstraints): Promise<BaseTrack[]> {
|
|
156
|
-
const mediaStreamTracks = await this.mediaStreamTrackManager.createUserMediaTracks(constraints);
|
|
157
|
-
|
|
158
|
-
return this.createTracks({ constraints, mediaStreamTracks });
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
async createDisplayMediaTracks(constraints: MediaStreamConstraints): Promise<BaseTrack[]> {
|
|
162
|
-
const mediaStreamTracks = await this.mediaStreamTrackManager.createDisplayMediaTracks(constraints);
|
|
163
|
-
|
|
164
|
-
return this.createTracks({ constraints, mediaStreamTracks });
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
createCustomMediaTrack(
|
|
168
|
-
mediaStreamTrack: MediaStreamTrack,
|
|
169
|
-
constraints: MediaStreamConstraints,
|
|
170
|
-
): BaseTrack {
|
|
171
|
-
return this.createTracks({ constraints, mediaStreamTracks: [mediaStreamTrack] })[0];
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async deleteTrack(track: BaseTrack): Promise<void> {
|
|
175
|
-
const logContext = {
|
|
176
|
-
trackId: track.id,
|
|
177
|
-
label: track.getLabel(),
|
|
178
|
-
producerId: track.producerId,
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
try {
|
|
182
|
-
if ('disableNoiseSuppression' in track) {
|
|
183
|
-
await (track as AudioTrack).disableNoiseSuppression();
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if ('disableEffects' in track) {
|
|
187
|
-
await (track as VideoTrack).disableEffects();
|
|
188
|
-
}
|
|
189
|
-
} catch (error) {
|
|
190
|
-
this.#logger.warn('deleteTrack()', { error, ...logContext });
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
try {
|
|
194
|
-
this.tracks.delete(track.getLabel());
|
|
195
|
-
track.stopMediaStreamTrack();
|
|
196
|
-
await track.closeProducer();
|
|
197
|
-
} catch (error) {
|
|
198
|
-
this.#logger.error('deleteTrack()', { error });
|
|
199
|
-
} finally {
|
|
200
|
-
this.#logger.debug('deleteTrack()', logContext);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
getAllTracks(): BaseTrack[] {
|
|
205
|
-
return Array.from(this.tracks.values());
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
publishedTracks(): BaseTrack[] {
|
|
209
|
-
return this.getAllTracks().filter((track) => track.isPublished);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
clearTracks(): void {
|
|
213
|
-
try {
|
|
214
|
-
this.getAllTracks().forEach((track) => track.stopMediaStreamTrack());
|
|
215
|
-
} catch (error) {
|
|
216
|
-
this.#logger.warn('clearTracks()', { error });
|
|
217
|
-
} finally {
|
|
218
|
-
this.tracks.clear();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
async unpublishTracks(): Promise<void> {
|
|
223
|
-
try {
|
|
224
|
-
await Promise.all(this.publishedTracks().map(async (track) => await track.unpublish(false)));
|
|
225
|
-
} catch (error) {
|
|
226
|
-
this.#logger.warn('unpublishTracks()', { error });
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
setTrack(track: BaseTrack): void {
|
|
231
|
-
this.tracks.set(track.getLabel(), track);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
async initEffectsSDK(): Promise<boolean> {
|
|
235
|
-
if (this.#effectsSDKInitialized) {
|
|
236
|
-
return true;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (!this.#effectsSDKParams) {
|
|
240
|
-
this.#logger.error('Effects SDK config params not provided', { case: 'initEffectsSDK' });
|
|
241
|
-
throw new OperationError(
|
|
242
|
-
'effects_sdk_config_missing',
|
|
243
|
-
new Error('Effects SDK config not provided'),
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const init = async (resolve: (value: boolean) => void, reject: (error: Error) => void): Promise<void> => {
|
|
248
|
-
if (!window.tsvb) {
|
|
249
|
-
this.#logger.info('Effects SDK not loaded, skipping initialization', { case: 'initEffectsSDK' });
|
|
250
|
-
resolve(false);
|
|
251
|
-
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
this.#logger.info('Effects SDK initializing', { case: 'initEffectsSDK' });
|
|
256
|
-
|
|
257
|
-
try {
|
|
258
|
-
/* cant use Promise.all(), something breaks in parallel preload() */
|
|
259
|
-
this.#effectsProcessors.set(
|
|
260
|
-
TrackLabel.Camera, await this.createEffectsSDKTrackProcessor(TrackLabel.Camera),
|
|
261
|
-
);
|
|
262
|
-
this.#effectsProcessors.set(
|
|
263
|
-
TrackLabel.CameraPreview, await this.createEffectsSDKTrackProcessor(TrackLabel.CameraPreview),
|
|
264
|
-
);
|
|
265
|
-
this.#effectsSDKInitialized = true;
|
|
266
|
-
this.#logger.info('Effects SDK initialized', { case: 'initEffectsSDK' });
|
|
267
|
-
resolve(true);
|
|
268
|
-
} catch (error: unknown) {
|
|
269
|
-
this.#logger.error('Failed to initialize Effects SDK', { error, case: 'initEffectsSDK' });
|
|
270
|
-
reject(error as Error);
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
return await new Promise((resolve, reject) => {
|
|
275
|
-
if (!window.tsvb) {
|
|
276
|
-
this.#logger.info('Effects SDK tsvb-web.js is not ready, waiting', { case: 'initEffectsSDK' });
|
|
277
|
-
window.addEventListener('load', async () => await init(resolve, reject));
|
|
278
|
-
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
init(resolve, reject).catch((error: unknown) => {
|
|
283
|
-
this.#logger.error('Failed to execute init() in initEffectsSDK', {
|
|
284
|
-
error: serializeError(error),
|
|
285
|
-
});
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
async initDenoiser(track: AudioTrack, options?: CreateMicrophoneAudioTrackOptions): Promise<void> {
|
|
291
|
-
if (this.#denoiserInitializing) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
try {
|
|
296
|
-
this.#denoiserInitializing = true;
|
|
297
|
-
this.clientEventEmitter.emit(CLIENT_EVENTS.denoiserInitializing, true);
|
|
298
|
-
|
|
299
|
-
try {
|
|
300
|
-
await this.integrationsService.audio.waitForInitialization;
|
|
301
|
-
} catch (error: unknown) {
|
|
302
|
-
if (this.#denoiser === 'asdk') {
|
|
303
|
-
this.#denoiserFallbacked = true;
|
|
304
|
-
this.#denoiser = 'rnnoise';
|
|
305
|
-
this.config.set('denoiser', this.#denoiser);
|
|
306
|
-
|
|
307
|
-
this.#logger.debug('Set config to rnnoise denoiser', {
|
|
308
|
-
case: 'Denoiser',
|
|
309
|
-
error: serializeError(error),
|
|
310
|
-
type: this.config.get('denoiser'),
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
this.clientEventEmitter.emit(CLIENT_EVENTS.denoiserFallback);
|
|
314
|
-
|
|
315
|
-
this.integrationsService.init();
|
|
316
|
-
await this.integrationsService.audio.waitForInitialization;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
this.#logger.debug('Denoiser initialized, activating', {
|
|
321
|
-
case: 'Denoiser',
|
|
322
|
-
type: this.integrationsService.audio.type,
|
|
323
|
-
trackLabel: track.getLabel(),
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
const audioTrack = track;
|
|
327
|
-
const trackProcessor = this.processorsCache.get(this.#denoiser, TrackLabel.Microphone);
|
|
328
|
-
|
|
329
|
-
if (!trackProcessor) {
|
|
330
|
-
this.#logger.error('No cached trackProcessor found', {
|
|
331
|
-
case: 'Denoiser',
|
|
332
|
-
trackLabel: track.getLabel(),
|
|
333
|
-
type: this.integrationsService.audio.type,
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (trackProcessor.type === 'asdk') {
|
|
340
|
-
(trackProcessor as ASDKTrackProcessor).setOnError((reason, asdkError) => {
|
|
341
|
-
this.clientEventEmitter.emit(CLIENT_EVENTS.denoiserInitializing, true);
|
|
342
|
-
this.fallbackToRNoise(track, { reason, options, error: asdkError })
|
|
343
|
-
.catch((error: unknown) => {
|
|
344
|
-
this.#logger.error('Failed to fallback to RNNoise through onError', {
|
|
345
|
-
case: 'Denoiser',
|
|
346
|
-
type: this.#denoiser,
|
|
347
|
-
error: serializeError(error),
|
|
348
|
-
label: track.getLabel(),
|
|
349
|
-
});
|
|
350
|
-
})
|
|
351
|
-
.then(() => {
|
|
352
|
-
this.clientEventEmitter.emit(CLIENT_EVENTS.denoiserInitializing, false);
|
|
353
|
-
})
|
|
354
|
-
.catch(() => { /* no operation */ });
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
audioTrack.setTrackProcessor(trackProcessor);
|
|
359
|
-
|
|
360
|
-
this.#logger.debug('Denoiser trackProcessor set, check if activation is needed', {
|
|
361
|
-
case: 'Denoiser',
|
|
362
|
-
type: this.#denoiser,
|
|
363
|
-
shouldEnableDenoiser: options?.noiseSuppression,
|
|
364
|
-
trackLabel: track.getLabel(),
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
if (options?.noiseSuppression) {
|
|
368
|
-
await (track).enableNoiseSuppression();
|
|
369
|
-
}
|
|
370
|
-
} catch (error) {
|
|
371
|
-
this.#logger.warn('Failed to start noise suppression, featured original track', {
|
|
372
|
-
case: 'Denoiser',
|
|
373
|
-
type: this.#denoiser,
|
|
374
|
-
error: serializeError(error),
|
|
375
|
-
label: track.getLabel(),
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
if (this.#denoiser === 'asdk') {
|
|
379
|
-
try {
|
|
380
|
-
this.#logger.warn('Fallback to RNNoise', {
|
|
381
|
-
error: serializeError(error),
|
|
382
|
-
});
|
|
383
|
-
await this.fallbackToRNoise(track, { options, reason: 'ASDK init error', error });
|
|
384
|
-
} catch (error2) {
|
|
385
|
-
this.#logger.error('Failed to fallback to RNNoise through catch', {
|
|
386
|
-
case: 'Denoiser',
|
|
387
|
-
type: this.#denoiser,
|
|
388
|
-
error: serializeError(error2),
|
|
389
|
-
label: track.getLabel(),
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} finally {
|
|
394
|
-
this.clientEventEmitter.emit(CLIENT_EVENTS.denoiserInitializing, false);
|
|
395
|
-
this.#denoiserInitializing = false;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
async fallbackToRNoise(track: AudioTrack, context: DenoiserFallbackContext): Promise<void> {
|
|
400
|
-
if (this.#denoiserFallbacked) {
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
this.#denoiserFallbacked = true;
|
|
405
|
-
|
|
406
|
-
if (this.#denoiser === 'rnnoise') {
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
this.clientEventEmitter.emit(CLIENT_EVENTS.denoiserFallback);
|
|
411
|
-
|
|
412
|
-
this.#logger.info('Fallback to RNNoise', {
|
|
413
|
-
reason: context?.reason,
|
|
414
|
-
error: serializeError(context?.error),
|
|
415
|
-
case: 'Denoiser',
|
|
416
|
-
});
|
|
417
|
-
|
|
418
|
-
const audioTrack = track;
|
|
419
|
-
|
|
420
|
-
await audioTrack.disableNoiseSuppression();
|
|
421
|
-
audioTrack.unsetTrackProcessor();
|
|
422
|
-
|
|
423
|
-
this.#denoiser = 'rnnoise';
|
|
424
|
-
this.config.set('denoiser', this.#denoiser);
|
|
425
|
-
this.#logger.debug('Set config to rnnoise denoiser', {
|
|
426
|
-
case: 'Denoiser',
|
|
427
|
-
type: this.config.get('denoiser'),
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
this.integrationsService.init();
|
|
431
|
-
await this.integrationsService.audio.waitForInitialization;
|
|
432
|
-
|
|
433
|
-
const trackProcessor = this.processorsCache.get(this.#denoiser, TrackLabel.Microphone);
|
|
434
|
-
|
|
435
|
-
if (!trackProcessor) {
|
|
436
|
-
this.#logger.error('No cached trackProcessor found', {
|
|
437
|
-
case: 'Denoiser',
|
|
438
|
-
trackLabel: track.getLabel(),
|
|
439
|
-
type: this.integrationsService.audio.type,
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
audioTrack.setTrackProcessor(trackProcessor);
|
|
446
|
-
|
|
447
|
-
if (context?.options?.noiseSuppression) {
|
|
448
|
-
await audioTrack.enableNoiseSuppression();
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
async createEffectsSDKTrackProcessor(trackLabel?: TrackLabel): Promise<EffectsSDKTrackProcessor> {
|
|
453
|
-
if (trackLabel) {
|
|
454
|
-
const processor = this.#effectsProcessors.get(trackLabel);
|
|
455
|
-
|
|
456
|
-
if (processor) {
|
|
457
|
-
return processor;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
if (!this.#effectsSDKParams) {
|
|
462
|
-
this.#logger.error('Effects SDK config params not provided', { case: 'initEffectsSDK' });
|
|
463
|
-
throw new OperationError(
|
|
464
|
-
'effects_sdk_config_missing',
|
|
465
|
-
new Error('Effects SDK config not provided'),
|
|
466
|
-
);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
const processor = new EffectsSDKTrackProcessor({
|
|
470
|
-
loggerFactory: this.loggerFactory,
|
|
471
|
-
customerId: this.config.get('effectsSDKParams')?.customerId,
|
|
472
|
-
sdk_url: this.config.get('effectsSDKParams')?.sdk_url,
|
|
473
|
-
api_url: this.config.get('effectsSDKParams')?.api_url,
|
|
474
|
-
config: this.config,
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
await processor.init();
|
|
478
|
-
this.#logger.info('Track effects processor initialized', { trackLabel });
|
|
479
|
-
|
|
480
|
-
return processor;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
async handleProducerSetMaxSpatialLayer({
|
|
484
|
-
producerId,
|
|
485
|
-
spatialLayer: rawSpatialLayer,
|
|
486
|
-
}: ProducerRequestMaxSpatialLayer): Promise<void> {
|
|
487
|
-
const track = this.getAllTracks().find((t) => t.getProducer()?.id === producerId);
|
|
488
|
-
|
|
489
|
-
if (!track) {
|
|
490
|
-
this.#logger.warn('producerRequestMaxSpatialLayer()', { message: 'Producer not found' });
|
|
491
|
-
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
if (!(track instanceof DefaultVideoTrack)) {
|
|
496
|
-
this.#logger.warn('producerRequestMaxSpatialLayer()', { message: 'Wrong producer kind' });
|
|
497
|
-
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
const spatialLayer = rawSpatialLayer ?? SpatialLayer.LOW;
|
|
502
|
-
const currentMaxSpatialLayer = track.getMaxSpatialLayer();
|
|
503
|
-
|
|
504
|
-
if (currentMaxSpatialLayer === spatialLayer) {
|
|
505
|
-
this.#logger.debug('producerRequestMaxSpatialLayer()', {
|
|
506
|
-
message: 'Skip set max spatial layer',
|
|
507
|
-
requestedSpatialLayer: spatialLayer,
|
|
508
|
-
currentMaxSpatialLayer,
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
if (track.getEncodings().length > 1) { // no need to do this operation for the only encoding item
|
|
515
|
-
await track.setMaxSpatialLayer(spatialLayer);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
await this.signalingApiClient.producer.setProducerMaxSpatialLayer(producerId, {
|
|
519
|
-
maxSpatialLayer: spatialLayer,
|
|
520
|
-
});
|
|
521
|
-
await track.adjustEncodingPresetToCurrentMaxSpatialLayer(spatialLayer);
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
static getVideoTrackTransformParams(track: MediaStreamTrack): TransformParams {
|
|
525
|
-
const caps = track.getSettings();
|
|
526
|
-
|
|
527
|
-
return {
|
|
528
|
-
width: caps.width ?? VIDEO_CONSTRAINS.hd.width,
|
|
529
|
-
height: caps.height ?? VIDEO_CONSTRAINS.hd.height,
|
|
530
|
-
};
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
static getScreenVideoTrackParams(options?: CreateScreenMediaOptions): CreateVideoTrackParams {
|
|
534
|
-
const videoTrackOptions = options?.video ?? {
|
|
535
|
-
frameRate: { max: 20 },
|
|
536
|
-
width: { max: VIDEO_CONSTRAINS.hd.width },
|
|
537
|
-
height: { max: VIDEO_CONSTRAINS.hd.height },
|
|
538
|
-
};
|
|
539
|
-
|
|
540
|
-
return {
|
|
541
|
-
videoTrackOptions,
|
|
542
|
-
encoderConfig: options?.videoEncoderConfig ?? {
|
|
543
|
-
encodings: SCREEN_SHARING_SIMULCAST_ENCODINGS,
|
|
544
|
-
},
|
|
545
|
-
};
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
static getCameraVideoTrackParams(options?: CreateCameraVideoTrackOptions): CreateVideoTrackParams {
|
|
549
|
-
const videoTrackOptions = options?.video ?? {
|
|
550
|
-
frameRate: { max: 24 },
|
|
551
|
-
width: { max: VIDEO_CONSTRAINS.hd.width },
|
|
552
|
-
height: { max: VIDEO_CONSTRAINS.hd.height },
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
return {
|
|
556
|
-
videoTrackOptions,
|
|
557
|
-
encoderConfig: options?.encoderConfig ?? {
|
|
558
|
-
encodings: WEBCAM_SIMULCAST_ENCODINGS,
|
|
559
|
-
},
|
|
560
|
-
};
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
private createDevice(): Device {
|
|
564
|
-
const handlerName = detectHandlerName();
|
|
565
|
-
|
|
566
|
-
this.#logger.debug('Creating a media device', {
|
|
567
|
-
handlerName: handlerName ?? 'not specified',
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
return new Device({ handlerName });
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
export default Media;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { injectable } from 'inversify';
|
|
2
|
-
import type { TrackLabel } from '../../../types/common';
|
|
3
|
-
|
|
4
|
-
export interface PendingClosureProducer {
|
|
5
|
-
label: TrackLabel;
|
|
6
|
-
producerId: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
@injectable()
|
|
10
|
-
class PendingClosureProducerStorage {
|
|
11
|
-
readonly #pending = new Map<TrackLabel, PendingClosureProducer>();
|
|
12
|
-
|
|
13
|
-
set(label: TrackLabel, producerId: string): void {
|
|
14
|
-
this.#pending.set(label, {
|
|
15
|
-
label,
|
|
16
|
-
producerId,
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get(label: TrackLabel): PendingClosureProducer | undefined {
|
|
21
|
-
return this.#pending.get(label);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
has(label: TrackLabel): boolean {
|
|
25
|
-
return this.#pending.has(label);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
delete(label: TrackLabel): void {
|
|
29
|
-
this.#pending.delete(label);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
entries(): PendingClosureProducer[] {
|
|
33
|
-
return Array.from(this.#pending.values());
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export default PendingClosureProducerStorage;
|