@@ -63,54 +63,73 @@ export class LiveMonitoringSessionHandler extends BaseSessionHandler {
6363 let addMediaPromise : Promise < any > = Promise . resolve ( ) ;
6464 params . mediaStream . getTracks ( ) . forEach ( ( track ) => {
6565 addMediaPromise = addMediaPromise . then ( ( ) => {
66- this . sdk . logger . info ( 'Adding screen track to live screen monitoring session' , { trackId : track . id , label : track . label , conversationId : session . conversationId , sessionType : this . sessionType } ) ;
67- return session . pc . addTrack ( track ) ;
66+ const trackStream = createNewStreamWithTrack ( track ) ;
67+ this . sdk . logger . info ( 'Adding screen track to live screen monitoring session' , { streamId : trackStream . id , trackId : track . id , label : track . label , conversationId : session . conversationId , sessionType : this . sessionType } ) ;
68+ return session . pc . addTrack ( track , trackStream ) ;
6869 } ) ;
6970 } ) ;
7071 await addMediaPromise ;
72+
73+ // Set unused video transceivers direction: inactive to not get sent to the observer clients
74+ const unusedTransceivers = session . pc . getTransceivers ( )
75+ . filter ( transceiver => transceiver . receiver . track ?. kind === 'video' && ! transceiver . sender . track )
76+ this . sdk . logger . info ( `Setting ${ unusedTransceivers . length } unused video transceivers to inactive` , { conversationId : session . conversationId , sessionId : session . id } ) ;
77+ unusedTransceivers . forEach ( transceiver => {
78+ transceiver . direction = "inactive" ;
79+ } ) ;
7180 }
7281
7382 async acceptSessionForObserver ( session : LiveScreenMonitoringSession , params : IAcceptSessionRequest ) {
74- const videoElement = params . videoElement || this . sdk . _config . defaults . videoElement ;
83+ const videoElements = params . videoElements || ( params . videoElement ? [ params . videoElement ] : [ this . sdk . _config . defaults . videoElement ] . filter ( Boolean ) ) ;
7584 const sessionInfo = { conversationId : session . conversationId , sessionId : session . id } ;
7685
77- if ( ! videoElement ) {
86+ if ( ! videoElements . length ) {
7887 throw createAndEmitSdkError . call ( this . sdk , SdkErrorTypes . invalid_options ,
79- 'acceptSession for live monitoring observer requires a videoElement to be provided or in the default config' ,
88+ 'acceptSession for live monitoring observer requires videoElements array or videoElement to be provided or in the default config' ,
8089 sessionInfo ) ;
8190 }
8291
83- const attachParams = { videoElement } ;
84-
85- const handleIncomingTracks = ( session : IExtendedMediaSession , tracks : MediaStreamTrack | MediaStreamTrack [ ] ) => {
86- if ( ! Array . isArray ( tracks ) ) tracks = [ tracks ] ;
87-
88- for ( const track of tracks ) {
89- this . log ( 'info' , 'Incoming track from live monitoring session' , {
90- track,
91- conversationId : session . conversationId ,
92- sessionId : session . id ,
93- sessionType : session . sessionType
92+ const tracks = session . pc . getReceivers ( )
93+ . filter ( receiver => receiver . track )
94+ . map ( receiver => receiver . track )
95+ . filter ( track => track . kind === 'video' ) ;
96+
97+ this . log ( 'info' , `Accepting live screen monitoring session as observer with ${ videoElements . length } available video elements for ${ session . pc . getReceivers ( ) . length } receivers with ${ tracks . length } video tracks` ) ;
98+
99+ try {
100+ let addEmptyMediaPromise : Promise < any > = Promise . resolve ( ) ;
101+ tracks . forEach ( ( targetTrack ) => {
102+ addEmptyMediaPromise = addEmptyMediaPromise . then ( ( ) => {
103+ const canvas = document . createElement ( 'canvas' ) ;
104+ canvas . width = 1 ;
105+ canvas . height = 1 ;
106+ const emptyStream = canvas . captureStream ( 0 ) ;
107+ const emptyVideoTrack = emptyStream . getVideoTracks ( ) [ 0 ] ;
108+ this . sdk . logger . info ( 'Adding empty screen track to live screen monitoring session' , { streamId : emptyStream . id , trackId : emptyVideoTrack . id , label : emptyVideoTrack . label , conversationId : session . conversationId , sessionType : this . sessionType } ) ;
109+ return session . pc . addTrack ( emptyVideoTrack , emptyStream ) ;
94110 } ) ;
111+ } ) ;
112+ await addEmptyMediaPromise ;
113+ } catch ( error : any ) {
114+ this . sdk . logger . error ( 'Error when adding empty video streams' , error ) ;
115+ }
95116
96- this . attachIncomingTrackToElement ( track , attachParams ) ;
117+ let videoElementIndex = 0 ;
118+ for ( const track of tracks ) {
119+ if ( videoElementIndex < videoElements . length ) {
120+ const stream = createNewStreamWithTrack ( track ) ;
121+ const videoElement = videoElements [ videoElementIndex ] ;
122+ videoElement . muted = true ;
123+ videoElement . autoplay = true ;
124+ videoElement . srcObject = stream ;
125+ this . log ( 'info' , `Attached stream to video element at index ${ videoElementIndex } ` , {
126+ streamId : videoElement . srcObject ?. id ,
127+ track : track ,
128+ ...sessionInfo ,
129+ } ) ;
130+ videoElementIndex ++ ;
97131 }
98-
99132 session . emit ( 'incomingMedia' ) ;
100- } ;
101-
102- // Get existing tracks
103- const tracks = session . pc . getReceivers ( )
104- . filter ( receiver => receiver . track )
105- . map ( receiver => receiver . track ) ;
106-
107- if ( tracks . length ) {
108- handleIncomingTracks ( session , tracks ) ;
109- } else {
110- // Listen for tracks that arrive later
111- session . on ( 'peerTrackAdded' , ( track : MediaStreamTrack ) => {
112- handleIncomingTracks ( session , track ) ;
113- } ) ;
114133 }
115134 }
116135
@@ -129,29 +148,6 @@ export class LiveMonitoringSessionHandler extends BaseSessionHandler {
129148 this . log ( 'warn' , 'Cannot update outgoing media for live monitoring sessions' , { sessionId : session . id , sessionType : session . sessionType } ) ;
130149 throw createAndEmitSdkError . call ( this . sdk , SdkErrorTypes . not_supported , 'Cannot update outgoing media for live monitoring sessions' ) ;
131150 }
132-
133- /**
134- * Attach incoming track to HTML element
135- */
136- attachIncomingTrackToElement (
137- track : MediaStreamTrack ,
138- { videoElement } : { videoElement : HTMLVideoElement }
139- ) : HTMLAudioElement | HTMLVideoElement {
140- const element = videoElement ;
141-
142- if ( track . kind === 'video' ) {
143- if ( element ) {
144- element . muted = true ;
145- }
146- }
147-
148- if ( element ) {
149- element . autoplay = true ;
150- element . srcObject = createNewStreamWithTrack ( track ) ;
151- }
152-
153- return element ;
154- }
155151}
156152
157153export default LiveMonitoringSessionHandler ;
0 commit comments