@kaltura-sdk/rtc-avatar 1.32.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 +10077 -0
- package/package.json +21 -0
- package/src/index.d.ts +6 -0
- package/src/lib/connection/EselfRTCConnection.d.ts +186 -0
- package/src/lib/connection/index.d.ts +3 -0
- package/src/lib/connection/types.d.ts +94 -0
- package/src/lib/dom/EselfDOMManager.d.ts +80 -0
- package/src/lib/dom/index.d.ts +1 -0
- package/src/lib/eself-demo.d.ts +1 -0
- package/src/lib/session/EselfSession.d.ts +394 -0
- package/src/lib/session/index.d.ts +1 -0
- package/src/lib/signaling/EselfSignaling.d.ts +76 -0
- package/src/lib/signaling/KasSignalingAdapter.d.ts +55 -0
- package/src/lib/signaling/SrsSignalingAdapter.d.ts +50 -0
- package/src/lib/signaling/WhepSignalingAdapter.d.ts +70 -0
- package/src/lib/signaling/index.d.ts +5 -0
- package/src/lib/signaling/types.d.ts +34 -0
- package/src/lib/utils/RequestsDebouncer.d.ts +15 -0
- package/src/lib/utils/compressedLogger.d.ts +95 -0
- package/src/lib/utils/logBuffer.d.ts +47 -0
- package/src/lib/utils/logsCollector.d.ts +28 -0
- package/src/lib/utils/runWithRetry.d.ts +10 -0
- package/src/lib/utils/tests/testUtils.d.ts +2 -0
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kaltura-sdk/rtc-avatar",
|
|
3
|
+
"version": "1.32.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
|
+
"@kaltura-sdk/rtc-core": "^1.25.0",
|
|
13
|
+
"@unisphere/core": "^1.91.1",
|
|
14
|
+
"lodash.isequal": "^4.5.0"
|
|
15
|
+
},
|
|
16
|
+
"module": "./index.esm.js",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"registry": "https://registry.npmjs.org"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { PeerConnection, PeerConnectionConfig, IceConfiguration, CoreRTCSession, TrackKind, GetUserMediaEveObj, VideoSenderConfig } from '@kaltura-sdk/rtc-core';
|
|
2
|
+
import { EselfSignaling } from '../signaling';
|
|
3
|
+
import { ConnectionType, ConnectionEvent, ConnectionEventPayloads, ConnectionState, MediaTrackState } from './types';
|
|
4
|
+
import { IceCandidateData } from '../session';
|
|
5
|
+
/**
|
|
6
|
+
* Options for configuring the RTC connection behavior.
|
|
7
|
+
*/
|
|
8
|
+
export interface EselfRTCConnectionOptions {
|
|
9
|
+
/** Force video codec (e.g. 'H264', 'VP8') */
|
|
10
|
+
videoCodec?: string;
|
|
11
|
+
/** Force audio codec (e.g. 'opus') */
|
|
12
|
+
audioCodec?: string;
|
|
13
|
+
/** Enable trickle ICE for this connection */
|
|
14
|
+
enableTrickleIce?: boolean;
|
|
15
|
+
/** Degradation preference for the video sender */
|
|
16
|
+
videoDegradationPreference?: RTCDegradationPreference;
|
|
17
|
+
/** Content hint for the video track */
|
|
18
|
+
videoContentHint?: string;
|
|
19
|
+
/** Maximum frame rate for the video sender */
|
|
20
|
+
videoMaxFps?: number;
|
|
21
|
+
/** Maximum bitrate in Kilobits for the video sender */
|
|
22
|
+
videoMaxBitrateKbps?: number;
|
|
23
|
+
/** Scale resolution down factor for the video sender (1.0 = no scaling) */
|
|
24
|
+
videoScaleResolutionDownBy?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Event listener type for connection events
|
|
28
|
+
*/
|
|
29
|
+
type EventListener<T extends ConnectionEvent> = (payload: ConnectionEventPayloads[T]) => void;
|
|
30
|
+
/**
|
|
31
|
+
* EselfRTCConnection: Per-connection coordinator that wraps ONE core SDK PeerConnection
|
|
32
|
+
*
|
|
33
|
+
* Purpose:
|
|
34
|
+
* - Wraps a single PeerConnection from the core SDK
|
|
35
|
+
* - Handles signaling for this connection
|
|
36
|
+
* - Emits simplified events to EselfSession
|
|
37
|
+
* - Manages connection lifecycle (NO retry logic in Phase 2a)
|
|
38
|
+
*
|
|
39
|
+
* Two modes:
|
|
40
|
+
* - Publisher: Sends local stream (e.g., ASR audio publishing)
|
|
41
|
+
* - Viewer: Receives remote stream only (e.g., STV avatar viewing)
|
|
42
|
+
*
|
|
43
|
+
* Events emitted:
|
|
44
|
+
* - pcConnected: Connection established
|
|
45
|
+
* - pcConnectionFailed: Connection failed
|
|
46
|
+
* - pcTrackReceived: Remote track received
|
|
47
|
+
* - pcIceCandidate: Local ICE candidate generated
|
|
48
|
+
*/
|
|
49
|
+
export declare class EselfRTCConnection {
|
|
50
|
+
private connectionId;
|
|
51
|
+
private connectionType;
|
|
52
|
+
private peerConnection;
|
|
53
|
+
private signalingClient;
|
|
54
|
+
private logger;
|
|
55
|
+
private state;
|
|
56
|
+
private localStream;
|
|
57
|
+
private videoElementId;
|
|
58
|
+
private options;
|
|
59
|
+
useRelay: boolean;
|
|
60
|
+
private audioState;
|
|
61
|
+
private videoState;
|
|
62
|
+
private isReconnecting;
|
|
63
|
+
private requestsDebouncer;
|
|
64
|
+
private hwMuteDebounceTimer;
|
|
65
|
+
private readonly HW_MUTE_DEBOUNCE_MS;
|
|
66
|
+
private coreRTCSession;
|
|
67
|
+
private getUserMediaCallback;
|
|
68
|
+
private eventListeners;
|
|
69
|
+
constructor(connectionId: string, connectionType: ConnectionType, signalingClient: EselfSignaling, createPeerConnection: (connectionId: string, config: PeerConnectionConfig, callbacks: any) => PeerConnection, coreRTCSession: CoreRTCSession, getUserMediaCallback: (audio: boolean, video: boolean, elementId?: string, isDeviceChange?: boolean) => Promise<{
|
|
70
|
+
gumResult: GetUserMediaEveObj;
|
|
71
|
+
stream: MediaStream | null;
|
|
72
|
+
}>, options?: EselfRTCConnectionOptions);
|
|
73
|
+
/**
|
|
74
|
+
* Sets the video element ID for DOM reattachment during unmute
|
|
75
|
+
* @param elementId - The container element ID where video should be attached
|
|
76
|
+
*/
|
|
77
|
+
setVideoElementId(elementId: string | null): void;
|
|
78
|
+
/**
|
|
79
|
+
* Sets the reconnection flag
|
|
80
|
+
* @param value - True if this is a reconnection attempt
|
|
81
|
+
*/
|
|
82
|
+
setReconnecting(value: boolean): void;
|
|
83
|
+
/**
|
|
84
|
+
* Test method to manually trigger connection failed event
|
|
85
|
+
* Used for testing reconnection logic in development/testing
|
|
86
|
+
*/
|
|
87
|
+
testTriggerConnectionFailed(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Create and configure the peer connection
|
|
90
|
+
*
|
|
91
|
+
* @param iceConfig - ICE server configuration
|
|
92
|
+
* @param localStream - Optional local stream for publisher connections
|
|
93
|
+
* @param videoElementId - Optional element ID for video attachment
|
|
94
|
+
* @throws Error if connection creation fails
|
|
95
|
+
*/
|
|
96
|
+
createConnection(iceConfig: IceConfiguration, localStream?: MediaStream, videoElementId?: string): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Handle a remote offer (for viewer mode)
|
|
99
|
+
* Creates answer and sends it via signaling
|
|
100
|
+
*
|
|
101
|
+
* @param sdp - Remote SDP offer
|
|
102
|
+
*/
|
|
103
|
+
handleRemoteOffer(sdp: RTCSessionDescriptionInit): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Handle a remote answer (after sending offer)
|
|
106
|
+
*
|
|
107
|
+
* @param sdp - Remote SDP answer
|
|
108
|
+
*/
|
|
109
|
+
handleRemoteAnswer(sdp: RTCSessionDescriptionInit, videoSenderConfig?: VideoSenderConfig | null): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Handle a remote ICE candidate
|
|
112
|
+
*
|
|
113
|
+
* @param candidate - Remote ICE candidate
|
|
114
|
+
*/
|
|
115
|
+
handleRemoteICECandidate(candidate: IceCandidateData): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Register an event listener
|
|
118
|
+
*
|
|
119
|
+
* @param event - Event type
|
|
120
|
+
* @param listener - Listener function
|
|
121
|
+
*/
|
|
122
|
+
on<T extends ConnectionEvent>(event: T, listener: EventListener<T>): void;
|
|
123
|
+
/**
|
|
124
|
+
* Remove an event listener
|
|
125
|
+
*
|
|
126
|
+
* @param event - Event type
|
|
127
|
+
* @param listener - Listener function
|
|
128
|
+
*/
|
|
129
|
+
off<T extends ConnectionEvent>(event: T, listener: EventListener<T>): void;
|
|
130
|
+
/**
|
|
131
|
+
* Close the connection and clean up resources
|
|
132
|
+
*/
|
|
133
|
+
close(): void;
|
|
134
|
+
/**
|
|
135
|
+
* Get current connection state
|
|
136
|
+
*/
|
|
137
|
+
getState(): ConnectionState;
|
|
138
|
+
/**
|
|
139
|
+
* Get the underlying core SDK PeerConnection (for advanced use)
|
|
140
|
+
*/
|
|
141
|
+
getPeerConnection(): PeerConnection | null;
|
|
142
|
+
private handlePcCreated;
|
|
143
|
+
private handlePcConnected;
|
|
144
|
+
private handlePcConnectedFinal;
|
|
145
|
+
private handlePcConnectionFail;
|
|
146
|
+
private handlePcTrackEvent;
|
|
147
|
+
private handleStartPublishing;
|
|
148
|
+
private handleIceCandidate;
|
|
149
|
+
/**
|
|
150
|
+
* Generic method to mute a track using RequestsDebouncer with state comparison
|
|
151
|
+
* Protects against rapid duplicate calls from the app
|
|
152
|
+
* @param trackKind - TrackKind.AUDIO or TrackKind.VIDEO
|
|
153
|
+
*/
|
|
154
|
+
muteTrack(trackKind: TrackKind): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Generic method to unmute a track using RequestsDebouncer with state comparison
|
|
157
|
+
* Calls getUserMedia through callback to preserve constraints
|
|
158
|
+
* @param trackKind - TrackKind.AUDIO or TrackKind.VIDEO
|
|
159
|
+
*/
|
|
160
|
+
unmuteTrack(trackKind: TrackKind): Promise<boolean>;
|
|
161
|
+
muteAudio(): Promise<void>;
|
|
162
|
+
unmuteAudio(): Promise<boolean>;
|
|
163
|
+
muteVideo(): Promise<void>;
|
|
164
|
+
unmuteVideo(): Promise<boolean>;
|
|
165
|
+
/**
|
|
166
|
+
* Sets up hardware mute detection on tracks
|
|
167
|
+
* Should be called after tracks are added to connection
|
|
168
|
+
*/
|
|
169
|
+
setupHardwareMuteDetection(): void;
|
|
170
|
+
/**
|
|
171
|
+
* Handles track mute event (hardware mute detected)
|
|
172
|
+
* Uses 5-second debounce to avoid false positives
|
|
173
|
+
*/
|
|
174
|
+
private handleTrackMute;
|
|
175
|
+
/**
|
|
176
|
+
* Handles track unmute event (hardware unmute detected)
|
|
177
|
+
*/
|
|
178
|
+
private handleTrackUnmute;
|
|
179
|
+
getAudioState(): MediaTrackState;
|
|
180
|
+
getVideoState(): MediaTrackState;
|
|
181
|
+
/**
|
|
182
|
+
* Emit an event to all registered listeners
|
|
183
|
+
*/
|
|
184
|
+
private emit;
|
|
185
|
+
}
|
|
186
|
+
export default EselfRTCConnection;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { IceCandidateData } from '../session';
|
|
2
|
+
/**
|
|
3
|
+
* Connection type for EselfRTCConnection
|
|
4
|
+
*/
|
|
5
|
+
export type ConnectionType = 'publisher' | 'viewer';
|
|
6
|
+
/**
|
|
7
|
+
* Media track mute state
|
|
8
|
+
*/
|
|
9
|
+
export declare enum MediaTrackState {
|
|
10
|
+
UNMUTED = "UNMUTED",// Track active, not muted
|
|
11
|
+
MUTED = "MUTED",// Software muted by user
|
|
12
|
+
HW_MUTED = "HW_MUTED"
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* ICE configuration for peer connections
|
|
16
|
+
*/
|
|
17
|
+
export type IceConfiguration = {
|
|
18
|
+
iceServers: RTCIceServer[];
|
|
19
|
+
iceTransportPolicy?: RTCIceTransportPolicy;
|
|
20
|
+
bundlePolicy?: RTCBundlePolicy;
|
|
21
|
+
rtcpMuxPolicy?: RTCRtcpMuxPolicy;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Events emitted by EselfRTCConnection
|
|
25
|
+
*/
|
|
26
|
+
export declare enum ConnectionEvent {
|
|
27
|
+
PC_CONNECTED = "pcConnected",
|
|
28
|
+
PC_CONNECTION_FAILED = "pcConnectionFailed",
|
|
29
|
+
PC_TRACK_RECEIVED = "pcTrackReceived",
|
|
30
|
+
PC_ICE_CANDIDATE = "pcIceCandidate",
|
|
31
|
+
AUDIO_MUTED = "audio-muted",
|
|
32
|
+
AUDIO_UNMUTED = "audio-unmuted",
|
|
33
|
+
VIDEO_MUTED = "video-muted",
|
|
34
|
+
VIDEO_UNMUTED = "video-unmuted",
|
|
35
|
+
HW_AUDIO_MUTED = "hw-audio-muted",
|
|
36
|
+
HW_AUDIO_UNMUTED = "hw-audio-unmuted"
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Connection event payloads
|
|
40
|
+
*/
|
|
41
|
+
export type ConnectionEventPayloads = {
|
|
42
|
+
[ConnectionEvent.PC_CONNECTED]: {
|
|
43
|
+
connectionId: string;
|
|
44
|
+
};
|
|
45
|
+
[ConnectionEvent.PC_CONNECTION_FAILED]: {
|
|
46
|
+
connectionId: string;
|
|
47
|
+
error: Error;
|
|
48
|
+
};
|
|
49
|
+
[ConnectionEvent.PC_TRACK_RECEIVED]: {
|
|
50
|
+
connectionId: string;
|
|
51
|
+
stream: MediaStream;
|
|
52
|
+
track: MediaStreamTrack;
|
|
53
|
+
};
|
|
54
|
+
[ConnectionEvent.PC_ICE_CANDIDATE]: {
|
|
55
|
+
connectionId: string;
|
|
56
|
+
iceCandidate: IceCandidateData | null;
|
|
57
|
+
};
|
|
58
|
+
[ConnectionEvent.AUDIO_MUTED]: {
|
|
59
|
+
connectionId: string;
|
|
60
|
+
state: MediaTrackState;
|
|
61
|
+
};
|
|
62
|
+
[ConnectionEvent.AUDIO_UNMUTED]: {
|
|
63
|
+
connectionId: string;
|
|
64
|
+
state: MediaTrackState;
|
|
65
|
+
};
|
|
66
|
+
[ConnectionEvent.VIDEO_MUTED]: {
|
|
67
|
+
connectionId: string;
|
|
68
|
+
state: MediaTrackState;
|
|
69
|
+
};
|
|
70
|
+
[ConnectionEvent.VIDEO_UNMUTED]: {
|
|
71
|
+
connectionId: string;
|
|
72
|
+
state: MediaTrackState;
|
|
73
|
+
};
|
|
74
|
+
[ConnectionEvent.HW_AUDIO_MUTED]: {
|
|
75
|
+
connectionId: string;
|
|
76
|
+
previousState: MediaTrackState;
|
|
77
|
+
currentState: MediaTrackState;
|
|
78
|
+
};
|
|
79
|
+
[ConnectionEvent.HW_AUDIO_UNMUTED]: {
|
|
80
|
+
connectionId: string;
|
|
81
|
+
currentState: MediaTrackState;
|
|
82
|
+
message: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Connection state
|
|
87
|
+
*/
|
|
88
|
+
export declare enum ConnectionState {
|
|
89
|
+
IDLE = "idle",
|
|
90
|
+
CONNECTING = "connecting",
|
|
91
|
+
CONNECTED = "connected",
|
|
92
|
+
FAILED = "failed",
|
|
93
|
+
CLOSED = "closed"
|
|
94
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EselfDOMManager: Handles DOM manipulation and tracks multiple attachments per stream
|
|
3
|
+
*
|
|
4
|
+
* Key Features:
|
|
5
|
+
* - One stream can be attached to multiple video containers
|
|
6
|
+
* - Audio streams are attached to the body (one audio element per stream)
|
|
7
|
+
* - Tracks all attachments for proper cleanup
|
|
8
|
+
* - Gracefully handles missing containers (logs warning, doesn't throw)
|
|
9
|
+
*/
|
|
10
|
+
export declare class EselfDOMManager {
|
|
11
|
+
private logger;
|
|
12
|
+
private streamAttachments;
|
|
13
|
+
private audioElements;
|
|
14
|
+
constructor();
|
|
15
|
+
/**
|
|
16
|
+
* Attach a video stream to a container element
|
|
17
|
+
* Creates a video element inside the container and plays the stream
|
|
18
|
+
* Same stream can be attached to multiple containers
|
|
19
|
+
*
|
|
20
|
+
* @param stream - MediaStream to attach
|
|
21
|
+
* @param containerElementId - ID of the container element
|
|
22
|
+
*/
|
|
23
|
+
attachVideoStream(stream: MediaStream, containerElementId: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Attach an audio stream to the document body
|
|
26
|
+
* Creates an audio element in the body (not in a container)
|
|
27
|
+
* One audio element per stream (not multiple like video)
|
|
28
|
+
*
|
|
29
|
+
* @param stream - MediaStream to attach
|
|
30
|
+
*/
|
|
31
|
+
attachAudioStream(stream: MediaStream): void;
|
|
32
|
+
/**
|
|
33
|
+
* Detach a stream from a specific container element
|
|
34
|
+
* Removes the video element from that container only
|
|
35
|
+
* Stream may still be attached to other containers
|
|
36
|
+
*
|
|
37
|
+
* @param streamId - ID of the stream
|
|
38
|
+
* @param containerElementId - ID of the container to detach from
|
|
39
|
+
*/
|
|
40
|
+
detachStreamFromElement(streamId: string, containerElementId: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Detach a stream from ALL elements (all video containers + audio)
|
|
43
|
+
* Removes all video elements and audio element for this stream
|
|
44
|
+
*
|
|
45
|
+
* @param streamId - ID of the stream to fully detach
|
|
46
|
+
*/
|
|
47
|
+
detachStream(streamId: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* Clean up all tracked streams and elements
|
|
50
|
+
* Detaches all video and audio elements
|
|
51
|
+
* Call this on session destroy
|
|
52
|
+
*/
|
|
53
|
+
cleanup(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Check if a stream is attached to any elements
|
|
56
|
+
* @param streamId - ID of the stream to check
|
|
57
|
+
* @returns true if stream has any attachments (video or audio)
|
|
58
|
+
*/
|
|
59
|
+
isStreamAttached(streamId: string): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Get all container IDs that a stream is attached to
|
|
62
|
+
* @param streamId - ID of the stream
|
|
63
|
+
* @returns Array of container element IDs
|
|
64
|
+
*/
|
|
65
|
+
getStreamAttachments(streamId: string): string[];
|
|
66
|
+
/**
|
|
67
|
+
* Update tracks in DOM elements for local media preview
|
|
68
|
+
* Used when device changes to replace old tracks with new tracks
|
|
69
|
+
* This is for local media only (getUserMedia streams), not remote streams
|
|
70
|
+
*
|
|
71
|
+
* @param newTrack - New track to replace in DOM elements
|
|
72
|
+
* @param streamElementMappings - Map of element tracking from EselfSession
|
|
73
|
+
*/
|
|
74
|
+
updateLocalMediaTracks(newTrack: MediaStreamTrack, streamElementMappings: Map<string, {
|
|
75
|
+
audioElement: HTMLAudioElement | null;
|
|
76
|
+
videoElement: HTMLVideoElement | null;
|
|
77
|
+
videoContainerId: string | null;
|
|
78
|
+
}>): void;
|
|
79
|
+
}
|
|
80
|
+
export default EselfDOMManager;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { EselfDOMManager, default as EselfDOMManagerDefault, } from './EselfDOMManager';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const HiFromEsSelf: () => void;
|