@kaltura-sdk/rtc-core 1.25.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/README.md +237 -0
- package/index.d.ts +1 -0
- package/index.esm.js +15293 -0
- package/package.json +22 -0
- package/src/index.d.ts +6 -0
- package/src/lib/core-utils/BrowserDetector.d.ts +101 -0
- package/src/lib/core-utils/DevicesUtils.d.ts +1 -0
- package/src/lib/core-utils/GlobalEventEmitter.d.ts +1 -0
- package/src/lib/core-utils/MediaUtils.d.ts +45 -0
- package/src/lib/core-utils/Mutex.d.ts +8 -0
- package/src/lib/core-utils/SdpUtils.d.ts +25 -0
- package/src/lib/core-utils/UserBrowserUtils.d.ts +37 -0
- package/src/lib/core-utils/UtilityFunctions.d.ts +21 -0
- package/src/lib/core-utils/index.d.ts +4 -0
- package/src/lib/core-utils/webrtcAudioStats.d.ts +56 -0
- package/src/lib/core-utils/webrtcStatsTypes.d.ts +76 -0
- package/src/lib/core-utils/webrtcVideoStats.d.ts +6 -0
- package/src/lib/devices/DevicesManager.d.ts +137 -0
- package/src/lib/devices/UserMediaManager.d.ts +52 -0
- package/src/lib/devices/index.d.ts +2 -0
- package/src/lib/media/AudioAnalyzer.d.ts +60 -0
- package/src/lib/media/GetUserMediaManager.d.ts +178 -0
- package/src/lib/media/MediaSources.d.ts +105 -0
- package/src/lib/media/index.d.ts +4 -0
- package/src/lib/media/media-processing/AudioProcessing.d.ts +42 -0
- package/src/lib/media/media-processing/AudioProcessingModes.d.ts +76 -0
- package/src/lib/media/media-processing/index.d.ts +4 -0
- package/src/lib/media/media-processing/types.d.ts +83 -0
- package/src/lib/media/types.d.ts +73 -0
- package/src/lib/peer-connection/IceHandler.d.ts +60 -0
- package/src/lib/peer-connection/PeerConnection.d.ts +153 -0
- package/src/lib/peer-connection/PeerConnectionBeacon.d.ts +208 -0
- package/src/lib/peer-connection/PeerConnectionManager.d.ts +57 -0
- package/src/lib/peer-connection/PeerConnectionWebrtcStats.d.ts +32 -0
- package/src/lib/peer-connection/constants.d.ts +89 -0
- package/src/lib/peer-connection/index.d.ts +10 -0
- package/src/lib/peer-connection/types.d.ts +167 -0
- package/src/lib/session/CoreRTCSession.d.ts +215 -0
- package/src/lib/session/index.d.ts +2 -0
- package/src/lib/simulcast/simulcastCommonPublisher.d.ts +4 -0
- package/src/lib/unisphere-sample.d.ts +50 -0
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kaltura-sdk/rtc-core",
|
|
3
|
+
"version": "1.25.0",
|
|
4
|
+
"author": "kaltura",
|
|
5
|
+
"license": "AGPL-3.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/kaltura/rtc"
|
|
9
|
+
},
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@unisphere/core": "^1.91.1",
|
|
13
|
+
"bowser": "^2.13.1",
|
|
14
|
+
"emittery": "^1.2.0",
|
|
15
|
+
"webrtc-adapter": "^9.0.3"
|
|
16
|
+
},
|
|
17
|
+
"module": "./index.esm.js",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"registry": "https://registry.npmjs.org"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import Bowser from 'bowser';
|
|
2
|
+
/**
|
|
3
|
+
* Browser detection and information utility
|
|
4
|
+
* Uses Bowser library to parse user agent and provide browser/platform information
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* import { browserDetector } from '@kaltura-corp/unisphere-rtc-core';
|
|
8
|
+
*
|
|
9
|
+
* if (browserDetector.isChrome()) {
|
|
10
|
+
* console.log('Running in Chrome');
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* if (browserDetector.isMobile()) {
|
|
14
|
+
* console.log('Running on mobile device');
|
|
15
|
+
* }
|
|
16
|
+
*/
|
|
17
|
+
declare class BrowserDetector {
|
|
18
|
+
private browser;
|
|
19
|
+
private parsedData;
|
|
20
|
+
constructor();
|
|
21
|
+
/**
|
|
22
|
+
* Check if current browser is Chrome
|
|
23
|
+
* @returns true if Chrome, false otherwise
|
|
24
|
+
*/
|
|
25
|
+
isChrome(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Check if current browser is Firefox
|
|
28
|
+
* @returns true if Firefox, false otherwise
|
|
29
|
+
*/
|
|
30
|
+
isFirefox(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Check if current browser is Safari
|
|
33
|
+
* @returns true if Safari, false otherwise
|
|
34
|
+
*/
|
|
35
|
+
isSafari(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Check if current browser is Microsoft Edge
|
|
38
|
+
* @returns true if Edge, false otherwise
|
|
39
|
+
*/
|
|
40
|
+
isEdge(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Check if running on mobile platform
|
|
43
|
+
* @returns true if mobile, false otherwise
|
|
44
|
+
*/
|
|
45
|
+
isMobile(): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Check if running on desktop platform
|
|
48
|
+
* @returns true if desktop, false otherwise
|
|
49
|
+
*/
|
|
50
|
+
isDesktop(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Check if running in Electron
|
|
53
|
+
* @returns true if Electron, false otherwise
|
|
54
|
+
*/
|
|
55
|
+
isElectron(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Check if browser version satisfies given constraints
|
|
58
|
+
* @param constraints - Browser version constraints (e.g., { chrome: '>=65', firefox: '>=59' })
|
|
59
|
+
* @returns true if browser satisfies constraints, false otherwise
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* browserDetector.satisfies({ chrome: '>=65', firefox: '>=59', safari: '>=15' })
|
|
63
|
+
*/
|
|
64
|
+
satisfies(constraints: Bowser.Parser.checkTree): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Get browser name
|
|
67
|
+
* @returns Browser name (e.g., 'Chrome', 'Firefox', 'Safari') or undefined if not detected
|
|
68
|
+
*/
|
|
69
|
+
getBrowserName(): string | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Get browser version
|
|
72
|
+
* @returns Browser version string or undefined if not detected
|
|
73
|
+
*/
|
|
74
|
+
getBrowserVersion(): string | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Get OS name
|
|
77
|
+
* @returns OS name (e.g., 'macOS', 'Windows', 'iOS', 'Android') or undefined if not detected
|
|
78
|
+
*/
|
|
79
|
+
getOSName(): string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Get platform type
|
|
82
|
+
* @returns Platform type ('desktop', 'mobile', 'tablet') or undefined if not detected
|
|
83
|
+
*/
|
|
84
|
+
getPlatformType(): string | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Get full parsed browser data
|
|
87
|
+
* @returns Parsed result containing browser, OS, and platform information
|
|
88
|
+
*/
|
|
89
|
+
getParsedData(): Bowser.Parser.ParsedResult | null;
|
|
90
|
+
/**
|
|
91
|
+
* Check if browser detection is available
|
|
92
|
+
* @returns true if browser detection succeeded, false otherwise
|
|
93
|
+
*/
|
|
94
|
+
isAvailable(): boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Singleton instance of BrowserDetector
|
|
98
|
+
* Use this to access browser detection functionality throughout the application
|
|
99
|
+
*/
|
|
100
|
+
export declare const browserDetector: BrowserDetector;
|
|
101
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isTrackFromDevice(track: MediaStreamTrack, deviceId: string): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const GlobalEmmiter: any;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { StreamLockType } from '../media/types';
|
|
2
|
+
export declare function getVideoTrackInfo(track: MediaStreamTrack | null, userId: string): {
|
|
3
|
+
deviceId: string | null;
|
|
4
|
+
label: string | null;
|
|
5
|
+
height: number;
|
|
6
|
+
width: number;
|
|
7
|
+
fps: number | null;
|
|
8
|
+
logStr: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function getStreamTracks(stream: MediaStream | null, trackType?: string | null): MediaStreamTrack[] | null;
|
|
11
|
+
type DefaultVideoMediaConstraintsType = {
|
|
12
|
+
desiredWidth: number;
|
|
13
|
+
desiredHeight: number;
|
|
14
|
+
desiredFrameRate: number;
|
|
15
|
+
bwPercentage: number;
|
|
16
|
+
streamLock: StreamLockType;
|
|
17
|
+
facingMode?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare const defaultGetUserMediaConstraints: DefaultVideoMediaConstraintsType;
|
|
20
|
+
export declare function getStreamTracksLogStr(stream: MediaStream, userId: string, addLabels?: boolean): string;
|
|
21
|
+
export declare function getAudioTrackInfo(track: MediaStreamTrack, userId: string): {
|
|
22
|
+
deviceId: string | null;
|
|
23
|
+
label: string | null;
|
|
24
|
+
enabled: boolean | null;
|
|
25
|
+
muted: boolean | null;
|
|
26
|
+
readyState: MediaStreamTrackState | null;
|
|
27
|
+
logStr: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function getFirstStreamTrack(stream: MediaStream | null): MediaStreamTrack | null;
|
|
30
|
+
export declare function trackChanged(prevTrack: MediaStreamTrack | null, newTrack: MediaStreamTrack | null): boolean;
|
|
31
|
+
export declare function fixDimensionsByTrack(dimensions: {
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
}, maxDimensions: {
|
|
35
|
+
height: number;
|
|
36
|
+
width: number;
|
|
37
|
+
}): {
|
|
38
|
+
width: number;
|
|
39
|
+
height: number;
|
|
40
|
+
};
|
|
41
|
+
export declare function stopTrack(track: MediaStreamTrack | null, isBrowserSafari?: boolean): void;
|
|
42
|
+
export declare function removeStreamTracks(stream: MediaStream | null): void;
|
|
43
|
+
export declare function getPeerSendersTracks(peer: RTCPeerConnection, trackType: string): RTCRtpSender[] | null;
|
|
44
|
+
export declare function isTrackFromDevice(track: MediaStreamTrack | null, deviceId: string): boolean;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { UnisphereLoggerType } from '@unisphere/core';
|
|
2
|
+
export declare enum JanusSdpMunge {
|
|
3
|
+
publicIp = "publicIp",
|
|
4
|
+
privateIp = "privateIp",
|
|
5
|
+
priority = "priority"
|
|
6
|
+
}
|
|
7
|
+
export interface OpusAttributes {
|
|
8
|
+
stereo?: number;
|
|
9
|
+
'sprop-stereo'?: number;
|
|
10
|
+
maxaveragebitrate?: number;
|
|
11
|
+
maxplaybackrate?: number;
|
|
12
|
+
cbr?: number;
|
|
13
|
+
useinbandfec?: number;
|
|
14
|
+
usedtx?: number;
|
|
15
|
+
maxptime?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function setDTX(sdp: string): string;
|
|
18
|
+
export declare function sdpForceCodec(which: 'audio' | 'video', codec: string, sdp: string | undefined): string;
|
|
19
|
+
export interface SdpManipulateResult {
|
|
20
|
+
sdp: string;
|
|
21
|
+
janusPrivateIp: string | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function sdpManipulateJanusSdp(sdp: string, SdpMungeType: JanusSdpMunge, janusPublicIp: string, logger: UnisphereLoggerType): SdpManipulateResult;
|
|
24
|
+
export declare function sdpLimitBw(sdp: string, bwKbps: number, bwAudioKbps: number, userId: string | number, isFirefox: boolean, logger: UnisphereLoggerType): string;
|
|
25
|
+
export declare function NumCandidatesInSdp(sdp: string): number;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { browserDetector } from './BrowserDetector';
|
|
2
|
+
/**
|
|
3
|
+
* Check if current platform is mobile
|
|
4
|
+
* @returns true if mobile browser, false otherwise
|
|
5
|
+
*/
|
|
6
|
+
export declare function isMobileBrowser(): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Check if current browser is Firefox
|
|
9
|
+
* @returns true if Firefox, false otherwise
|
|
10
|
+
*/
|
|
11
|
+
export declare function isFirefoxBrowser(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Check if current browser is Safari
|
|
14
|
+
* @returns true if Safari, false otherwise
|
|
15
|
+
*/
|
|
16
|
+
export declare function isSafariBrowser(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Check if current browser is Chrome
|
|
19
|
+
* @returns true if Chrome, false otherwise
|
|
20
|
+
*/
|
|
21
|
+
export declare function isChromeBrowser(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Check if current browser is Microsoft Edge
|
|
24
|
+
* @returns true if Edge, false otherwise
|
|
25
|
+
*/
|
|
26
|
+
export declare function isEdgeBrowser(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Check if running in Electron
|
|
29
|
+
* @returns true if Electron, false otherwise
|
|
30
|
+
*/
|
|
31
|
+
export declare function isElectron(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Check if running on desktop platform
|
|
34
|
+
* @returns true if desktop, false otherwise
|
|
35
|
+
*/
|
|
36
|
+
export declare function isDesktopBrowser(): boolean;
|
|
37
|
+
export { browserDetector };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if provided object is empty
|
|
3
|
+
*
|
|
4
|
+
* @param {Object} obj target object
|
|
5
|
+
* @returns {boolean} result
|
|
6
|
+
*/
|
|
7
|
+
export declare function isObjectEmpty(obj: object): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Extract the base URL from a full URL or path
|
|
10
|
+
* For CDN URLs (http/https), extracts protocol + host + first path segment
|
|
11
|
+
* For local paths, removes the filename
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* getBaseUrl('https://cdn.example.com/static/file.js') // 'https://cdn.example.com/static'
|
|
15
|
+
* getBaseUrl('./worklets/file.js') // './worklets'
|
|
16
|
+
*
|
|
17
|
+
* @param {string} path - The full URL or path
|
|
18
|
+
* @returns {string} The base URL/path without the filename
|
|
19
|
+
*/
|
|
20
|
+
export declare function getBaseUrl(path: string): string;
|
|
21
|
+
export declare function truncToNDecimalDigits(num: number, n: number): number;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { publisherQualityCheckStageType } from '../simulcast/simulcastCommonPublisher';
|
|
2
|
+
export type AudioMixIntervalStatsObj = {
|
|
3
|
+
time: number;
|
|
4
|
+
totalPackets: number;
|
|
5
|
+
totalBytes: number;
|
|
6
|
+
packetsLost: number;
|
|
7
|
+
jitter: number;
|
|
8
|
+
audioLevel: number;
|
|
9
|
+
totalAudioEnergy: number;
|
|
10
|
+
totalSamplesDuration: number;
|
|
11
|
+
totalRtt: number;
|
|
12
|
+
numRttMeasurements: number;
|
|
13
|
+
outRtt?: number;
|
|
14
|
+
outRemoteAudioJitter?: number;
|
|
15
|
+
deltaKbps?: number;
|
|
16
|
+
deltaLostPct?: number;
|
|
17
|
+
deltaNormEnergyDelta?: number;
|
|
18
|
+
};
|
|
19
|
+
export type AudioStatsObj = {
|
|
20
|
+
time: number;
|
|
21
|
+
iceRtt: number;
|
|
22
|
+
incoming: AudioMixIntervalStatsObj | null;
|
|
23
|
+
outgoing: AudioMixIntervalStatsObj | null;
|
|
24
|
+
};
|
|
25
|
+
export declare const kBandwidthAlertThresholdMsec: number;
|
|
26
|
+
export declare const kAudioAlertThresholdMsec: number;
|
|
27
|
+
export type AudioStatsResObj = {
|
|
28
|
+
stats: AudioStatsObj;
|
|
29
|
+
logStr: string;
|
|
30
|
+
};
|
|
31
|
+
export declare enum AudioAlerts {
|
|
32
|
+
PacketsLoss = "PacketsLoss",
|
|
33
|
+
HighRtt = "HighRtt",
|
|
34
|
+
HighJitter = "HighJitter",// High jitter or rtt
|
|
35
|
+
Distortion = "Distortion"
|
|
36
|
+
}
|
|
37
|
+
export type ErrAudioQualityAlertObj = {
|
|
38
|
+
alertType?: AudioAlerts;
|
|
39
|
+
alertValue?: number;
|
|
40
|
+
};
|
|
41
|
+
export type CheckStatsResObj = {
|
|
42
|
+
incoming: ErrAudioQualityAlertObj | null;
|
|
43
|
+
outgoing: ErrAudioQualityAlertObj | null;
|
|
44
|
+
};
|
|
45
|
+
export declare function checkAudioStats(audioStats: AudioStatsObj, streamId: string): CheckStatsResObj;
|
|
46
|
+
export declare function prepareAudioStats(curTime: number, prevStats: AudioStatsObj, curStats: AudioStatsObj, activeIceInfo: any, isMainAudioMix: boolean, checkStage: publisherQualityCheckStageType, noLogStrHeaders: boolean): AudioStatsResObj;
|
|
47
|
+
export declare function getAudioStats(statsReport: any[], isPublisher: boolean, bDirectional: boolean): AudioStatsObj;
|
|
48
|
+
export declare function getAudioTrackRTCStats(statsReport: any): {
|
|
49
|
+
concealedSamples: any;
|
|
50
|
+
totalSamplesReceived: any;
|
|
51
|
+
silentConcealedSamples: any;
|
|
52
|
+
};
|
|
53
|
+
export declare function getAudioSourceStats(statsReport: any): {
|
|
54
|
+
totalAudioEnergy: any;
|
|
55
|
+
audioLevel: any;
|
|
56
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { AudioStatsResObj, CheckStatsResObj } from './webrtcAudioStats';
|
|
2
|
+
export type StreamRidType = string;
|
|
3
|
+
export declare const k_singleRID: StreamRidType;
|
|
4
|
+
export declare const kQcMsecDefault: number;
|
|
5
|
+
export declare const kQcStartAfterConnected: number;
|
|
6
|
+
export type VideoStreamStatsCommonObj = {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
totalPackets: number;
|
|
10
|
+
totalBytes: number;
|
|
11
|
+
totalPacketsLost: number;
|
|
12
|
+
nacks: number;
|
|
13
|
+
pliCount: number;
|
|
14
|
+
firCount: number;
|
|
15
|
+
jitter: number;
|
|
16
|
+
curRtt: number;
|
|
17
|
+
framesEncDec: number;
|
|
18
|
+
deltaPackets: number;
|
|
19
|
+
deltaLostPct: number;
|
|
20
|
+
deltaNacks: number;
|
|
21
|
+
deltaNackPct: number;
|
|
22
|
+
deltaBytes: number;
|
|
23
|
+
deltaVideoKbps: number;
|
|
24
|
+
deltaFramesEncDec: number;
|
|
25
|
+
deltaPlis: number;
|
|
26
|
+
deltaPliPct: number;
|
|
27
|
+
};
|
|
28
|
+
export type ViewerStatsObj = {
|
|
29
|
+
time: number;
|
|
30
|
+
durationMsec: number;
|
|
31
|
+
statsAvailBitrateKbps: number;
|
|
32
|
+
streamStats: VideoStreamStatsCommonObj;
|
|
33
|
+
framesReceived: number;
|
|
34
|
+
inFramesDropped: number;
|
|
35
|
+
inFreezeCount: number;
|
|
36
|
+
inTotalFreezeDuration: number;
|
|
37
|
+
inJitterBufDelay: number;
|
|
38
|
+
deltaFreezeDuration: number;
|
|
39
|
+
deltaAudioKbps: number;
|
|
40
|
+
deltaFps: number;
|
|
41
|
+
videoScoreStr: string;
|
|
42
|
+
audioStats: AudioStatsResObj | null;
|
|
43
|
+
audioStatsCheck: CheckStatsResObj | null;
|
|
44
|
+
deltaAudioBytes: number;
|
|
45
|
+
};
|
|
46
|
+
export declare class QualityLimitationDurations {
|
|
47
|
+
none: number;
|
|
48
|
+
bandwidth: number;
|
|
49
|
+
cpu: number;
|
|
50
|
+
other: number;
|
|
51
|
+
constructor(none?: number, bandwidth?: number, cpu?: number, other?: number);
|
|
52
|
+
}
|
|
53
|
+
export type PublisherVideoStreamStatsObj = {
|
|
54
|
+
active: boolean;
|
|
55
|
+
available: boolean;
|
|
56
|
+
rid: string;
|
|
57
|
+
genStats?: VideoStreamStatsCommonObj;
|
|
58
|
+
framesSent?: number;
|
|
59
|
+
currentFps?: number;
|
|
60
|
+
deltaFramesSent?: number;
|
|
61
|
+
};
|
|
62
|
+
export type PublisherStatsObj = {
|
|
63
|
+
time: number;
|
|
64
|
+
durationMsec: number;
|
|
65
|
+
availBitrateKbps: number;
|
|
66
|
+
streamsStats: PublisherVideoStreamStatsObj[];
|
|
67
|
+
qualityLimitationReason: string;
|
|
68
|
+
qualityLimitationDurationsStr: string;
|
|
69
|
+
qualityLimitationDurations: QualityLimitationDurations;
|
|
70
|
+
videoScoreStr: string;
|
|
71
|
+
totalDeltaVideoBytes: number;
|
|
72
|
+
audioStats: AudioStatsResObj | null;
|
|
73
|
+
lastAudioErr: CheckStatsResObj | null;
|
|
74
|
+
lastAudioErrTime: number;
|
|
75
|
+
deltaAudioBytes: number;
|
|
76
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Manager
|
|
3
|
+
* Extracted from src/components/media-devices.js
|
|
4
|
+
* Manages media device enumeration, selection, and getUserMedia operations
|
|
5
|
+
*/
|
|
6
|
+
import { UserMediaManager, UserMediaConfig, DefaultVideoMediaConstraintsType } from './UserMediaManager';
|
|
7
|
+
export type EnumerateDevicesResult = {
|
|
8
|
+
audioDevices: Record<string, MediaDeviceInfo>;
|
|
9
|
+
videoDevices: Record<string, MediaDeviceInfo>;
|
|
10
|
+
audioOutputDevices: Record<string, MediaDeviceInfo>;
|
|
11
|
+
unclassifiedDevices: Record<string, MediaDeviceInfo>;
|
|
12
|
+
};
|
|
13
|
+
export type UserDevicesType = Pick<DeviceEnumerationResult, 'availableDevices' | 'selectedDevices'>;
|
|
14
|
+
export interface DeviceManagerConfig {
|
|
15
|
+
storage?: {
|
|
16
|
+
getItem: (key: string) => string | null;
|
|
17
|
+
setItem: (key: string, value: string) => void;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface InitialConstraintsConfig {
|
|
21
|
+
audio?: {
|
|
22
|
+
echoCancellation?: boolean;
|
|
23
|
+
autoGainControl?: boolean;
|
|
24
|
+
noiseReduction?: boolean;
|
|
25
|
+
};
|
|
26
|
+
video?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare enum DevicesEvents {
|
|
29
|
+
deviceListChanged = "deviceListChanged",
|
|
30
|
+
deviceChanged = "deviceChanged",
|
|
31
|
+
deviceDisappeared = "deviceDisappeared"
|
|
32
|
+
}
|
|
33
|
+
export interface DeviceEnumerationResult {
|
|
34
|
+
availableDevices: EnumerateDevicesResult;
|
|
35
|
+
selectedDevices: {
|
|
36
|
+
audioDevice: MediaDeviceInfo | null;
|
|
37
|
+
videoDevice: MediaDeviceInfo | null;
|
|
38
|
+
audioOutputDevice: MediaDeviceInfo | null;
|
|
39
|
+
};
|
|
40
|
+
enumeratedDevices: MediaDeviceInfo[];
|
|
41
|
+
devicesCount: {
|
|
42
|
+
audioInput: number;
|
|
43
|
+
videoInput: number;
|
|
44
|
+
audioOutput: number;
|
|
45
|
+
unclassified: number;
|
|
46
|
+
};
|
|
47
|
+
prevDevices: {
|
|
48
|
+
audioDevice: MediaDeviceInfo | null;
|
|
49
|
+
videoDevice: MediaDeviceInfo | null;
|
|
50
|
+
audioOutputDevice: MediaDeviceInfo | null;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export declare enum DeviceType {
|
|
54
|
+
AudioInput = "audioinput",
|
|
55
|
+
VideoInput = "videoinput",
|
|
56
|
+
AudioOutput = "audiooutput"
|
|
57
|
+
}
|
|
58
|
+
export declare class DeviceManager {
|
|
59
|
+
private logger;
|
|
60
|
+
private storage;
|
|
61
|
+
availableDevices: EnumerateDevicesResult;
|
|
62
|
+
selectedDevices: {
|
|
63
|
+
audioDevice: MediaDeviceInfo | null;
|
|
64
|
+
videoDevice: MediaDeviceInfo | null;
|
|
65
|
+
audioOutputDevice: MediaDeviceInfo | null;
|
|
66
|
+
};
|
|
67
|
+
failedDevices: {
|
|
68
|
+
audioDevices: string[];
|
|
69
|
+
videoDevices: string[];
|
|
70
|
+
audioOutputDevices: string[];
|
|
71
|
+
unclassifiedDevices: string[];
|
|
72
|
+
};
|
|
73
|
+
userMediaManager: UserMediaManager;
|
|
74
|
+
private currentVideoConstraints;
|
|
75
|
+
constructor(config: DeviceManagerConfig, initialUserMediaConfig: UserMediaConfig);
|
|
76
|
+
private getOndevicechangeHandler;
|
|
77
|
+
resetAvailableDevices(): void;
|
|
78
|
+
resetSelectedDevices(): void;
|
|
79
|
+
resetFailedDevices(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Enumerate all available media devices
|
|
82
|
+
*/
|
|
83
|
+
enumerateDevices(): Promise<DeviceEnumerationResult | null>;
|
|
84
|
+
private handleDeviceEnumeration;
|
|
85
|
+
/**
|
|
86
|
+
* Set default devices (from storage if available)
|
|
87
|
+
*/
|
|
88
|
+
private setDefaultDevices;
|
|
89
|
+
/**
|
|
90
|
+
* Change device selection
|
|
91
|
+
*/
|
|
92
|
+
changeDeviceSelection(deviceType: DeviceType, device: string, isRevalidate?: boolean): void;
|
|
93
|
+
private revalidateDefaultDevice;
|
|
94
|
+
/**
|
|
95
|
+
* Convert 'default' device ID to actual device ID
|
|
96
|
+
*/
|
|
97
|
+
convertDefaultDeviceToDeviceId(deviceList: Record<string, MediaDeviceInfo>, deviceId: string): string | null;
|
|
98
|
+
/**
|
|
99
|
+
* Get device info from device label
|
|
100
|
+
*/
|
|
101
|
+
getDeviceInfoFromDeviceLabel(type: DeviceType, label: string): MediaDeviceInfo | null;
|
|
102
|
+
addFailedDevice(deviceType: DeviceType, deviceId: string): void;
|
|
103
|
+
checkFailedDevice(deviceType: DeviceType, deviceId: string): boolean;
|
|
104
|
+
associateTrackWithDevice(mediaTrack: MediaStreamTrack | null): void;
|
|
105
|
+
/**
|
|
106
|
+
* Change audio output device (speaker) for all media elements
|
|
107
|
+
* @param deviceId - Device ID to switch to
|
|
108
|
+
* @returns Promise<boolean> - Success status
|
|
109
|
+
*/
|
|
110
|
+
changeAudioOutput(deviceId?: string): Promise<boolean>;
|
|
111
|
+
private setElementsSinkId;
|
|
112
|
+
/**
|
|
113
|
+
* Helper method to set sinkId on a media element with retry logic
|
|
114
|
+
* @param element - HTML media element
|
|
115
|
+
* @param deviceId - Device ID to set
|
|
116
|
+
* @param attempt - Current attempt number
|
|
117
|
+
*/
|
|
118
|
+
private setElementSinkId;
|
|
119
|
+
buildMediaConstraints(config?: {
|
|
120
|
+
video: {
|
|
121
|
+
shouldRequestVideo: boolean;
|
|
122
|
+
constraints?: DefaultVideoMediaConstraintsType | {
|
|
123
|
+
facingMode: {
|
|
124
|
+
exact: 'user';
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
deviceId?: string;
|
|
128
|
+
};
|
|
129
|
+
audio: {
|
|
130
|
+
shouldRequestAudio: boolean;
|
|
131
|
+
deviceId?: string;
|
|
132
|
+
};
|
|
133
|
+
audioDeviceId?: string;
|
|
134
|
+
videoDeviceId?: string;
|
|
135
|
+
}): MediaStreamConstraints;
|
|
136
|
+
}
|
|
137
|
+
export default DeviceManager;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { StreamLockType } from '../media/types';
|
|
2
|
+
export interface UserMediaConfig {
|
|
3
|
+
audio: {
|
|
4
|
+
echoCancellation: boolean;
|
|
5
|
+
autoGainControl: boolean;
|
|
6
|
+
noiseSuppression: boolean;
|
|
7
|
+
};
|
|
8
|
+
video: boolean;
|
|
9
|
+
}
|
|
10
|
+
export type DefaultVideoMediaConstraintsType = {
|
|
11
|
+
desiredWidth: number;
|
|
12
|
+
desiredHeight: number;
|
|
13
|
+
desiredFrameRate: number;
|
|
14
|
+
bwPercentage: number;
|
|
15
|
+
streamLock: StreamLockType;
|
|
16
|
+
facingMode?: string;
|
|
17
|
+
};
|
|
18
|
+
export declare class UserMediaManager {
|
|
19
|
+
defaultConstrains: UserMediaConfig;
|
|
20
|
+
private logger;
|
|
21
|
+
constructor(initialConstraintsConfig: UserMediaConfig);
|
|
22
|
+
private isStreamProcessingNeeded;
|
|
23
|
+
private isSimulcastRoom;
|
|
24
|
+
buildMediaConstraintsInternal(config?: {
|
|
25
|
+
video: {
|
|
26
|
+
shouldRequestVideo: boolean;
|
|
27
|
+
constraints?: DefaultVideoMediaConstraintsType | {
|
|
28
|
+
facingMode: {
|
|
29
|
+
exact: 'user';
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
deviceId?: string;
|
|
33
|
+
};
|
|
34
|
+
audio: {
|
|
35
|
+
shouldRequestAudio: boolean;
|
|
36
|
+
deviceId?: string;
|
|
37
|
+
};
|
|
38
|
+
audioDeviceId?: string;
|
|
39
|
+
videoDeviceId?: string;
|
|
40
|
+
}): MediaStreamConstraints;
|
|
41
|
+
buildAudioConstraints(config: {
|
|
42
|
+
audio: {
|
|
43
|
+
shouldRequestAudio: boolean;
|
|
44
|
+
deviceId?: string;
|
|
45
|
+
};
|
|
46
|
+
}): boolean | MediaTrackConstraints;
|
|
47
|
+
buildVideoConstraints(config?: {
|
|
48
|
+
shouldRequestVideo: boolean;
|
|
49
|
+
constraints: DefaultVideoMediaConstraintsType;
|
|
50
|
+
}, deviceId?: string): boolean | MediaTrackConstraints;
|
|
51
|
+
removeUnsupportedConstraints(constraints: MediaStreamConstraints): void;
|
|
52
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Window {
|
|
3
|
+
globalAudioContext?: AudioContext;
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* AudioAnalyzer: Pure audio analysis class using Web Audio API
|
|
8
|
+
* Samples audio track and detects volume levels for speaking indication
|
|
9
|
+
* Based on kme-web-sdk sound-indicator.js but stripped to pure audio logic
|
|
10
|
+
*/
|
|
11
|
+
export declare class AudioAnalyzer {
|
|
12
|
+
private logger;
|
|
13
|
+
private audioContext;
|
|
14
|
+
private analyser;
|
|
15
|
+
private source;
|
|
16
|
+
private dataArray;
|
|
17
|
+
private sampleTimerId;
|
|
18
|
+
private audioTrack;
|
|
19
|
+
private readonly fftSize;
|
|
20
|
+
private readonly smoothingTimeConstant;
|
|
21
|
+
private readonly minDecibels;
|
|
22
|
+
private readonly maxDecibels;
|
|
23
|
+
private readonly sampleIntervalMs;
|
|
24
|
+
private threshold;
|
|
25
|
+
private isSpeaking;
|
|
26
|
+
private hasStateListeners;
|
|
27
|
+
private hasVolumeListeners;
|
|
28
|
+
constructor();
|
|
29
|
+
/**
|
|
30
|
+
* Start analyzing audio from a track
|
|
31
|
+
* @param track - Audio track to analyze (MUST be a clone that stays unmuted)
|
|
32
|
+
* @param threshold - Optional volume threshold for speaking detection (default: 300)
|
|
33
|
+
*/
|
|
34
|
+
start(track: MediaStreamTrack, threshold?: number): void;
|
|
35
|
+
/**
|
|
36
|
+
* Stop analyzing audio
|
|
37
|
+
*/
|
|
38
|
+
stop(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Check if analyzer is currently running
|
|
41
|
+
*/
|
|
42
|
+
isRunning(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Set speaking threshold
|
|
45
|
+
* @param threshold - Volume threshold for speaking detection
|
|
46
|
+
*/
|
|
47
|
+
setThreshold(threshold: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* Update listener status for performance optimization
|
|
50
|
+
* Called by CoreRTCSession when listeners are added/removed
|
|
51
|
+
* @param hasStateListeners - Whether there are speakingStateChanged listeners
|
|
52
|
+
* @param hasVolumeListeners - Whether there are audioVolumeLevel listeners
|
|
53
|
+
*/
|
|
54
|
+
updateListenerStatus(hasStateListeners: boolean, hasVolumeListeners: boolean): void;
|
|
55
|
+
/**
|
|
56
|
+
* Sample audio and emit events (if listeners exist)
|
|
57
|
+
* Called every 50ms by setInterval
|
|
58
|
+
*/
|
|
59
|
+
private sampleAudio;
|
|
60
|
+
}
|