Skip to content

Commit fe49526

Browse files
authored
Merge pull request #992 from MyPureCloud/release/v13.0.0
Release/v13.0.0
2 parents acc608c + 2208903 commit fe49526

13 files changed

Lines changed: 392 additions & 419 deletions

changelog.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,29 @@ All notable changes to this project will be documented in this file.
33
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
44
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
55

6-
# [Unreleased](https://github.com/MyPureCloud/genesys-cloud-webrtc-sdk/compare/v12.1.0...HEAD)
6+
# [Unreleased](https://github.com/MyPureCloud/genesys-cloud-webrtc-sdk/compare/v13.0.0...HEAD)
7+
8+
# [v13.0.0](https://github.com/MyPureCloud/genesys-cloud-webrtc-sdk/compare/v12.1.0...HEAD)
9+
### Breaking Changes
10+
* [STREAM-1351](https://inindca.atlassian.net/browse/STREAM-1351) - Removed `v2.conversations.{id}.media` notification subscription. Removed the `activeVideoParticipantsUpdate` session event and `IOnScreenParticipantsUpdate` interface. Speaker and on-screen participant updates are now entirely handled via the data channel.
11+
12+
### Added
13+
* [STREAM-1056](https://inindca.atlassian.net/browse/STREAM-1056) Added documentation for live screen monitoring functionality
14+
15+
### Fixed
16+
* [STREAM-905](https://inindca.atlassian.net/browse/STREAM-905) - Fix issue where `sessionStarted` was not emitted for calls that re-use persistent connections after a media recovery has occurred. Now initializing `_emittedSessionStarteds` for reinvites but only emitting if not a reinvite.
717

818
# [v12.1.0](https://github.com/MyPureCloud/genesys-cloud-webrtc-sdk/compare/v12.0.0...v12.1.0)
919
### Added
1020
* [STREAM-1153](https://inindca.atlassian.net/browse/STREAM-1153) - Add support for monitoring multiple screens during live monitoring sessions
1121
* [STREAM-1123](https://inindca.atlassian.net/browse/STREAM-1123) - Only update necessary tracks when changing devices. Prevent virtual background from getting replaced
22+
* [STREAM-781](https://inindca.atlassian.net/browse/STREAM-781) - Fix issue where hold caused `Unhandled promise rejection from setConversationHeld` for inactive conversations.
1223

1324
### Changed
14-
* [STREAM-1211](https://inindca.atlassian.net/browse/STREAM-1178) - Update `axios` to `v1.13.5`.
25+
* [STREAM-1211](https://inindca.atlassian.net/browse/STREAM-1211) - Update `axios` to `v1.13.5`.
26+
* [STREAM-1285](https://inindca.atlassian.net/browse/STREAM-1285) - Refactor `handlePropose` in SoftphoneSessionHandler for clarity and future changes. Update associated comments to better reflect implementation.
27+
* [STREAM-1403](https://inindca.atlassian.net/browse/STREAM-1403) - Update `lodash` to `v4.18.1` to address Snyk vulnerability.
28+
* [STREAM-1423](https://inindca.atlassian.net/browse/STREAM-1423) - Update `axios` to `v1.15.0`.
1529

1630
# [v12.0.0](https://github.com/MyPureCloud/genesys-cloud-webrtc-sdk/compare/v11.5.1...v12.0.0)
1731
### Added

doc/index.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- [WebRTC SoftPhone]
1919
- [WebRTC Video Conferencing]
2020
- [WebRTC Screen Recording]
21+
- [WebRTC Live Screen Monitoring]
2122
- [WebRTC Media] (media, devices, and permissions support)
2223
- [WebRTC Headset Integration]
2324

@@ -131,6 +132,7 @@ interface ISdkConfig {
131132
wsHost?: string;
132133
autoConnectSessions?: boolean;
133134
autoAcceptPendingScreenRecordingRequests?: boolean;
135+
autoAcceptPendingLiveScreenMonitoringRequests?: boolean;
134136
jidResource?: string;
135137
disableAutoAnswer?: boolean;
136138
logLevel?: LogLevels;
@@ -220,6 +222,14 @@ If true, incoming proposes for screen recording sessions will be accepted immedi
220222
and no `pendingSession` event will be emitted. The consumer will still have to react to
221223
`sessionStarted` in order to add screen media and then call `sdk.acceptSession(...)`.
222224

225+
#### `autoAcceptPendingLiveScreenMonitoringRequests`
226+
227+
`autoAcceptPendingLiveScreenMonitoringRequests?: boolean;` Optional: default `false`
228+
229+
If true, incoming proposes for live screen monitoring sessions will be accepted immediately
230+
and no `pendingSession` event will be emitted. The consumer will still have to react to
231+
`sessionStarted` in order to add screen media and then call `sdk.acceptSession(...)`.
232+
223233
#### `jidResource`
224234

225235
`jidResource?: string;` Optional: default `undefined`
@@ -1200,7 +1210,7 @@ Params:
12001210
provided, no media will be requested.
12011211
- `audioElement?: HTMLAudioElement` Optional: audio element to attach incoming audio to
12021212
default is sdk `defaults.audioElement`
1203-
- `videoElement?: HTMLAudioElement` Optional: video element to attach incoming video to
1213+
- `videoElement?: HTMLVideoElement` Optional: video element to attach incoming video to
12041214
default is sdk `defaults.videoElement`. (only used for video sessions)
12051215
- `videoDeviceId?: string | boolean | null;` Optional: See [ISdkMediaDeviceIds] for full details
12061216
- `audioDeviceId?: string | boolean | null;` Optional: See [ISdkMediaDeviceIds] for full details
@@ -2042,6 +2052,7 @@ The SDK will add the `type` to give more clarity as to why the error was thrown.
20422052
[WebRTC SoftPhone]: softphone.md
20432053
[WebRTC Video Conferencing]: video.md
20442054
[WebRTC Screen Recording]: screen-recording.md
2055+
[WebRTC Live Screen Monitoring]: live-screen-monitoring.md
20452056
[WebRTC Media]: media.md
20462057
[ISdkMediaDeviceIds]: media.md#isdkmediadeviceids
20472058
[SDK Media audioTrackVolume event]: media.md#audiotrackvolume

doc/live-screen-monitoring.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Genesys Cloud WebRTC SDK Live Screen Monitoring
2+
3+
This SDK supports live screen monitoring functionality that allows real-time viewing of user screens. Live screen monitoring sessions are initiated by the server and provide the ability to observe user activity in real-time for support, training, or compliance purposes.
4+
5+
When the server determines that live screen monitoring should be initiated, it will send a `pendingSession` similar to how other session types work (ie. softphone and video conversations). The consuming client must accept the `pendingSession`, gather screen media, and add the media to that session.
6+
7+
> *Note: live screen monitoring does not support guest users.*
8+
9+
## WebRTC SDK Live Screen Monitoring Index
10+
This documentation expands upon the [GenesysCloudWebrtcSdk] documentation but is specific to
11+
live screen monitoring.
12+
13+
* [Example usage](#example-usage)
14+
* [Observer vs Target Roles](#observer-vs-target-roles)
15+
16+
## Prerequisites
17+
18+
You must have live screen monitoring policies in place and the WebRTC SDK must be configured to allow live screen monitoring sessions.
19+
20+
## Example Usage
21+
22+
### Automatic Accept (default)
23+
Signaling is automatically accepted by the SDK. When the live screen monitoring session comes in, you need to add your screen tracks and then call `sdk.acceptSession(session)`.
24+
25+
``` ts
26+
// set up needed events
27+
sdk.on('sessionStarted', async (session) => {
28+
if (sdk.isLiveScreenMonitoringSession(session)) {
29+
// gather media - the SDK does *not* gather screen media for you
30+
const screenStream = await navigator.getDisplayMedia();
31+
32+
// create metadata for the screen being monitored
33+
const track = screenStream.getTracks()[0];
34+
const { height, width, deviceId } = track.getSettings();
35+
const liveScreenMonitoringMetadata = [
36+
{
37+
trackId: track.id,
38+
screenId: deviceId,
39+
originX: 0,
40+
originY: 0,
41+
resolutionX: width,
42+
resolutionY: height,
43+
primary: true,
44+
}
45+
];
46+
47+
sdk.acceptSession({
48+
conversationId: session.conversationId,
49+
sessionType: session.sessionType,
50+
mediaStream: screenStream,
51+
liveScreenMonitoringMetadata
52+
});
53+
}
54+
});
55+
```
56+
57+
### Manual Accept
58+
If you want to manually control the acceptance of live screen monitoring sessions:
59+
60+
``` ts
61+
const sdk = new GenesysCloudWebrtcSdk({
62+
// other config stuff ...
63+
autoAcceptPendingLiveScreenMonitoringRequests: false
64+
});
65+
66+
sdk.on('pendingSession', (session) => {
67+
if (session.sessionType === SessionTypes.liveScreenMonitoring) {
68+
// manually accept the pending session
69+
sdk.acceptPendingSession({
70+
conversationId: session.conversationId,
71+
sessionType: session.sessionType
72+
});
73+
}
74+
});
75+
76+
sdk.on('sessionStarted', async (session) => {
77+
if (sdk.isLiveScreenMonitoringSession(session)) {
78+
const screenStream = await navigator.getDisplayMedia();
79+
80+
const track = screenStream.getTracks()[0];
81+
const { height, width, deviceId } = track.getSettings();
82+
const liveScreenMonitoringMetadata = [
83+
{
84+
trackId: track.id,
85+
screenId: deviceId,
86+
originX: 0,
87+
originY: 0,
88+
resolutionX: width,
89+
resolutionY: height,
90+
primary: true,
91+
}
92+
];
93+
94+
sdk.acceptSession({
95+
conversationId: session.conversationId,
96+
sessionType: session.sessionType,
97+
mediaStream: screenStream,
98+
liveScreenMonitoringMetadata
99+
});
100+
}
101+
});
102+
```
103+
104+
### Multiple Screens
105+
Live screen monitoring supports monitoring up to **four** screens simultaneously. All screen tracks need to be on the same media stream provided in `sdk.acceptSession(...)`.
106+
107+
``` ts
108+
sdk.on('sessionStarted', async (session) => {
109+
if (sdk.isLiveScreenMonitoringSession(session)) {
110+
// gather multiple screens
111+
const screenStream1 = await navigator.getDisplayMedia();
112+
const screenStream2 = await navigator.getDisplayMedia();
113+
114+
// combine streams
115+
screenStream2.getVideoTracks().forEach(track => screenStream1.addTrack(track));
116+
117+
// create metadata for all screens
118+
const liveScreenMonitoringMetadata = createMultiScreenMetadata();
119+
120+
sdk.acceptSession({
121+
conversationId: session.conversationId,
122+
sessionType: session.sessionType,
123+
mediaStream: screenStream1,
124+
liveScreenMonitoringMetadata
125+
});
126+
}
127+
});
128+
```
129+
130+
## Observer vs Target Roles
131+
132+
Live screen monitoring sessions involve two distinct roles with different behaviors:
133+
134+
### Target Role
135+
The **target** is the user whose screen is being monitored. When accepting a session as a target:
136+
- Must provide a `mediaStream` containing screen capture tracks
137+
- The session automatically accepts if the `fromUserId` matches the current user
138+
- Cannot end the monitoring session (only observers can end it)
139+
- Sends their screen content to observers
140+
141+
``` ts
142+
// Target accepts with screen media
143+
sdk.acceptSession({
144+
conversationId: session.conversationId,
145+
sessionType: session.sessionType,
146+
mediaStream: screenStream, // Required for targets
147+
liveScreenMonitoringMetadata
148+
});
149+
```
150+
151+
### Observer Role
152+
The **observer** is the user monitoring the target's screen. When accepting a session as an observer:
153+
- Must provide `videoElements` array or `videoElement` to display incoming video
154+
- Set `liveMonitoringObserver: true` in the accept parameters
155+
- Receives video streams from the target and displays them in provided video elements
156+
- Can end the monitoring session
157+
- Sends empty video tracks to maintain WebRTC connection
158+
159+
``` ts
160+
// Observer accepts with video elements
161+
sdk.acceptSession({
162+
conversationId: session.conversationId,
163+
sessionType: session.sessionType,
164+
liveMonitoringObserver: true, // Identifies this as observer role
165+
videoElements: [videoElement1, videoElement2], // Required for observers
166+
});
167+
```
168+
169+
### Role Determination
170+
The SDK automatically determines the role based on:
171+
1. If `liveMonitoringObserver: true` is set in accept parameters → Observer
172+
2. If `fromUserId` matches current user ID → Target (auto-accepted)
173+
3. Otherwise → Target (manual acceptance required unless specified)
174+
175+
[GenesysCloudWebrtcSdk]: index.md#genesyscloudwebrtcsdk

doc/video.md

Lines changed: 14 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ are done using the public API, but are abstracted being api's in this sdk.
66
> *Note: video conferencing does not support guest users.*
77
88
## WebRTC SDK Video Index
9-
This documentation expands upon the [GenesysCloudWebrtcSdk] documention but is specific to
10-
video conferencing. See the full list of the [APIs], [methods], and [events].
9+
This documentation expands upon the [GenesysCloudWebrtcSdk] documention but is specific to
10+
video conferencing. See the full list of the [APIs], [methods], and [events].
1111

1212
* See [sdk.startVideoConference()] for usage
1313
* [Example usage](#example-usage)
@@ -71,55 +71,8 @@ interface IParticipantUpdate {
7171
audioMuted: boolean
7272
}
7373
```
74-
Value of event:
75-
* `update: IParticipantsUpdate` – list of updated participants
76-
77-
#### `activeVideoParticipantsUpdate`
78-
79-
This event will happen when the server switches who is visible on the screen.
80-
81-
> *Note: this user may not be providing video or that video could be muted. It is up to the
82-
> implementing party to show something else such as an avatar or profile picture in such instances.*
83-
84-
Declaration:
85-
``` ts
86-
session.on('activeVideoParticipantsUpdate', (update: IOnScreenParticipantsUpdate) => {});
87-
88-
/* interface declaration */
89-
interface IOnScreenParticipantsUpdate {
90-
participantsOnScreen: [
91-
{
92-
userId: string,
93-
}
94-
]
95-
}
96-
```
9774
Value of event:
98-
* `update: IOnScreenParticipantsUpdate` – the new participant on the screen
99-
100-
101-
#### `speakersUpdate`
102-
103-
This event tells who is making noise in the conference.
104-
105-
> Caveat: currently, we can only emit on this event when the on-screen user changes,
106-
this will often appear to be out of sync. This will be fixed in the future.
107-
108-
Declaration:
109-
``` ts
110-
session.on('speakersUpdate', (update: ISpeakersUpdate) => {})):
111-
112-
/* interface declaration */
113-
interface ISpeakersUpdate {
114-
speakers: [
115-
{
116-
userId: string;
117-
}
118-
]
119-
}
120-
```
121-
Value of event:
122-
* `update: ISpeakersUpdate` – userIds of the participants speaking
75+
* `update: IParticipantsUpdate` – list of updated participants
12376

12477
## Video Session Methods
12578

@@ -134,7 +87,7 @@ be cleaned up and replaced with a track presenting your screen. When ending scre
13487
a camera track was cleaned up during `startScreenShare` a new one will be created to replace the screen share track.
13588

13689

137-
Declaration:
90+
Declaration:
13891
``` ts
13992
session.startScreenShare(): Promise<void>;
14093
```
@@ -145,13 +98,13 @@ Returns: a promise that completes after the screen share started.
14598

14699

147100
#### `stopScreenShare()`
148-
Ends the active outgoing screen share. If video media was on before the screen share
149-
started, the media we be required and added to the session.
101+
Ends the active outgoing screen share. If video media was on before the screen share
102+
started, the media we be required and added to the session.
150103

151-
If there was no active screen share for this session, an error is logged
152-
and returns (no error is thrown).
104+
If there was no active screen share for this session, an error is logged
105+
and returns (no error is thrown).
153106

154-
Declaration:
107+
Declaration:
155108
``` ts
156109
session.stopScreenShare(): Promise<void>;
157110
```
@@ -164,19 +117,19 @@ Returns: a promise that completes after the screen share end and the new video
164117

165118
#### `pinParticipantVideo()`
166119
Locks video to the provided video conference participant. If `participantId` is `null`
167-
or `undefined`, any currently pinned participants will be removed and will switch automatically
168-
when speaking.
120+
or `undefined`, any currently pinned participants will be removed and will switch automatically
121+
when speaking.
169122

170123
When a participant's video is pinned it will disable the video switching when other participants talk.
171124

172125
> Note: participantIds can be found in the [participantsUpdate](#participantsupdate) event.
173126
174-
Declaration:
127+
Declaration:
175128
``` ts
176129
session.pinParticipantVideo(participantId?: string): Promise<void>;
177130
```
178131

179-
Params:
132+
Params:
180133
* `participantId: string` – Optional: if provided, it will pin that participant's video. If
181134
the id is not provided, it will clear any old pin and reset back to the active user on screen.
182135

@@ -188,4 +141,4 @@ Returns: a promise that completes after the Public API call finishes pinning the
188141
[methods]: index.md#methods
189142
[events]: index.md#events
190143

191-
[session level events]: index.md#session-level-events
144+
[session level events]: index.md#session-level-events

0 commit comments

Comments
 (0)