Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TypeScript interfaces for all exported classes #1463

Merged
merged 14 commits into from
Nov 11, 2024
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

### NEXT

- Node: Add TypeScript interfaces for all exported classes ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)).
- Node: Add new `transport.type` getter than returns `'webrtc' | 'plain' | 'pipe' | 'direct'` ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)).
- Node: Add new `rtpObserver.type` getter than returns `'activespeaker' | 'audiolevel'` ([PR #1463](https://github.com/versatica/mediasoup/pull/1463)).

### 3.14.16

- `SimulcastConsumer`: Fix cannot switch layers if initial `tsReferenceSpatialLayer disappears` disappears ([PR #1459](https://github.com/versatica/mediasoup/pull/1459) by @Lynnworld).
Expand Down
2 changes: 2 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const config = tsEslint.config(
2,
{ vars: 'all', args: 'after-used', caughtErrors: 'none' },
],
'no-unused-private-class-members': 2,
'no-use-before-define': 0,
'no-useless-call': 2,
'no-useless-computed-key': 2,
Expand Down Expand Up @@ -127,6 +128,7 @@ const config = tsEslint.config(
},
},
rules: {
'@typescript-eslint/class-literal-property-style': [2, 'getters'],
'@typescript-eslint/consistent-generic-constructors': [
2,
'type-annotation',
Expand Down
86 changes: 34 additions & 52 deletions node/src/ActiveSpeakerObserver.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,33 @@
import { Logger } from './Logger';
import { EnhancedEventEmitter } from './enhancedEvents';
import {
RtpObserver,
RtpObserverEvents,
RtpObserverObserverEvents,
RtpObserverConstructorOptions,
} from './RtpObserver';
import { Producer } from './Producer';
import { AppData } from './types';
import type {
ActiveSpeakerObserver,
ActiveSpeakerObserverDominantSpeaker,
ActiveSpeakerObserverEvents,
ActiveSpeakerObserverObserver,
ActiveSpeakerObserverObserverEvents,
} from './ActiveSpeakerObserverTypes';
import type { RtpObserver } from './RtpObserverTypes';
import { RtpObserverImpl, RtpObserverConstructorOptions } from './RtpObserver';
import type { AppData } from './types';
import { Event, Notification } from './fbs/notification';
import * as FbsActiveSpeakerObserver from './fbs/active-speaker-observer';

export type ActiveSpeakerObserverOptions<
ActiveSpeakerObserverAppData extends AppData = AppData,
> = {
interval?: number;

/**
* Custom application data.
*/
appData?: ActiveSpeakerObserverAppData;
};

export type ActiveSpeakerObserverDominantSpeaker = {
/**
* The audio Producer instance.
*/
producer: Producer;
};

export type ActiveSpeakerObserverEvents = RtpObserverEvents & {
dominantspeaker: [ActiveSpeakerObserverDominantSpeaker];
};

export type ActiveSpeakerObserverObserver =
EnhancedEventEmitter<ActiveSpeakerObserverObserverEvents>;

export type ActiveSpeakerObserverObserverEvents = RtpObserverObserverEvents & {
dominantspeaker: [ActiveSpeakerObserverDominantSpeaker];
};

type RtpObserverObserverConstructorOptions<ActiveSpeakerObserverAppData> =
RtpObserverConstructorOptions<ActiveSpeakerObserverAppData>;

const logger = new Logger('ActiveSpeakerObserver');

export class ActiveSpeakerObserver<
ActiveSpeakerObserverAppData extends AppData = AppData,
> extends RtpObserver<
ActiveSpeakerObserverAppData,
ActiveSpeakerObserverEvents,
ActiveSpeakerObserverObserver
> {
/**
* @private
*/
export class ActiveSpeakerObserverImpl<
ActiveSpeakerObserverAppData extends AppData = AppData,
>
extends RtpObserverImpl<
ActiveSpeakerObserverAppData,
ActiveSpeakerObserverEvents,
ActiveSpeakerObserverObserver
>
implements RtpObserver, ActiveSpeakerObserver
{
constructor(
options: RtpObserverObserverConstructorOptions<ActiveSpeakerObserverAppData>
) {
Expand All @@ -64,13 +37,13 @@ export class ActiveSpeakerObserver<
super(options, observer);

this.handleWorkerNotifications();
this.handleListenerError();
}

get type(): 'activespeaker' {
return 'activespeaker';
}

/**
* Observer.
*
* @override
*/
get observer(): ActiveSpeakerObserverObserver {
return super.observer;
}
Expand Down Expand Up @@ -109,4 +82,13 @@ export class ActiveSpeakerObserver<
}
);
}

private handleListenerError(): void {
this.on('listenererror', (eventName, error) => {
logger.error(
`event listener threw an error [eventName:${eventName}]:`,
error
);
});
}
}
59 changes: 59 additions & 0 deletions node/src/ActiveSpeakerObserverTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { EnhancedEventEmitter } from './enhancedEvents';
import type {
RtpObserver,
RtpObserverEvents,
RtpObserverObserverEvents,
} from './RtpObserverTypes';
import type { Producer } from './ProducerTypes';
import type { AppData } from './types';

export type ActiveSpeakerObserverOptions<
ActiveSpeakerObserverAppData extends AppData = AppData,
> = {
interval?: number;

/**
* Custom application data.
*/
appData?: ActiveSpeakerObserverAppData;
};

export type ActiveSpeakerObserverDominantSpeaker = {
/**
* The audio Producer instance.
*/
producer: Producer;
};

export type ActiveSpeakerObserverEvents = RtpObserverEvents & {
dominantspeaker: [ActiveSpeakerObserverDominantSpeaker];
};

export type ActiveSpeakerObserverObserver =
EnhancedEventEmitter<ActiveSpeakerObserverObserverEvents>;

export type ActiveSpeakerObserverObserverEvents = RtpObserverObserverEvents & {
dominantspeaker: [ActiveSpeakerObserverDominantSpeaker];
};

export interface ActiveSpeakerObserver<
ActiveSpeakerObserverAppData extends AppData = AppData,
> extends RtpObserver<
ActiveSpeakerObserverAppData,
ActiveSpeakerObserverEvents,
ActiveSpeakerObserverObserver
> {
/**
* RtpObserver type.
*
* @override
*/
get type(): 'activespeaker';

/**
* Observer.
*
* @override
*/
get observer(): ActiveSpeakerObserverObserver;
}
113 changes: 37 additions & 76 deletions node/src/AudioLevelObserver.ts
Original file line number Diff line number Diff line change
@@ -1,83 +1,35 @@
import { Logger } from './Logger';
import { EnhancedEventEmitter } from './enhancedEvents';
import {
RtpObserver,
RtpObserverEvents,
RtpObserverObserverEvents,
RtpObserverConstructorOptions,
} from './RtpObserver';
import { Producer } from './Producer';
import { AppData } from './types';
import * as utils from './utils';
import type {
AudioLevelObserver,
AudioLevelObserverVolume,
AudioLevelObserverEvents,
AudioLevelObserverObserver,
AudioLevelObserverObserverEvents,
} from './AudioLevelObserverTypes';
import type { RtpObserver } from './RtpObserverTypes';
import { RtpObserverImpl, RtpObserverConstructorOptions } from './RtpObserver';
import type { Producer } from './ProducerTypes';
import type { AppData } from './types';
import * as fbsUtils from './fbsUtils';
import { Event, Notification } from './fbs/notification';
import * as FbsAudioLevelObserver from './fbs/audio-level-observer';

export type AudioLevelObserverOptions<
AudioLevelObserverAppData extends AppData = AppData,
> = {
/**
* Maximum number of entries in the 'volumes”' event. Default 1.
*/
maxEntries?: number;

/**
* Minimum average volume (in dBvo from -127 to 0) for entries in the
* 'volumes' event. Default -80.
*/
threshold?: number;

/**
* Interval in ms for checking audio volumes. Default 1000.
*/
interval?: number;

/**
* Custom application data.
*/
appData?: AudioLevelObserverAppData;
};

export type AudioLevelObserverVolume = {
/**
* The audio Producer instance.
*/
producer: Producer;

/**
* The average volume (in dBvo from -127 to 0) of the audio Producer in the
* last interval.
*/
volume: number;
};

export type AudioLevelObserverEvents = RtpObserverEvents & {
volumes: [AudioLevelObserverVolume[]];
silence: [];
};

export type AudioLevelObserverObserver =
EnhancedEventEmitter<AudioLevelObserverObserverEvents>;

export type AudioLevelObserverObserverEvents = RtpObserverObserverEvents & {
volumes: [AudioLevelObserverVolume[]];
silence: [];
};

type AudioLevelObserverConstructorOptions<AudioLevelObserverAppData> =
RtpObserverConstructorOptions<AudioLevelObserverAppData>;

const logger = new Logger('AudioLevelObserver');

export class AudioLevelObserver<
AudioLevelObserverAppData extends AppData = AppData,
> extends RtpObserver<
AudioLevelObserverAppData,
AudioLevelObserverEvents,
AudioLevelObserverObserver
> {
/**
* @private
*/
export class AudioLevelObserverImpl<
AudioLevelObserverAppData extends AppData = AppData,
>
extends RtpObserverImpl<
AudioLevelObserverAppData,
AudioLevelObserverEvents,
AudioLevelObserverObserver
>
implements RtpObserver, AudioLevelObserver
{
constructor(
options: AudioLevelObserverConstructorOptions<AudioLevelObserverAppData>
) {
Expand All @@ -87,13 +39,13 @@ export class AudioLevelObserver<
super(options, observer);

this.handleWorkerNotifications();
this.handleListenerError();
}

get type(): 'audiolevel' {
return 'audiolevel';
}

/**
* Observer.
*
* @override
*/
get observer(): AudioLevelObserverObserver {
return super.observer;
}
Expand All @@ -111,7 +63,7 @@ export class AudioLevelObserver<

// Get the corresponding Producer instance and remove entries with
// no Producer (it may have been closed in the meanwhile).
const volumes: AudioLevelObserverVolume[] = utils
const volumes: AudioLevelObserverVolume[] = fbsUtils
.parseVector(notification, 'volumes', parseVolume)
.map(
({
Expand Down Expand Up @@ -153,6 +105,15 @@ export class AudioLevelObserver<
}
);
}

private handleListenerError(): void {
this.on('listenererror', (eventName, error) => {
logger.error(
`event listener threw an error [eventName:${eventName}]:`,
error
);
});
}
}

function parseVolume(binary: FbsAudioLevelObserver.Volume): {
Expand Down
Loading
Loading