@unisphere/models-sdk-js 1.2.0 → 1.3.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/index.esm.js +85 -39
- package/package.json +1 -1
- package/src/KalturaAvatarSession.d.ts +14 -5
- package/src/control-sdk/types.d.ts +9 -0
- package/src/rtc-sdk/AvatarRTCSDK.d.ts +3 -5
- package/src/rtc-sdk/types.d.ts +2 -0
- package/src/types.d.ts +2 -0
package/index.esm.js
CHANGED
|
@@ -4423,7 +4423,8 @@ class AvatarControlSDK {
|
|
|
4423
4423
|
id: config.avatarId
|
|
4424
4424
|
},
|
|
4425
4425
|
voiceConfig: config.voiceId ? {
|
|
4426
|
-
id: config.voiceId
|
|
4426
|
+
id: config.voiceId,
|
|
4427
|
+
modelId: 'eleven_flash_v2_5'
|
|
4427
4428
|
} : undefined
|
|
4428
4429
|
})
|
|
4429
4430
|
});
|
|
@@ -4891,11 +4892,12 @@ class PeerConnectionManager {
|
|
|
4891
4892
|
}
|
|
4892
4893
|
const config = {
|
|
4893
4894
|
iceServers: this.iceServers,
|
|
4894
|
-
iceTransportPolicy: this.iceTransportPolicy
|
|
4895
|
+
iceTransportPolicy: this.iceTransportPolicy,
|
|
4896
|
+
bundlePolicy: 'max-bundle'
|
|
4895
4897
|
};
|
|
4896
4898
|
this.logger.info('Creating RTCPeerConnection');
|
|
4897
4899
|
this.pc = new RTCPeerConnection(config);
|
|
4898
|
-
// Setup event
|
|
4900
|
+
// Setup event handlersCan you
|
|
4899
4901
|
this.setupEventHandlers();
|
|
4900
4902
|
this.logger.info('RTCPeerConnection created successfully');
|
|
4901
4903
|
}
|
|
@@ -5272,32 +5274,30 @@ class AvatarRTCSDK {
|
|
|
5272
5274
|
this.signalingManager = null;
|
|
5273
5275
|
this.videoElement = null;
|
|
5274
5276
|
this.state = ConnectionState.DISCONNECTED;
|
|
5275
|
-
// Reconnection state
|
|
5276
|
-
this.whepUrl = null;
|
|
5277
5277
|
this.reconnectAttempts = 0;
|
|
5278
5278
|
this.isReconnecting = false;
|
|
5279
5279
|
// Event handlers
|
|
5280
5280
|
this.eventHandlers = new Map();
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
this.
|
|
5285
|
-
this.
|
|
5281
|
+
if (!config.whepUrl) {
|
|
5282
|
+
throw new AvatarError('WHEP URL is required', AvatarErrorCode.INVALID_ARGUMENT);
|
|
5283
|
+
}
|
|
5284
|
+
this.whepUrl = config.whepUrl;
|
|
5285
|
+
this.iceServers = config.iceServers || DEFAULT_ICE_SERVERS;
|
|
5286
|
+
this.iceTransportPolicy = config.iceTransportPolicy || 'all';
|
|
5287
|
+
this.retryConfig = config.retryConfig || DEFAULT_RETRY_CONFIG;
|
|
5288
|
+
this.logger = config.logger || createLogger('AvatarRTCSDK', parseLogLevel(config.logLevel));
|
|
5289
|
+
this.logger.info('Initialized AvatarRTCSDK with WHEP URL:', this.whepUrl);
|
|
5286
5290
|
}
|
|
5287
5291
|
/**
|
|
5288
5292
|
* Connect to WebRTC endpoint using WHEP URL with retry logic
|
|
5289
|
-
*
|
|
5290
|
-
* @param whepUrl - WHEP URL for WebRTC signaling
|
|
5291
5293
|
*/
|
|
5292
|
-
connect(
|
|
5294
|
+
connect() {
|
|
5293
5295
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5294
|
-
this.logger.info('Connecting to WHEP URL:', whepUrl);
|
|
5296
|
+
this.logger.info('Connecting to WHEP URL:', this.whepUrl);
|
|
5295
5297
|
if (this.state === ConnectionState.CONNECTING || this.state === ConnectionState.CONNECTED) {
|
|
5296
5298
|
this.logger.warn('Already connecting or connected, ignoring');
|
|
5297
5299
|
return;
|
|
5298
5300
|
}
|
|
5299
|
-
// Store whepUrl for reconnection
|
|
5300
|
-
this.whepUrl = whepUrl;
|
|
5301
5301
|
this.reconnectAttempts = 0;
|
|
5302
5302
|
this.setState(ConnectionState.CONNECTING);
|
|
5303
5303
|
try {
|
|
@@ -5326,9 +5326,6 @@ class AvatarRTCSDK {
|
|
|
5326
5326
|
*/
|
|
5327
5327
|
connectInternal() {
|
|
5328
5328
|
return __awaiter(this, void 0, void 0, function* () {
|
|
5329
|
-
if (!this.whepUrl) {
|
|
5330
|
-
throw new AvatarError('WHEP URL not set', AvatarErrorCode.INVALID_ARGUMENT);
|
|
5331
|
-
}
|
|
5332
5329
|
// Create peer connection manager
|
|
5333
5330
|
this.pcManager = new PeerConnectionManager({
|
|
5334
5331
|
iceServers: this.iceServers,
|
|
@@ -5442,7 +5439,6 @@ class AvatarRTCSDK {
|
|
|
5442
5439
|
// Stop any ongoing reconnection attempts
|
|
5443
5440
|
this.isReconnecting = false;
|
|
5444
5441
|
this.reconnectAttempts = 0;
|
|
5445
|
-
this.whepUrl = null;
|
|
5446
5442
|
// Stop video
|
|
5447
5443
|
if (this.videoElement) {
|
|
5448
5444
|
if (this.videoElement.srcObject) {
|
|
@@ -6498,6 +6494,7 @@ class KalturaAvatarSession {
|
|
|
6498
6494
|
* @param config - Optional configuration
|
|
6499
6495
|
*/
|
|
6500
6496
|
constructor(apiKey, config) {
|
|
6497
|
+
this.rtcSDK = null;
|
|
6501
6498
|
this.state = SessionState.IDLE;
|
|
6502
6499
|
this.sessionId = null;
|
|
6503
6500
|
// Event handlers
|
|
@@ -6507,6 +6504,7 @@ class KalturaAvatarSession {
|
|
|
6507
6504
|
}
|
|
6508
6505
|
const logLevel = (config === null || config === void 0 ? void 0 : config.logLevel) || 'info';
|
|
6509
6506
|
this.logger = createLogger('KalturaAvatarSession', parseLogLevel(logLevel));
|
|
6507
|
+
this.config = config;
|
|
6510
6508
|
this.logger.info('Initializing Kaltura Avatar SDK');
|
|
6511
6509
|
// Initialize Control SDK
|
|
6512
6510
|
const controlConfig = {
|
|
@@ -6516,15 +6514,6 @@ class KalturaAvatarSession {
|
|
|
6516
6514
|
logLevel
|
|
6517
6515
|
};
|
|
6518
6516
|
this.controlSDK = new AvatarControlSDK(controlConfig);
|
|
6519
|
-
// Initialize RTC SDK
|
|
6520
|
-
const rtcConfig = {
|
|
6521
|
-
iceServers: config === null || config === void 0 ? void 0 : config.iceServers,
|
|
6522
|
-
iceTransportPolicy: config === null || config === void 0 ? void 0 : config.iceTransportPolicy,
|
|
6523
|
-
logger: this.logger
|
|
6524
|
-
};
|
|
6525
|
-
this.rtcSDK = new AvatarRTCSDK(rtcConfig);
|
|
6526
|
-
// Setup RTC event handlers
|
|
6527
|
-
this.setupRTCEventHandlers();
|
|
6528
6517
|
this.logger.info('Kaltura Avatar SDK initialized');
|
|
6529
6518
|
}
|
|
6530
6519
|
/**
|
|
@@ -6539,6 +6528,7 @@ class KalturaAvatarSession {
|
|
|
6539
6528
|
*/
|
|
6540
6529
|
createSession(options) {
|
|
6541
6530
|
return __awaiter(this, void 0, void 0, function* () {
|
|
6531
|
+
var _a, _b;
|
|
6542
6532
|
this.logger.info('Creating session with options:', options);
|
|
6543
6533
|
// Validate state
|
|
6544
6534
|
if (this.state !== SessionState.IDLE && this.state !== SessionState.ERROR) {
|
|
@@ -6563,11 +6553,35 @@ class KalturaAvatarSession {
|
|
|
6563
6553
|
const initResponse = yield this.controlSDK.initClient(this.sessionId);
|
|
6564
6554
|
const whepUrl = initResponse.whepUrl;
|
|
6565
6555
|
this.logger.info('Client initialized, WHEP URL:', whepUrl);
|
|
6566
|
-
//
|
|
6567
|
-
|
|
6568
|
-
|
|
6556
|
+
// Convert TURN server fields to ICE servers format
|
|
6557
|
+
const iceServers = [{
|
|
6558
|
+
urls: [`turn:${initResponse.turn.url}:80?transport=udp`, `turn:${initResponse.turn.url}:443?transport=udp`, `turn:${initResponse.turn.url}:80?transport=tcp`],
|
|
6559
|
+
username: initResponse.turn.username,
|
|
6560
|
+
credential: initResponse.turn.credential
|
|
6561
|
+
}];
|
|
6562
|
+
this.logger.info('ICE servers configured:', iceServers);
|
|
6563
|
+
// Step 3: Initialize RTC SDK with WHEP URL and ICE servers from backend
|
|
6564
|
+
this.logger.info('Step 3: Initializing RTC SDK');
|
|
6565
|
+
const rtcConfig = {
|
|
6566
|
+
whepUrl,
|
|
6567
|
+
// Use ICE servers from backend response, fallback to config if not provided
|
|
6568
|
+
iceServers: iceServers || ((_a = this.config) === null || _a === void 0 ? void 0 : _a.iceServers),
|
|
6569
|
+
iceTransportPolicy: (_b = this.config) === null || _b === void 0 ? void 0 : _b.iceTransportPolicy,
|
|
6570
|
+
logger: this.logger
|
|
6571
|
+
};
|
|
6572
|
+
this.rtcSDK = new AvatarRTCSDK(rtcConfig);
|
|
6573
|
+
// Setup RTC event handlers
|
|
6574
|
+
this.setupRTCEventHandlers();
|
|
6575
|
+
// Step 4: Connect WebRTC
|
|
6576
|
+
this.logger.info('Step 4: Connecting WebRTC');
|
|
6577
|
+
yield this.rtcSDK.connect();
|
|
6569
6578
|
this.setState(SessionState.READY);
|
|
6570
6579
|
this.logger.info('Session ready');
|
|
6580
|
+
// Step 5: Auto-attach video if container ID provided
|
|
6581
|
+
if (options.videoContainerId) {
|
|
6582
|
+
this.logger.info('Auto-attaching avatar to container:', options.videoContainerId);
|
|
6583
|
+
this.attachAvatar(options.videoContainerId);
|
|
6584
|
+
}
|
|
6571
6585
|
} catch (error) {
|
|
6572
6586
|
this.logger.error('Failed to create session:', error);
|
|
6573
6587
|
this.setState(SessionState.ERROR);
|
|
@@ -6577,14 +6591,35 @@ class KalturaAvatarSession {
|
|
|
6577
6591
|
});
|
|
6578
6592
|
}
|
|
6579
6593
|
/**
|
|
6580
|
-
* Attach avatar video to a video element
|
|
6594
|
+
* Attach avatar video to a div container by creating a video element inside it
|
|
6581
6595
|
*
|
|
6582
|
-
* @param
|
|
6596
|
+
* @param containerId - ID of the div element to attach the avatar video to
|
|
6583
6597
|
*/
|
|
6584
|
-
attachAvatar(
|
|
6585
|
-
this.logger.info('Attaching avatar to
|
|
6586
|
-
if (!
|
|
6587
|
-
throw new AvatarError('Invalid
|
|
6598
|
+
attachAvatar(containerId) {
|
|
6599
|
+
this.logger.info('Attaching avatar to container:', containerId);
|
|
6600
|
+
if (!containerId || typeof containerId !== 'string') {
|
|
6601
|
+
throw new AvatarError('Invalid container ID', AvatarErrorCode.INVALID_ARGUMENT);
|
|
6602
|
+
}
|
|
6603
|
+
if (!this.rtcSDK) {
|
|
6604
|
+
throw new AvatarError('RTC SDK not initialized. Create a session first.', AvatarErrorCode.INVALID_STATE);
|
|
6605
|
+
}
|
|
6606
|
+
// Find the container element
|
|
6607
|
+
const container = document.getElementById(containerId);
|
|
6608
|
+
if (!container) {
|
|
6609
|
+
throw new AvatarError(`Container element with ID '${containerId}' not found`, AvatarErrorCode.VIDEO_ELEMENT_INVALID);
|
|
6610
|
+
}
|
|
6611
|
+
// Create video element if it doesn't exist
|
|
6612
|
+
let videoElement = container.querySelector('video');
|
|
6613
|
+
if (!videoElement) {
|
|
6614
|
+
videoElement = document.createElement('video');
|
|
6615
|
+
videoElement.setAttribute('autoplay', '');
|
|
6616
|
+
videoElement.setAttribute('playsinline', '');
|
|
6617
|
+
videoElement.style.width = '100%';
|
|
6618
|
+
videoElement.style.height = '100%';
|
|
6619
|
+
container.appendChild(videoElement);
|
|
6620
|
+
this.logger.info('Created new video element in container');
|
|
6621
|
+
} else {
|
|
6622
|
+
this.logger.info('Using existing video element in container');
|
|
6588
6623
|
}
|
|
6589
6624
|
this.rtcSDK.attachVideo(videoElement);
|
|
6590
6625
|
this.logger.info('Avatar attached');
|
|
@@ -6656,18 +6691,23 @@ class KalturaAvatarSession {
|
|
|
6656
6691
|
this.setState(SessionState.ENDED);
|
|
6657
6692
|
try {
|
|
6658
6693
|
// Disconnect RTC first
|
|
6659
|
-
this.rtcSDK
|
|
6694
|
+
if (this.rtcSDK) {
|
|
6695
|
+
this.rtcSDK.disconnect();
|
|
6696
|
+
}
|
|
6660
6697
|
// End session with backend
|
|
6661
6698
|
if (this.sessionId) {
|
|
6662
6699
|
yield this.controlSDK.endSession(this.sessionId);
|
|
6663
6700
|
this.sessionId = null;
|
|
6664
6701
|
}
|
|
6702
|
+
// Clear RTC SDK reference
|
|
6703
|
+
this.rtcSDK = null;
|
|
6665
6704
|
this.setState(SessionState.IDLE);
|
|
6666
6705
|
this.logger.info('Session ended successfully');
|
|
6667
6706
|
} catch (error) {
|
|
6668
6707
|
this.logger.error('Error ending session:', error);
|
|
6669
6708
|
// Set state to idle anyway to allow creating new session
|
|
6670
6709
|
this.setState(SessionState.IDLE);
|
|
6710
|
+
this.rtcSDK = null;
|
|
6671
6711
|
throw error;
|
|
6672
6712
|
}
|
|
6673
6713
|
});
|
|
@@ -6682,6 +6722,9 @@ class KalturaAvatarSession {
|
|
|
6682
6722
|
* Get current connection state
|
|
6683
6723
|
*/
|
|
6684
6724
|
getConnectionState() {
|
|
6725
|
+
if (!this.rtcSDK) {
|
|
6726
|
+
return ConnectionState.DISCONNECTED;
|
|
6727
|
+
}
|
|
6685
6728
|
return this.rtcSDK.getConnectionState();
|
|
6686
6729
|
}
|
|
6687
6730
|
/**
|
|
@@ -6716,6 +6759,9 @@ class KalturaAvatarSession {
|
|
|
6716
6759
|
* Setup event handlers for RTC SDK
|
|
6717
6760
|
*/
|
|
6718
6761
|
setupRTCEventHandlers() {
|
|
6762
|
+
if (!this.rtcSDK) {
|
|
6763
|
+
return;
|
|
6764
|
+
}
|
|
6719
6765
|
this.rtcSDK.on('connected', () => {
|
|
6720
6766
|
this.emit('connectionChange', ConnectionState.CONNECTED);
|
|
6721
6767
|
});
|
package/package.json
CHANGED
|
@@ -9,8 +9,16 @@
|
|
|
9
9
|
* ```typescript
|
|
10
10
|
* const session = new KalturaAvatarSession('your-api-key');
|
|
11
11
|
*
|
|
12
|
+
* // Option 1: Auto-attach during session creation
|
|
13
|
+
* await session.createSession({
|
|
14
|
+
* avatarId: 'avatar-123',
|
|
15
|
+
* videoContainerId: 'avatar-container'
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Option 2: Attach manually after session creation
|
|
12
19
|
* await session.createSession({ avatarId: 'avatar-123' });
|
|
13
|
-
* session.attachAvatar(
|
|
20
|
+
* session.attachAvatar('avatar-container');
|
|
21
|
+
*
|
|
14
22
|
* await session.sayText('Hello from Kaltura Avatar!');
|
|
15
23
|
* await session.endSession();
|
|
16
24
|
* ```
|
|
@@ -21,8 +29,9 @@ import { AvatarConfig, ConnectionState, CreateSessionOptions, SessionState, Sess
|
|
|
21
29
|
*/
|
|
22
30
|
export declare class KalturaAvatarSession {
|
|
23
31
|
private readonly controlSDK;
|
|
24
|
-
private
|
|
32
|
+
private rtcSDK;
|
|
25
33
|
private readonly logger;
|
|
34
|
+
private readonly config;
|
|
26
35
|
private state;
|
|
27
36
|
private sessionId;
|
|
28
37
|
private eventHandlers;
|
|
@@ -45,11 +54,11 @@ export declare class KalturaAvatarSession {
|
|
|
45
54
|
*/
|
|
46
55
|
createSession(options: CreateSessionOptions): Promise<void>;
|
|
47
56
|
/**
|
|
48
|
-
* Attach avatar video to a video element
|
|
57
|
+
* Attach avatar video to a div container by creating a video element inside it
|
|
49
58
|
*
|
|
50
|
-
* @param
|
|
59
|
+
* @param containerId - ID of the div element to attach the avatar video to
|
|
51
60
|
*/
|
|
52
|
-
attachAvatar(
|
|
61
|
+
attachAvatar(containerId: string): void;
|
|
53
62
|
/**
|
|
54
63
|
* Send audio file for the avatar to speak
|
|
55
64
|
*
|
|
@@ -31,6 +31,15 @@ export interface InitClientResponse {
|
|
|
31
31
|
success: boolean;
|
|
32
32
|
/** WHEP URL for WebRTC connection */
|
|
33
33
|
whepUrl: string;
|
|
34
|
+
/** TURN server configuration */
|
|
35
|
+
turn: {
|
|
36
|
+
/** TURN server URL */
|
|
37
|
+
url: string;
|
|
38
|
+
/** TURN server username */
|
|
39
|
+
username: string;
|
|
40
|
+
/** TURN server credential */
|
|
41
|
+
credential: string;
|
|
42
|
+
};
|
|
34
43
|
/** Optional error message if initialization failed */
|
|
35
44
|
error?: string;
|
|
36
45
|
}
|
|
@@ -26,17 +26,15 @@ export declare class AvatarRTCSDK {
|
|
|
26
26
|
private readonly iceServers;
|
|
27
27
|
private readonly iceTransportPolicy;
|
|
28
28
|
private readonly retryConfig;
|
|
29
|
-
private whepUrl;
|
|
29
|
+
private readonly whepUrl;
|
|
30
30
|
private reconnectAttempts;
|
|
31
31
|
private isReconnecting;
|
|
32
32
|
private eventHandlers;
|
|
33
|
-
constructor(config
|
|
33
|
+
constructor(config: RTCConfig);
|
|
34
34
|
/**
|
|
35
35
|
* Connect to WebRTC endpoint using WHEP URL with retry logic
|
|
36
|
-
*
|
|
37
|
-
* @param whepUrl - WHEP URL for WebRTC signaling
|
|
38
36
|
*/
|
|
39
|
-
connect(
|
|
37
|
+
connect(): Promise<void>;
|
|
40
38
|
/**
|
|
41
39
|
* Internal connection logic (without retry)
|
|
42
40
|
*/
|
package/src/rtc-sdk/types.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { RetryConfig } from '../types';
|
|
|
7
7
|
* Configuration for the RTC SDK
|
|
8
8
|
*/
|
|
9
9
|
export interface RTCConfig {
|
|
10
|
+
/** WHEP URL for WebRTC connection */
|
|
11
|
+
whepUrl: string;
|
|
10
12
|
/** ICE servers for WebRTC connection */
|
|
11
13
|
iceServers?: RTCIceServer[];
|
|
12
14
|
/** ICE transport policy */
|
package/src/types.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface CreateSessionOptions {
|
|
|
26
26
|
avatarId: string;
|
|
27
27
|
/** Optional voice ID for the avatar */
|
|
28
28
|
voiceId?: string;
|
|
29
|
+
/** Optional ID of the div element to automatically attach the avatar video to */
|
|
30
|
+
videoContainerId?: string;
|
|
29
31
|
}
|
|
30
32
|
/**
|
|
31
33
|
* Configuration for retry logic with exponential backoff
|