Skip to content

Commit bbdcc48

Browse files
authored
[STREAM-1351] - Removed v2.conversations.{id}.media sub, cleaned up… (#988)
1 parent 7ac7b05 commit bbdcc48

5 files changed

Lines changed: 20 additions & 368 deletions

File tree

changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ 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

66
# [Unreleased](https://github.com/MyPureCloud/genesys-cloud-webrtc-sdk/compare/v12.0.0...HEAD)
7+
### Breaking Changes
8+
* [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.
9+
710
### Added
811
* Added documentation for live screen monitoring functionality
912

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

src/sessions/video-session-handler.ts

Lines changed: 1 addition & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { differenceBy, intersection } from 'lodash';
1+
import { differenceBy } from 'lodash';
22
import { Constants } from 'stanza';
33

44
import {
@@ -8,8 +8,6 @@ import {
88
IExtendedMediaSession,
99
IParticipantUpdate,
1010
IParticipantsUpdate,
11-
IOnScreenParticipantsUpdate,
12-
ISpeakersUpdate,
1311
IConversationParticipant,
1412
IMediaRequestOptions,
1513
IStartVideoSessionParams,
@@ -26,35 +24,6 @@ import { ConversationUpdate } from '../conversations/conversation-update';
2624
import { JsonRpcMessage } from 'genesys-cloud-streaming-client';
2725
import { jwtDecode } from "jwt-decode";
2826

29-
/**
30-
* speakers is an array of audio track ids sending audio
31-
*/
32-
export interface IMediaChangeEvent {
33-
eventBody: {
34-
id: string,
35-
participants: IMediaChangeEventParticipant[],
36-
speakers: string[]
37-
};
38-
metadata: {
39-
CorrelationId: string
40-
};
41-
}
42-
43-
/**
44-
* sinks represents outgoing paths for this track. For example, if we have a track that looks like { id: "1", mediaType: "audio", sinks: ["a", "b"] }
45-
* then we know that the audio of track "1" can be heard on tracks "a" and "b". Another way to say this is whichever participants are receiving
46-
* tracks "a" or "b" are hearing this participant
47-
*/
48-
export interface IMediaChangeEventParticipant {
49-
communicationId: string;
50-
userId: string;
51-
tracks: {
52-
id: string,
53-
mediaType: 'audio' | 'video',
54-
sinks?: string[]
55-
}[];
56-
}
57-
5827
export class VideoSessionHandler extends BaseSessionHandler {
5928
requestedSessions: { [roomJid: string]: boolean } = {};
6029
requestedMeetingSessions: { [meetingId: string]: boolean } = {};
@@ -165,91 +134,6 @@ export class VideoSessionHandler extends BaseSessionHandler {
165134
session.emit('participantsUpdate', update);
166135
}
167136

168-
updateParticipantsOnScreen (session: VideoMediaSession, mediaUpdateEvent: IMediaChangeEvent) {
169-
const incomingVideoTrackIds = session.pc.getReceivers()
170-
.filter((receiver) => receiver.track && receiver.track.kind === 'video')
171-
.map((receiver) => receiver.track.id);
172-
173-
/**
174-
* Firefox messes the trackIds up from what is actually in the sdp offer.
175-
* Need to pull it from the offer to accurately match the track.sinks
176-
*/
177-
const incomingVideoMsidTrackId = this.getTrackIdFromSdp(session.pc.remoteDescription.sdp, 'video');
178-
179-
if (incomingVideoMsidTrackId) {
180-
incomingVideoTrackIds.push(incomingVideoMsidTrackId);
181-
}
182-
183-
const onScreenParticipants: Array<{ userId: string }> = [];
184-
mediaUpdateEvent.eventBody.participants.forEach((updateParticipant: IMediaChangeEventParticipant) => {
185-
const matchingVideoTracks = updateParticipant.tracks
186-
.filter((track) => track.mediaType === 'video')
187-
.filter((track) => {
188-
const intersectingTracks = intersection(track.sinks, incomingVideoTrackIds);
189-
return intersectingTracks.length;
190-
});
191-
192-
if (matchingVideoTracks.length) {
193-
onScreenParticipants.push({ userId: updateParticipant.userId });
194-
}
195-
});
196-
197-
const lastUpdate: IOnScreenParticipantsUpdate = session._lastOnScreenUpdate || { participants: [] } as any;
198-
199-
// send out an update if the onScreenParticipants count or items changed
200-
if (lastUpdate.participants.length === onScreenParticipants.length) {
201-
const changed = differenceBy(lastUpdate.participants, onScreenParticipants, 'userId').length ||
202-
differenceBy(lastUpdate.participants, onScreenParticipants, 'userId').length;
203-
204-
if (!changed) {
205-
return;
206-
}
207-
}
208-
209-
const update: IOnScreenParticipantsUpdate = {
210-
participants: onScreenParticipants
211-
};
212-
213-
session._lastOnScreenUpdate = update;
214-
session.emit('activeVideoParticipantsUpdate', update);
215-
}
216-
217-
updateSpeakers (session: IExtendedMediaSession, mediaUpdateEvent: IMediaChangeEvent) {
218-
const incomingAudioTrackIds = session.pc.getReceivers()
219-
.filter((receiver) => receiver.track && receiver.track.kind === 'audio')
220-
.map((receiver) => receiver.track.id);
221-
222-
/**
223-
* Firefox messes the trackIds up from what is actually in the sdp offer.
224-
* Need to pull it from the offer to accurately match the track.sinks
225-
*/
226-
const incomingAudioMsidTrackId = this.getTrackIdFromSdp(session.pc.remoteDescription.sdp, 'audio');
227-
228-
if (incomingAudioMsidTrackId) {
229-
incomingAudioTrackIds.push(incomingAudioMsidTrackId);
230-
}
231-
232-
const speakingParticipants: Array<{ userId: string }> = [];
233-
mediaUpdateEvent.eventBody.participants.forEach((updateParticipant: IMediaChangeEventParticipant) => {
234-
const matchingAudioTracks = updateParticipant.tracks
235-
.filter((track) => track.mediaType === 'audio')
236-
.filter((track) => {
237-
const intersectingTracks = intersection(track.sinks, incomingAudioTrackIds);
238-
return intersectingTracks.length;
239-
});
240-
241-
if (matchingAudioTracks.length) {
242-
speakingParticipants.push({ userId: updateParticipant.userId });
243-
}
244-
});
245-
246-
const update: ISpeakersUpdate = {
247-
speakers: speakingParticipants
248-
};
249-
250-
session.emit('speakersUpdate', update);
251-
}
252-
253137
// triggers a propose from the backend
254138
async startSession(startParams: IStartVideoSessionParams | IStartVideoMeetingSessionParams): Promise<{ conversationId: string }> {
255139
if ("jid" in startParams) {
@@ -414,10 +298,6 @@ export class VideoSessionHandler extends BaseSessionHandler {
414298
}
415299

416300
session._outboundStream = stream;
417-
// If using a JWT, we can't subscribe to the media change events.
418-
if (!this.sdk._config.jwt) {
419-
await this.sdk._streamingConnection.notifications.subscribe(`v2.conversations.${session.conversationId}.media`, this.handleMediaChangeEvent.bind(this, session));
420-
}
421301

422302
await this.addMediaToSession(session, stream);
423303

@@ -699,11 +579,6 @@ export class VideoSessionHandler extends BaseSessionHandler {
699579
}
700580
}
701581

702-
handleMediaChangeEvent (session: VideoMediaSession, event: IMediaChangeEvent): void {
703-
this.updateParticipantsOnScreen(session, event);
704-
this.updateSpeakers(session, event);
705-
}
706-
707582
async startScreenShare (session: VideoMediaSession): Promise<void> {
708583
session._resurrectVideoOnScreenShareEnd = !session.videoMuted;
709584
try {

src/types/interfaces.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ export { ISessionInfo, IPendingSession };
1313
declare module 'genesys-cloud-streaming-client' {
1414
export interface SessionEvents {
1515
participantsUpdate: IParticipantsUpdate;
16-
activeVideoParticipantsUpdate: IOnScreenParticipantsUpdate;
1716
speakersUpdate: ISpeakersUpdate;
1817
incomingMedia: void;
1918
pinnedParticipant: { participantId: string | null };
@@ -928,7 +927,6 @@ export interface VideoMediaSession extends IExtendedMediaSession {
928927
pinParticipantVideo?: (participantId: string) => Promise<void>;
929928
_resurrectVideoOnScreenShareEnd?: boolean;
930929
_lastParticipantsUpdate?: IParticipantsUpdate;
931-
_lastOnScreenUpdate?: IOnScreenParticipantsUpdate;
932930
}
933931

934932
export interface ScreenRecordingMediaSession extends IExtendedMediaSession {
@@ -1002,15 +1000,6 @@ export interface IParticipantUpdate {
10021000
videoMuted: boolean;
10031001
audioMuted: boolean;
10041002
}
1005-
1006-
export interface IOnScreenParticipantsUpdate {
1007-
participants: Array<
1008-
{
1009-
userId: string;
1010-
}
1011-
>;
1012-
}
1013-
10141003
export interface ISpeakersUpdate {
10151004
speakers: Array<
10161005
{

0 commit comments

Comments
 (0)