@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,115 +0,0 @@
|
|
|
1
|
-
import { inject, injectable } from 'inversify';
|
|
2
|
-
import { serializeError } from 'serialize-error';
|
|
3
|
-
import NotFoundError from '../../../errors/NotFoundError';
|
|
4
|
-
import { retryAsync } from '../../../helpers/retry';
|
|
5
|
-
import { TOKEN } from '../../../inversify.tokens';
|
|
6
|
-
import type { TrackLabel } from '../../../types/common';
|
|
7
|
-
import type Logger from '../../Logger';
|
|
8
|
-
import type Network from '../../network';
|
|
9
|
-
import PendingClosureProducerStorage, {
|
|
10
|
-
PendingClosureProducer,
|
|
11
|
-
} from './PendingClosureProducerStorage';
|
|
12
|
-
|
|
13
|
-
@injectable()
|
|
14
|
-
class ProducerCloseManager {
|
|
15
|
-
readonly #logger: Logger;
|
|
16
|
-
|
|
17
|
-
constructor(
|
|
18
|
-
@inject(TOKEN.Network) private readonly network: Network,
|
|
19
|
-
@inject(TOKEN.PendingClosureProducerStorage) private readonly storage: PendingClosureProducerStorage,
|
|
20
|
-
@inject(TOKEN.LoggerFactory) loggerFactory: (namespace: string) => Logger,
|
|
21
|
-
) {
|
|
22
|
-
this.#logger = loggerFactory('ProducerCloseManager');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async close(label: TrackLabel, producerId: string): Promise<void> {
|
|
26
|
-
try {
|
|
27
|
-
const closed = await this.sendCloseRequest(producerId);
|
|
28
|
-
this.storage.delete(label);
|
|
29
|
-
|
|
30
|
-
if (!closed) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
this.#logger.info('Remote producer closed', { label, producerId });
|
|
35
|
-
} catch (error) {
|
|
36
|
-
this.storage.set(label, producerId);
|
|
37
|
-
this.#logger.warn('Failed to close remote producer, queued for retry', {
|
|
38
|
-
label,
|
|
39
|
-
producerId,
|
|
40
|
-
error: serializeError(error),
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async ensureNoPending(label: TrackLabel): Promise<void> {
|
|
46
|
-
const pending = this.storage.get(label);
|
|
47
|
-
|
|
48
|
-
if (!pending) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
await this.flushEntry(pending);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async flushPending(): Promise<void> {
|
|
56
|
-
const entries = this.storage.entries();
|
|
57
|
-
|
|
58
|
-
for (const entry of entries) {
|
|
59
|
-
try {
|
|
60
|
-
await this.flushEntry(entry);
|
|
61
|
-
} catch {}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private async flushEntry(entry: PendingClosureProducer): Promise<void> {
|
|
66
|
-
try {
|
|
67
|
-
await retryAsync(
|
|
68
|
-
async () => {
|
|
69
|
-
await this.sendCloseRequest(entry.producerId);
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
maxRetries: 5,
|
|
73
|
-
minBackoffDelayMs: 200,
|
|
74
|
-
maxBackoffDelayMs: 1000,
|
|
75
|
-
actionName: 'closeRemoteProducer',
|
|
76
|
-
logger: this.#logger,
|
|
77
|
-
},
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
this.storage.delete(entry.label);
|
|
81
|
-
this.#logger.info('Pending remote producer closed', {
|
|
82
|
-
label: entry.label,
|
|
83
|
-
producerId: entry.producerId,
|
|
84
|
-
});
|
|
85
|
-
} catch (error) {
|
|
86
|
-
this.#logger.warn('Failed to close pending remote producer', {
|
|
87
|
-
label: entry.label,
|
|
88
|
-
producerId: entry.producerId,
|
|
89
|
-
error: serializeError(error),
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
throw error;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
private async sendCloseRequest(producerId: string): Promise<boolean> {
|
|
97
|
-
try {
|
|
98
|
-
await this.network.closeRemoteProducer(producerId);
|
|
99
|
-
|
|
100
|
-
return true;
|
|
101
|
-
} catch (error) {
|
|
102
|
-
if (error instanceof NotFoundError) {
|
|
103
|
-
this.#logger.debug('Remote producer maybe already closed', {
|
|
104
|
-
producerId,
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export default ProducerCloseManager;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { injectable } from 'inversify';
|
|
2
|
-
import { TrackLabel } from '../../../types/common';
|
|
3
|
-
import { AudioTrackProcessor } from './audio/AudioTrackProcessor';
|
|
4
|
-
|
|
5
|
-
export type ProcessorType = 'asdk' | 'rnnoise';
|
|
6
|
-
|
|
7
|
-
@injectable()
|
|
8
|
-
export class ProcessorsCache {
|
|
9
|
-
readonly #audioProcessorsCache = new Map<string, AudioTrackProcessor>();
|
|
10
|
-
|
|
11
|
-
add(type: ProcessorType, label: TrackLabel, processor: AudioTrackProcessor): void {
|
|
12
|
-
const key = this.getKey(type, label);
|
|
13
|
-
|
|
14
|
-
if (this.#audioProcessorsCache.has(key)) {
|
|
15
|
-
throw new Error('Attempt to rewrite cached track processor');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
this.#audioProcessorsCache.set(key, processor);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
get(type: ProcessorType, label: TrackLabel): AudioTrackProcessor | undefined {
|
|
22
|
-
return this.#audioProcessorsCache.get(this.getKey(type, label));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
has(type: ProcessorType, label: TrackLabel): boolean {
|
|
26
|
-
return this.#audioProcessorsCache.has(this.getKey(type, label));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private getKey(type: ProcessorType, label: TrackLabel): string {
|
|
30
|
-
return `${ type }:${ label }`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
reset(): void {
|
|
34
|
-
for (const processor of this.#audioProcessorsCache.values()) {
|
|
35
|
-
processor.stopProcessing();
|
|
36
|
-
processor.release();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
this.#audioProcessorsCache.clear();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { serializeError } from 'serialize-error';
|
|
2
|
-
import type { atsvb } from 'audio-effects-sdk';
|
|
3
|
-
import type { LoggerFactory } from '../../../../../types/container';
|
|
4
|
-
import type Logger from '../../../../Logger';
|
|
5
|
-
import type { AudioTrackProcessor } from '../AudioTrackProcessor';
|
|
6
|
-
import { TEN_SECONDS_IN_MS, DEBOUNCE_LIMIT, ASDK_VERSION } from '../../../../../constants/common';
|
|
7
|
-
import type ConfigService from '../../../../../config/ConfigService';
|
|
8
|
-
import { URL } from 'url';
|
|
9
|
-
|
|
10
|
-
enum ErrorType {
|
|
11
|
-
INFO = 'info',
|
|
12
|
-
WARNING = 'warning',
|
|
13
|
-
ERROR = 'error'
|
|
14
|
-
}
|
|
15
|
-
enum ErrorCode {
|
|
16
|
-
PERFORMANCE_STOP = 1001,
|
|
17
|
-
REDUCE_LATENCY = 1002,
|
|
18
|
-
}
|
|
19
|
-
enum ErrorEmitter {
|
|
20
|
-
ATSVB = 'atsvb',
|
|
21
|
-
STREAM_PROCESSOR = 'stream_processor',
|
|
22
|
-
ML_INFERENCE = 'ml_inference',
|
|
23
|
-
MODEL = 'model',
|
|
24
|
-
WORKLET = 'worklet',
|
|
25
|
-
WORKER = 'worker',
|
|
26
|
-
MODEL_LOADER = 'model_loader',
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface ErrorObject {
|
|
30
|
-
message: string;
|
|
31
|
-
type: ErrorType;
|
|
32
|
-
code?: ErrorCode;
|
|
33
|
-
emitter?: ErrorEmitter;
|
|
34
|
-
cause?: Error;
|
|
35
|
-
data?: unknown;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
declare global {
|
|
39
|
-
interface Window {
|
|
40
|
-
atsvb: typeof atsvb;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const noop = (): void => { /* no operation */ };
|
|
45
|
-
|
|
46
|
-
export interface AudioTrackProcessorParams {
|
|
47
|
-
asdkCustomerId: string;
|
|
48
|
-
config: ConfigService;
|
|
49
|
-
loggerFactory: LoggerFactory;
|
|
50
|
-
onModelsLoaded?: () => void;
|
|
51
|
-
onError?: () => void;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export class ASDKTrackProcessor implements AudioTrackProcessor {
|
|
55
|
-
readonly #atsvb: atsvb;
|
|
56
|
-
|
|
57
|
-
readonly #logger: Logger;
|
|
58
|
-
|
|
59
|
-
#originalTrack: MediaStreamTrack | null = null;
|
|
60
|
-
|
|
61
|
-
readonly #debounceCounters = new Map<number, number>();
|
|
62
|
-
|
|
63
|
-
#track?: MediaStreamTrack;
|
|
64
|
-
|
|
65
|
-
readonly type = 'asdk';
|
|
66
|
-
|
|
67
|
-
#onError: (reason: string, error: Error | undefined) => void;
|
|
68
|
-
|
|
69
|
-
constructor(params: AudioTrackProcessorParams) {
|
|
70
|
-
const { loggerFactory } = params;
|
|
71
|
-
this.#logger = loggerFactory('ASDKTrackProcessor');
|
|
72
|
-
this.#onError = typeof params.onError === 'function' ? params.onError : noop;
|
|
73
|
-
|
|
74
|
-
this.#atsvb = new window.atsvb(params.asdkCustomerId);
|
|
75
|
-
|
|
76
|
-
const staticFilesPath = params.config.get('staticFilesPath');
|
|
77
|
-
const {
|
|
78
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
79
|
-
localDir, version, sdk_url, api_url,
|
|
80
|
-
} = params.config.get('asdk');
|
|
81
|
-
|
|
82
|
-
let pathToWasm = `https://effectssdk.ai/sdk/audio/dev/${ version ?? ASDK_VERSION }`;
|
|
83
|
-
|
|
84
|
-
if (localDir) {
|
|
85
|
-
const url = new URL(`${ localDir }/${ version ?? ASDK_VERSION }`, staticFilesPath);
|
|
86
|
-
pathToWasm = url.href;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const asdkParams: Record<string, unknown> = {
|
|
90
|
-
preset: 'balanced',
|
|
91
|
-
sample_rate: 48_000,
|
|
92
|
-
api_url,
|
|
93
|
-
wasmPaths: {
|
|
94
|
-
'ort-wasm.wasm': `${ pathToWasm }/ort-wasm.wasm`,
|
|
95
|
-
'ort-wasm-simd.wasm': `${ pathToWasm }/ort-wasm-simd.wasm`,
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const shouldLoadFromLocal = !sdk_url && localDir;
|
|
100
|
-
const sdkUrl = shouldLoadFromLocal ? `${ pathToWasm }/` : sdk_url;
|
|
101
|
-
|
|
102
|
-
if (shouldLoadFromLocal) {
|
|
103
|
-
this.#logger.warn('Using static ASDK path due to missing config', {
|
|
104
|
-
case: 'Denoiser',
|
|
105
|
-
type: 'asdk',
|
|
106
|
-
...params.config.get('asdk'),
|
|
107
|
-
sdkUrl: asdkParams.sdk_url,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (sdkUrl) {
|
|
112
|
-
asdkParams.sdk_url = sdkUrl;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
this.#atsvb.config(asdkParams);
|
|
116
|
-
|
|
117
|
-
this.#atsvb.onError(this.onError.bind(this));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
setOnError(onError: (reason: string, error: Error | undefined) => void): void {
|
|
121
|
-
this.#onError = onError;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async init(): Promise<void> {
|
|
125
|
-
await this.#atsvb.preload();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
release(): void {
|
|
129
|
-
this.#atsvb.stop();
|
|
130
|
-
this.#atsvb.clear();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
get isProcessing(): boolean {
|
|
134
|
-
return !!this.#track;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async processTrack(track: MediaStreamTrack): Promise<MediaStreamTrack> {
|
|
138
|
-
if (this.#originalTrack === track || track.readyState === 'ended') {
|
|
139
|
-
return this.#atsvb.getStream()?.getAudioTracks()[0] || track;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
this.stopProcessing();
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
const outTrackPromise = new Promise<MediaStreamTrack>((resolve, reject) => {
|
|
146
|
-
this.#atsvb.onReady = () => {
|
|
147
|
-
try {
|
|
148
|
-
const newStream = this.#atsvb.getStream();
|
|
149
|
-
const outTrack = newStream?.getAudioTracks()[0];
|
|
150
|
-
|
|
151
|
-
if (!outTrack) {
|
|
152
|
-
resolve(track);
|
|
153
|
-
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
this.#originalTrack = track;
|
|
158
|
-
this.#track = outTrack;
|
|
159
|
-
|
|
160
|
-
resolve(outTrack);
|
|
161
|
-
this.#atsvb.run();
|
|
162
|
-
} catch (error) {
|
|
163
|
-
reject(error as Error);
|
|
164
|
-
} finally {
|
|
165
|
-
this.#atsvb.onReady = undefined;
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
this.#atsvb.useStream(new MediaStream([track]));
|
|
171
|
-
|
|
172
|
-
const outTrack = await outTrackPromise;
|
|
173
|
-
|
|
174
|
-
this.#logger.info('processTrack()', {
|
|
175
|
-
case: 'Denoiser',
|
|
176
|
-
type: this.type,
|
|
177
|
-
track: track.id,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
return outTrack;
|
|
181
|
-
} catch (error) {
|
|
182
|
-
this.#logger.error('processTrack()', {
|
|
183
|
-
error: serializeError(error),
|
|
184
|
-
type: this.type,
|
|
185
|
-
case: 'Denoiser',
|
|
186
|
-
track,
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
this.#onError('ASDK processTrack() error', error as Error);
|
|
190
|
-
this.#onError = noop;
|
|
191
|
-
|
|
192
|
-
throw new Error('Can not process this track');
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
stopProcessing(): void {
|
|
197
|
-
try {
|
|
198
|
-
this.#atsvb.stop();
|
|
199
|
-
} catch (error) {
|
|
200
|
-
this.#logger.error('stopProcessing()', {
|
|
201
|
-
type: this.type,
|
|
202
|
-
case: 'Denoiser',
|
|
203
|
-
error: serializeError(error),
|
|
204
|
-
});
|
|
205
|
-
} finally {
|
|
206
|
-
this.#originalTrack = null;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
getUpdatedDebounceCounter(errorCode: number): number {
|
|
211
|
-
let value = this.#debounceCounters.get(errorCode) ?? 0;
|
|
212
|
-
|
|
213
|
-
value += 1;
|
|
214
|
-
this.#debounceCounters.set(errorCode, value);
|
|
215
|
-
|
|
216
|
-
setTimeout(() => {
|
|
217
|
-
const currentValue = this.#debounceCounters.get(errorCode) ?? 0;
|
|
218
|
-
|
|
219
|
-
if (currentValue <= 0) {
|
|
220
|
-
this.#debounceCounters.set(errorCode, 0);
|
|
221
|
-
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
this.#debounceCounters.set(errorCode, currentValue - 1);
|
|
226
|
-
}, TEN_SECONDS_IN_MS);
|
|
227
|
-
|
|
228
|
-
return value;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
onError(error: ErrorObject): void {
|
|
232
|
-
const {
|
|
233
|
-
message, type, cause, ...rest
|
|
234
|
-
} = error;
|
|
235
|
-
|
|
236
|
-
if (type === ErrorType.ERROR) {
|
|
237
|
-
this.#logger.error(message, {
|
|
238
|
-
error: serializeError(cause),
|
|
239
|
-
cause,
|
|
240
|
-
...rest,
|
|
241
|
-
type: this.type,
|
|
242
|
-
case: 'Denoiser',
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
if (rest.code === ErrorCode.REDUCE_LATENCY || rest.code === ErrorCode.PERFORMANCE_STOP) {
|
|
246
|
-
const debounceCounter = this.getUpdatedDebounceCounter(rest.code);
|
|
247
|
-
|
|
248
|
-
if (debounceCounter > DEBOUNCE_LIMIT) {
|
|
249
|
-
this.#debounceCounters.set(rest.code, 0);
|
|
250
|
-
this.#onError(`ASDK performance issue(${ rest.code }): ${ message }`, cause);
|
|
251
|
-
this.#onError = noop;
|
|
252
|
-
}
|
|
253
|
-
} else {
|
|
254
|
-
this.#onError(`ASDK runtime error: ${ message }`, cause);
|
|
255
|
-
this.#onError = noop;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (type === ErrorType.WARNING) {
|
|
260
|
-
this.#logger.warn(message, {
|
|
261
|
-
...rest,
|
|
262
|
-
type: this.type,
|
|
263
|
-
case: 'Denoiser',
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
if (type === ErrorType.INFO) {
|
|
268
|
-
this.#logger.info(message, {
|
|
269
|
-
...rest,
|
|
270
|
-
type: this.type,
|
|
271
|
-
case: 'Denoiser',
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { ErrorObject } from './errorBus';
|
|
2
|
-
|
|
3
|
-
export interface Config {
|
|
4
|
-
preset: 'speed' | 'balanced' | 'quality',
|
|
5
|
-
sampleRate: 16000 | 32000 | 44100 | 48000,
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export declare class atsvb {
|
|
9
|
-
private readonly customer_id: string;
|
|
10
|
-
|
|
11
|
-
private readonly streamProcessor: any;
|
|
12
|
-
|
|
13
|
-
private readonly _isRunning: boolean;
|
|
14
|
-
|
|
15
|
-
private readonly _currentInitialization: Promise<void> | null;
|
|
16
|
-
|
|
17
|
-
clear(): void;
|
|
18
|
-
config(config: Config): void;
|
|
19
|
-
constructor(customer_id: string);
|
|
20
|
-
getAudioTrack(): MediaStreamTrack[] | undefined;
|
|
21
|
-
getCustomerId(): string;
|
|
22
|
-
getStream(): MediaStream | undefined;
|
|
23
|
-
init(stream: MediaStream): Promise<void>;
|
|
24
|
-
initImpl(stream: MediaStream, prevPromise: Promise<void>): Promise<void>;
|
|
25
|
-
onError(f: (e: ErrorObject) => void): void;
|
|
26
|
-
onReady?: () => void;
|
|
27
|
-
preload(): Promise<void>;
|
|
28
|
-
run(): void;
|
|
29
|
-
setDenoisePower(power: number): void;
|
|
30
|
-
setDroppedFramesThreshold(threshold: number): void;
|
|
31
|
-
setPreset(preset: Config['preset'], sampleRate: Config['sampleRate']): Promise<void>;
|
|
32
|
-
setPresetImpl(preset: Config['preset'], sampleRate: Config['sampleRate'], prevPromise: Promise<void>): Promise<void>;
|
|
33
|
-
stop(): void;
|
|
34
|
-
useAudioTrack(track: MediaStreamTrack): void;
|
|
35
|
-
useStream(stream: MediaStream): void;
|
|
36
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
export type CallbackFunction = (n: ErrorObject) => void;
|
|
2
|
-
|
|
3
|
-
export declare enum ErrorType {
|
|
4
|
-
INFO = "info",
|
|
5
|
-
WARNING = "warning",
|
|
6
|
-
ERROR = "error"
|
|
7
|
-
}
|
|
8
|
-
declare class _ErrorBus {
|
|
9
|
-
private static readonly _instance;
|
|
10
|
-
|
|
11
|
-
static getInstance(): _ErrorBus;
|
|
12
|
-
private readonly onErrorFunction?;
|
|
13
|
-
private constructor();
|
|
14
|
-
subscribe(f: CallbackFunction): void;
|
|
15
|
-
notify(n: ErrorObjectLight): void;
|
|
16
|
-
}
|
|
17
|
-
export declare const ErrorBus: _ErrorBus;
|
|
18
|
-
export interface ErrorObject {
|
|
19
|
-
message: string;
|
|
20
|
-
type: ErrorType;
|
|
21
|
-
emitter?: ErrorEmitter;
|
|
22
|
-
cause?: Error;
|
|
23
|
-
data?: any;
|
|
24
|
-
}
|
|
25
|
-
type ErrorObjectLight = Omit<ErrorObject, 'type'> & {
|
|
26
|
-
type?: ErrorType;
|
|
27
|
-
};
|
|
28
|
-
export declare enum ErrorType {
|
|
29
|
-
INFO = 'info',
|
|
30
|
-
WARNING = 'warning',
|
|
31
|
-
ERROR = 'error',
|
|
32
|
-
}
|
|
33
|
-
export declare enum ErrorEmitter {
|
|
34
|
-
TSVB = 'tsvb',
|
|
35
|
-
COMPONENTS_SYSTEM = 'components_system',
|
|
36
|
-
SRTEAM_PROCESSOR = 'stream_processor',
|
|
37
|
-
ML_INFERENCE = 'ml_inference',
|
|
38
|
-
PRESET_INIT = 'preset_init',
|
|
39
|
-
RENDERER = 'renderer',
|
|
40
|
-
RECORDER = 'recorder',
|
|
41
|
-
EFFECT_VIRTUAL_BACKGROUND = 'effect_virtual_background',
|
|
42
|
-
EFFECT_COLOR_CORRECTION = 'effect_color_correction',
|
|
43
|
-
EFFECT_COLOR_FILTER = 'effect_color_filter',
|
|
44
|
-
EFFECT_SMART_ZOOM = 'effect_smart_zoom',
|
|
45
|
-
EFFECT_LOW_LIGHT = 'effect_low_light',
|
|
46
|
-
}
|
|
47
|
-
export {};
|
package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionAudioWorkletNode.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type ConfigService from '../../../../../config/ConfigService';
|
|
2
|
-
import { container } from '../../../../../inversify.config';
|
|
3
|
-
import { TOKEN } from '../../../../../inversify.tokens';
|
|
4
|
-
import type { NoiseSuppressorParams } from '../../../../../types/streamEffects';
|
|
5
|
-
|
|
6
|
-
export default class NoiseSuppressionAudioWorkletNode extends AudioWorkletNode {
|
|
7
|
-
constructor(params: NoiseSuppressorParams) {
|
|
8
|
-
super(params.context, 'rnnoise', {
|
|
9
|
-
channelCountMode: 'explicit',
|
|
10
|
-
channelCount: 1,
|
|
11
|
-
channelInterpretation: 'speakers',
|
|
12
|
-
numberOfInputs: 1,
|
|
13
|
-
numberOfOutputs: 1,
|
|
14
|
-
outputChannelCount: [1],
|
|
15
|
-
processorOptions: {
|
|
16
|
-
module: params.noiseSuppressor.module,
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
this.port.onmessage = ({ data }) => {
|
|
21
|
-
const e: Event = Object.assign(new Event('status'), data);
|
|
22
|
-
this.dispatchEvent(e);
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
update(keepalive: boolean): void {
|
|
27
|
-
this.port.postMessage(keepalive);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
static async register(context: AudioContext): Promise<void> {
|
|
31
|
-
// TODO: refactor after TT-187 merge (audio effects)
|
|
32
|
-
const config = container.get<ConfigService>(TOKEN.Config);
|
|
33
|
-
await context.audioWorklet.addModule(`${ config.get('staticFilesPath') }/noiseSuppressionWorklet.js`);
|
|
34
|
-
}
|
|
35
|
-
}
|
package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionNodeProvider.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { NoiseSuppressionNode, NoiseSuppressorParams } from '../../../../../types/streamEffects';
|
|
2
|
-
import NoiseSuppressionAudioWorkletNode from './NoiseSuppressionAudioWorkletNode';
|
|
3
|
-
import NoiseSuppressionScriptProcessor from './NoiseSuppressionScriptProcessorNode';
|
|
4
|
-
import { isSafari } from '../../../../../helpers/browser';
|
|
5
|
-
|
|
6
|
-
export default class NoiseSuppressionNodeProvider {
|
|
7
|
-
readonly #context: AudioContext;
|
|
8
|
-
|
|
9
|
-
readonly #noiseSuppressor: WebAssembly.WebAssemblyInstantiatedSource;
|
|
10
|
-
|
|
11
|
-
#noiseSuppressionNode?: NoiseSuppressionAudioWorkletNode | NoiseSuppressionScriptProcessor;
|
|
12
|
-
|
|
13
|
-
constructor({ context, noiseSuppressor }: NoiseSuppressorParams) {
|
|
14
|
-
this.#context = context;
|
|
15
|
-
this.#noiseSuppressor = noiseSuppressor;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async createNoiseSuppressionNode(): Promise<NoiseSuppressionNode> {
|
|
19
|
-
return isSafari() ? this.createScriptProcessorNode() : await this.createAudioWorkletNode();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
stop(): void {
|
|
23
|
-
this.#noiseSuppressionNode?.update(false);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private async createAudioWorkletNode(): Promise<NoiseSuppressionAudioWorkletNode> {
|
|
27
|
-
await NoiseSuppressionAudioWorkletNode.register(this.#context);
|
|
28
|
-
this.#noiseSuppressionNode = new NoiseSuppressionAudioWorkletNode({
|
|
29
|
-
context: this.#context,
|
|
30
|
-
noiseSuppressor: this.#noiseSuppressor,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
return this.#noiseSuppressionNode;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private createScriptProcessorNode(): ScriptProcessorNode {
|
|
37
|
-
this.#noiseSuppressionNode = new NoiseSuppressionScriptProcessor({
|
|
38
|
-
context: this.#context,
|
|
39
|
-
noiseSuppressor: this.#noiseSuppressor,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return this.#noiseSuppressionNode.noiseSuppressionScriptProcessorNode;
|
|
43
|
-
}
|
|
44
|
-
}
|
package/src/engine/media/streamEffects/audio/noiseSuppression/NoiseSuppressionScriptProcessorNode.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { NoiseSuppressorParams, RNNoiseInstance } from '../../../../../types/streamEffects';
|
|
2
|
-
|
|
3
|
-
const BYTES_PER_FLOAT32 = 4;
|
|
4
|
-
|
|
5
|
-
export default class NoiseSuppressionScriptProcessor {
|
|
6
|
-
readonly #instance: RNNoiseInstance;
|
|
7
|
-
|
|
8
|
-
readonly #context: AudioContext;
|
|
9
|
-
|
|
10
|
-
readonly #circularBuffer: Float32Array;
|
|
11
|
-
|
|
12
|
-
readonly #state: number;
|
|
13
|
-
|
|
14
|
-
readonly #processor: ScriptProcessorNode;
|
|
15
|
-
|
|
16
|
-
#alive = true;
|
|
17
|
-
|
|
18
|
-
constructor(params: NoiseSuppressorParams) {
|
|
19
|
-
this.#instance = params.noiseSuppressor.instance.exports as unknown as RNNoiseInstance;
|
|
20
|
-
this.#context = params.context;
|
|
21
|
-
this.#circularBuffer = new Float32Array(this.#instance.memory.buffer);
|
|
22
|
-
this.#state = this.#instance.newState();
|
|
23
|
-
this.#processor = this.#context.createScriptProcessor();
|
|
24
|
-
this.setOnAudioProcess();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get noiseSuppressionScriptProcessorNode(): ScriptProcessorNode {
|
|
28
|
-
return this.#processor;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
update(keepalive: boolean): void {
|
|
32
|
-
if (!keepalive) {
|
|
33
|
-
this.#alive = false;
|
|
34
|
-
this.#instance.deleteState(this.#state);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const e = Object.assign(new Event('status'), { vadProb: this.#instance.getVadProb(this.#state) });
|
|
38
|
-
this.#processor.dispatchEvent(e);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private setOnAudioProcess(): void {
|
|
42
|
-
this.#processor.addEventListener('audioprocess', ({ inputBuffer, outputBuffer }) => {
|
|
43
|
-
if (!this.#alive) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/*
|
|
48
|
-
- В WebAssembly все адреса считаются в байтах.
|
|
49
|
-
- В JavaScript для работы с тем же куском памяти мы используем Float32Array, где элемент занимает 4 байта.
|
|
50
|
-
- Чтобы из «адреса_в_байтах» → «индекса_в_Float32Array», нужно byteOffset / 4.
|
|
51
|
-
- Аналогично при работе с Int16Array делили бы на 2, с Float64Array — на 8.
|
|
52
|
-
- RNNoise обрабатывает по 10 мс (480 сэмплов при 48 кГц). Если ваш ScriptProcessorNode настроен на 128 сэмплов,
|
|
53
|
-
то только каждое четвёртое срабатывание реально отдаст результат — именно поэтому проверка
|
|
54
|
-
if (pointer) встречается почти на каждом вызове.
|
|
55
|
-
- getVadProb() даёт оценку «есть ли речь», её можно использовать, например, чтобы зажигать индикатор говорящего.
|
|
56
|
-
Так что вся «магия» в двух местах деления на 4 — это простое соответствие между байтовыми адресами WASM и
|
|
57
|
-
индексами Float32Array, а pointer — это адрес начала готового,
|
|
58
|
-
уже очищенного от шума блока в том же кольцевом буфере.
|
|
59
|
-
*/
|
|
60
|
-
this.#circularBuffer.set(inputBuffer.getChannelData(0), this.#instance.getInput(this.#state) / BYTES_PER_FLOAT32);
|
|
61
|
-
const output = outputBuffer.getChannelData(0);
|
|
62
|
-
const pointer = this.#instance.pipe(this.#state, output.length) / BYTES_PER_FLOAT32;
|
|
63
|
-
|
|
64
|
-
if (pointer) {
|
|
65
|
-
output.set(this.#circularBuffer.subarray(pointer, pointer + output.length));
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
}
|