sceyt-call 1.3.1 → 1.3.2
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 +121 -4
- package/index.d.ts +57 -10
- package/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ JavaScript SDK for real-time voice and video calls with WebRTC. This SDK works a
|
|
|
13
13
|
* [Call Events](#call-events)
|
|
14
14
|
* [Client Events](#client-events)
|
|
15
15
|
* [Call Management](#call-management)
|
|
16
|
+
* [Remote Participant Control](#remote-participant-control)
|
|
17
|
+
* [Call Permissions](#call-permissions)
|
|
16
18
|
* [Call History (CDR)](#call-history-cdr)
|
|
17
19
|
* [Participant States](#participant-states)
|
|
18
20
|
* [Logging](#logging)
|
|
@@ -90,7 +92,7 @@ call.on('participantStateChanged', ({ participant, state }) => {
|
|
|
90
92
|
```typescript
|
|
91
93
|
// Audio controls
|
|
92
94
|
call.mute(true); // Mute microphone
|
|
93
|
-
call.mute(false); // Unmute
|
|
95
|
+
call.mute(false); // Unmute (blocked if hard-muted by host or call audio is locked)
|
|
94
96
|
call.hold(true); // Put on hold
|
|
95
97
|
|
|
96
98
|
// Video controls
|
|
@@ -170,7 +172,7 @@ await call.switchToSFU(handleError);
|
|
|
170
172
|
- `call.enableVideo(enabled, errorCallback?)` — camera/signal errors via callback
|
|
171
173
|
- `call.startScreenShare(errorCallback?)` — screen share errors via callback
|
|
172
174
|
- `call.stopScreenShare(errorCallback?)` — signal errors via callback
|
|
173
|
-
- `call.mute(mute, errorCallback?)` — signal errors via callback
|
|
175
|
+
- `call.mute(mute, errorCallback?)` — signal errors via callback; returns error immediately if hard-muted
|
|
174
176
|
- `call.switchToSFU(errorCallback?)` — signal errors via callback
|
|
175
177
|
- `call.leave()` — no callback, check return value
|
|
176
178
|
|
|
@@ -206,8 +208,10 @@ call.on('videoTrackAdded', ({ participant, track }) => {
|
|
|
206
208
|
videoElement.srcObject = new MediaStream([track]);
|
|
207
209
|
});
|
|
208
210
|
|
|
209
|
-
call.on('participantEvent', ({ participant, event }) => {
|
|
210
|
-
// event: 'Mute' | 'Unmute' | 'Hold' | 'VideoEnabled' |
|
|
211
|
+
call.on('participantEvent', ({ participant, event, changedBy }) => {
|
|
212
|
+
// event: 'Mute' | 'Unmute' | 'Hold' | 'VideoEnabled' | 'VideoDisabled' |
|
|
213
|
+
// 'ScreenSharingStarted' | 'ScreenSharingStopped' | etc.
|
|
214
|
+
// changedBy: userId of whoever triggered the change (e.g. a host muting a participant)
|
|
211
215
|
});
|
|
212
216
|
|
|
213
217
|
call.on('activeSpeakersChanged', ({ activeSpeakers }) => {
|
|
@@ -217,6 +221,18 @@ call.on('activeSpeakersChanged', ({ activeSpeakers }) => {
|
|
|
217
221
|
call.on('sessionRenewed', ({ call, sessionId }) => {
|
|
218
222
|
// Fired when the server assigns a new sessionId to an existing call
|
|
219
223
|
});
|
|
224
|
+
|
|
225
|
+
call.on('callPermissionsUpdated', ({ call, permissions }) => {
|
|
226
|
+
// Fired when the host updates call-level audio/video permissions
|
|
227
|
+
console.log('Audio allowed:', permissions.allowPublishAudio);
|
|
228
|
+
console.log('Video allowed:', permissions.allowPublishVideo);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
call.on('participantPermissionsUpdated', ({ call, participant, permissions }) => {
|
|
232
|
+
// Fired when a participant's individual permissions are updated by the host
|
|
233
|
+
console.log(`${participant.id} canPublishAudio: ${permissions.canPublishAudio}`);
|
|
234
|
+
console.log(`${participant.id} canPublishVideo: ${permissions.canPublishVideo}`);
|
|
235
|
+
});
|
|
220
236
|
```
|
|
221
237
|
|
|
222
238
|
## Client Events
|
|
@@ -266,6 +282,103 @@ const speakers = call?.activeSpeakers;
|
|
|
266
282
|
const { data } = await callClient.fetchCall('call-id');
|
|
267
283
|
```
|
|
268
284
|
|
|
285
|
+
## Remote Participant Control
|
|
286
|
+
|
|
287
|
+
Host participants can mute, disable video, or update permissions for other participants in the call. All methods return `CallClientResult<boolean>` and accept an optional error callback.
|
|
288
|
+
|
|
289
|
+
### Mute / Unmute Remote Participants
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
// Mute a specific participant (soft-mute — they can unmute themselves)
|
|
293
|
+
call.muteRemoteParticipant('user1');
|
|
294
|
+
|
|
295
|
+
// Hard-mute: revoke publish-audio permission (they cannot unmute)
|
|
296
|
+
call.disableRemoteParticipantAudio('user1');
|
|
297
|
+
|
|
298
|
+
// Restore audio permission (allow them to unmute)
|
|
299
|
+
call.enableRemoteParticipantAudio('user1');
|
|
300
|
+
// or equivalently:
|
|
301
|
+
call.unmuteRemoteParticipant('user1');
|
|
302
|
+
|
|
303
|
+
// Mute all participants at once
|
|
304
|
+
call.muteAllRemoteParticipants();
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Disable Video for Remote Participants
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Turn off a specific participant's video
|
|
311
|
+
call.disableRemoteParticipantVideo('user1');
|
|
312
|
+
// or equivalently:
|
|
313
|
+
call.videoOffRemoteParticipant('user1');
|
|
314
|
+
|
|
315
|
+
// Turn off video for all participants
|
|
316
|
+
call.videoOffAllRemoteParticipants();
|
|
317
|
+
// or equivalently:
|
|
318
|
+
call.disableAllRemoteParticipantsVideo();
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Update Participant Permissions
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
import type { IParticipantPermissions } from 'sceyt-call';
|
|
325
|
+
|
|
326
|
+
// Grant or revoke individual publish permissions
|
|
327
|
+
call.updateParticipantPermissions('user1', {
|
|
328
|
+
canPublishAudio: true,
|
|
329
|
+
canPublishVideo: false,
|
|
330
|
+
});
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Call Permissions
|
|
334
|
+
|
|
335
|
+
The host can lock audio or video at the call level, preventing all participants from publishing.
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
import type { ICallPermissions } from 'sceyt-call';
|
|
339
|
+
|
|
340
|
+
// Lock audio for the entire call
|
|
341
|
+
call.disableCallAudio();
|
|
342
|
+
|
|
343
|
+
// Restore audio for the entire call
|
|
344
|
+
call.enableCallAudio();
|
|
345
|
+
|
|
346
|
+
// Lock video for the entire call
|
|
347
|
+
call.disableCallVideo();
|
|
348
|
+
|
|
349
|
+
// Restore video for the entire call
|
|
350
|
+
call.enableCallVideo();
|
|
351
|
+
|
|
352
|
+
// Update both at once
|
|
353
|
+
call.updateCallPermissions({ allowPublishAudio: false, allowPublishVideo: true });
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Current call-level permissions are exposed on the `call.permissions` property:
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
console.log(call.permissions?.allowPublishAudio); // boolean | undefined
|
|
360
|
+
console.log(call.permissions?.allowPublishVideo); // boolean | undefined
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Participant-level media state
|
|
364
|
+
|
|
365
|
+
Each participant now exposes a structured `mediaState` object instead of the old flat `muted`, `videoEnabled`, and `screenSharing` boolean fields:
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
const p = call.participants[0];
|
|
369
|
+
|
|
370
|
+
console.log(p.mediaState?.audio.enabled); // mic on/off
|
|
371
|
+
console.log(p.mediaState?.video.enabled); // camera on/off
|
|
372
|
+
console.log(p.mediaState?.screenShare.enabled); // screen share on/off
|
|
373
|
+
|
|
374
|
+
// changedBy tells you who last changed the state (e.g. a host action)
|
|
375
|
+
console.log(p.mediaState?.audio.changedBy);
|
|
376
|
+
|
|
377
|
+
// Individual publish permissions assigned by the host
|
|
378
|
+
console.log(p.permissions?.canPublishAudio);
|
|
379
|
+
console.log(p.permissions?.canPublishVideo);
|
|
380
|
+
```
|
|
381
|
+
|
|
269
382
|
## Call History (CDR)
|
|
270
383
|
|
|
271
384
|
```typescript
|
|
@@ -318,6 +431,10 @@ import type {
|
|
|
318
431
|
CallEventMap,
|
|
319
432
|
CallClientEventMap,
|
|
320
433
|
ICallDetailRecord,
|
|
434
|
+
ICallPermissions,
|
|
435
|
+
IParticipantPermissions,
|
|
436
|
+
IParticipantMediaState,
|
|
437
|
+
IMediaState,
|
|
321
438
|
ParticipantState,
|
|
322
439
|
CallState,
|
|
323
440
|
MediaFlow
|
package/index.d.ts
CHANGED
|
@@ -215,6 +215,8 @@ export interface CallSettings {
|
|
|
215
215
|
maxParticipantsCount?: number;
|
|
216
216
|
/** Type identifier for the call (e.g. 'audio', 'video', custom string) */
|
|
217
217
|
callType?: string;
|
|
218
|
+
/** Call-level audio/video permissions set by the owner */
|
|
219
|
+
permissions: ICallPermissions;
|
|
218
220
|
}
|
|
219
221
|
/**
|
|
220
222
|
* Options for creating a call.
|
|
@@ -276,11 +278,29 @@ interface SignalCallSettings {
|
|
|
276
278
|
persistent?: boolean;
|
|
277
279
|
notifyOnParticipantJoin?: boolean;
|
|
278
280
|
maxParticipantsCount?: number;
|
|
281
|
+
permissions: ICallPermissions;
|
|
279
282
|
}
|
|
280
283
|
interface SignalCallOptions {
|
|
281
284
|
settings?: SignalCallSettings;
|
|
282
285
|
callType?: string;
|
|
283
286
|
}
|
|
287
|
+
interface IMediaState {
|
|
288
|
+
enabled: boolean;
|
|
289
|
+
changedBy?: string;
|
|
290
|
+
}
|
|
291
|
+
interface IParticipantMediaState {
|
|
292
|
+
audio: IMediaState;
|
|
293
|
+
video: IMediaState;
|
|
294
|
+
screenShare: IMediaState;
|
|
295
|
+
}
|
|
296
|
+
interface IParticipantPermissions {
|
|
297
|
+
canPublishAudio: boolean;
|
|
298
|
+
canPublishVideo: boolean;
|
|
299
|
+
}
|
|
300
|
+
interface ICallPermissions {
|
|
301
|
+
allowPublishAudio: boolean;
|
|
302
|
+
allowPublishVideo: boolean;
|
|
303
|
+
}
|
|
284
304
|
/**
|
|
285
305
|
* Raw participant data as received from the server.
|
|
286
306
|
* Use the `Participant` class for a richer API.
|
|
@@ -292,10 +312,6 @@ export interface IParticipant {
|
|
|
292
312
|
clientId: string;
|
|
293
313
|
/** Whether this participant is the presenter */
|
|
294
314
|
presenter?: boolean;
|
|
295
|
-
/** Whether the participant's camera is on */
|
|
296
|
-
videoEnabled?: boolean;
|
|
297
|
-
/** Whether the participant's microphone is muted */
|
|
298
|
-
muted?: boolean;
|
|
299
315
|
/** Whether the participant is on hold */
|
|
300
316
|
onHold?: boolean;
|
|
301
317
|
/** Whether the participant is sharing their screen */
|
|
@@ -306,6 +322,10 @@ export interface IParticipant {
|
|
|
306
322
|
connectionState?: ParticipantConnectionState;
|
|
307
323
|
/** Whether the call was silenced for this participant */
|
|
308
324
|
isCallSilenced?: boolean;
|
|
325
|
+
/** Combined media track states */
|
|
326
|
+
mediaState?: IParticipantMediaState;
|
|
327
|
+
/** What this participant is allowed to publish */
|
|
328
|
+
permissions?: IParticipantPermissions;
|
|
309
329
|
}
|
|
310
330
|
type CallMetadata = {
|
|
311
331
|
[key: string]: string | number;
|
|
@@ -461,14 +481,8 @@ export declare class Participant {
|
|
|
461
481
|
id: string;
|
|
462
482
|
/** Client identifier for multi-device support. Empty string if not applicable. */
|
|
463
483
|
clientId: string;
|
|
464
|
-
/** Whether the participant's microphone is muted */
|
|
465
|
-
muted: boolean;
|
|
466
484
|
/** Whether the participant is on hold */
|
|
467
485
|
onHold: boolean;
|
|
468
|
-
/** Whether the participant's camera is enabled */
|
|
469
|
-
videoEnabled: boolean;
|
|
470
|
-
/** Whether the participant is sharing their screen */
|
|
471
|
-
screenSharing: boolean;
|
|
472
486
|
/** Array of audio tracks from this participant. Use these to play participant's audio. */
|
|
473
487
|
audioTracks: MediaStreamTrack[];
|
|
474
488
|
/** Array of video tracks from this participant. Use these to display participant's video. */
|
|
@@ -477,6 +491,10 @@ export declare class Participant {
|
|
|
477
491
|
state: ParticipantState;
|
|
478
492
|
/** Current WebRTC connection state of the participant */
|
|
479
493
|
connectionState: ParticipantConnectionState;
|
|
494
|
+
/** Combined media track states (audio, video, screenShare) */
|
|
495
|
+
mediaState?: IParticipantMediaState;
|
|
496
|
+
/** What this participant is allowed to publish */
|
|
497
|
+
permissions?: IParticipantPermissions;
|
|
480
498
|
}
|
|
481
499
|
interface ActiveSpeakerInfo {
|
|
482
500
|
participant: Participant;
|
|
@@ -579,6 +597,7 @@ export interface CallEventMap {
|
|
|
579
597
|
call: Call;
|
|
580
598
|
participant: Participant;
|
|
581
599
|
event: ParticipantEvent;
|
|
600
|
+
changedBy?: string;
|
|
582
601
|
};
|
|
583
602
|
/** Fired when participants are added to the call */
|
|
584
603
|
participantsAdded: {
|
|
@@ -610,6 +629,17 @@ export interface CallEventMap {
|
|
|
610
629
|
call: Call;
|
|
611
630
|
sessionId: string;
|
|
612
631
|
};
|
|
632
|
+
/** Fired when the owner updates call-level audio/video permissions */
|
|
633
|
+
callPermissionsUpdated: {
|
|
634
|
+
call: Call;
|
|
635
|
+
permissions: ICallPermissions;
|
|
636
|
+
};
|
|
637
|
+
/** Fired when a participant's individual permissions are updated by the owner */
|
|
638
|
+
participantPermissionsUpdated: {
|
|
639
|
+
call: Call;
|
|
640
|
+
participant: Participant;
|
|
641
|
+
permissions: IParticipantPermissions;
|
|
642
|
+
};
|
|
613
643
|
}
|
|
614
644
|
/**
|
|
615
645
|
* Event map for SceytCallClient class.
|
|
@@ -681,6 +711,8 @@ export declare class Call extends TypedEventEmitter<CallEventMap> {
|
|
|
681
711
|
callType?: string;
|
|
682
712
|
/** Scheduling and broadcast settings for this call */
|
|
683
713
|
settings?: CallSettings;
|
|
714
|
+
/** Current call-level audio/video permissions set by the owner */
|
|
715
|
+
permissions?: ICallPermissions;
|
|
684
716
|
/** Current list of active speakers in the call */
|
|
685
717
|
get activeSpeakers(): ActiveSpeakerInfo[];
|
|
686
718
|
set activeSpeakers(speakers: ActiveSpeakerInfo[]);
|
|
@@ -793,6 +825,21 @@ export declare class Call extends TypedEventEmitter<CallEventMap> {
|
|
|
793
825
|
* ```
|
|
794
826
|
*/
|
|
795
827
|
mute(mute: boolean, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
828
|
+
muteAllRemoteParticipants(errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
829
|
+
videoOffAllRemoteParticipants(errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
830
|
+
disableAllRemoteParticipantsVideo(errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
831
|
+
updateParticipantPermissions(id: string, permissions: IParticipantPermissions, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
832
|
+
muteRemoteParticipant(id: string, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
833
|
+
disableRemoteParticipantAudio(id: string, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
834
|
+
enableRemoteParticipantAudio(id: string, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
835
|
+
enableCallAudio(errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
836
|
+
disableCallAudio(errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
837
|
+
unmuteRemoteParticipant(id: string, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
838
|
+
disableRemoteParticipantVideo(id: string, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
839
|
+
videoOffRemoteParticipant(id: string, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
840
|
+
disableCallVideo(errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
841
|
+
enableCallVideo(errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
842
|
+
updateCallPermissions(permissions: ICallPermissions, errorCallback?: (result: CallClientResult<boolean>) => void): CallClientResult<boolean>;
|
|
796
843
|
/**
|
|
797
844
|
* Put the call on hold or resume it.
|
|
798
845
|
* When on hold, audio/video is paused but the call remains active.
|