diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index 624a0ebb..04d66b7d 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -627,8 +627,8 @@ export class OpenVidu { */ sendNewVideoDimensionsIfRequired(publisher: Publisher, reason: string, WAIT_INTERVAL: number, MAX_ATTEMPTS: number) { let attempts = 0; - const oldWidth = publisher.stream.videoDimensions.width; - const oldHeight = publisher.stream.videoDimensions.height; + const oldWidth = publisher?.stream?.videoDimensions?.width || 0; + const oldHeight = publisher?.stream?.videoDimensions?.height || 0; const repeatUntilChangeOrMaxAttempts: NodeJS.Timeout = setInterval(() => { attempts++; @@ -671,6 +671,36 @@ export class OpenVidu { }); }; + /** + * @hidden + */ + sendTrackChangedEvent(publisher: Publisher, reason: string, oldLabel: string, newLabel: string, propertyType: string) { + const oldValue = {label: oldLabel}; + const newValue = {label: newLabel}; + + if(publisher.stream.isLocalStreamPublished){ + this.sendRequest( + 'streamPropertyChanged', + { + streamId: publisher.stream.streamId, + property: propertyType, + newValue: JSON.stringify({newLabel}), + reason + }, + (error, response) => { + if (error) { + logger.error("Error sending 'streamPropertyChanged' event", error); + } else { + this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, publisher.stream, propertyType, newValue, oldValue, reason)]); + publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(publisher, publisher.stream, propertyType, newValue, oldValue, reason)]); + } + }); + } else { + this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, publisher.stream, propertyType, newValue, oldValue, reason)]); + publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(publisher, publisher.stream, propertyType, newValue, oldValue, reason)]); + } + } + /** * @hidden */ @@ -826,7 +856,7 @@ export class OpenVidu { params = {}; } logger.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); - this.jsonRpcClient.send(method, params, callback); + this.jsonRpcClient?.send(method, params, callback); } /** @@ -1105,7 +1135,7 @@ export class OpenVidu { if (error.code === 40007 && error.message === 'reconnection error') { // Kurento error: invalid RPC sessionId. This means that the kurento-jsonrpc-server of openvidu-server where kurento-jsonrpc-client - // is trying to reconnect does not know about this sessionId. This can mean two things: + // is trying to reconnect does not know about this sessionId. This can mean two things: // 1) openvidu-browser managed to reconnect after a while, but openvidu-server already evicted the user for not receiving ping. // 2) openvidu-server process is a different one because of a node crash. // Send a "sessionStatus" method to check the reason diff --git a/openvidu-browser/src/OpenVidu/Publisher.ts b/openvidu-browser/src/OpenVidu/Publisher.ts index 663356a2..eabb06cd 100644 --- a/openvidu-browser/src/OpenVidu/Publisher.ts +++ b/openvidu-browser/src/OpenVidu/Publisher.ts @@ -186,7 +186,7 @@ export class Publisher extends StreamManager { } }); - // There is a Virtual Background filter applied that must be removed in case the hardware must be freed + // There is a Virtual Background filter applied that must be removed in case the hardware must be freed if (!enabled && resource === true && !!this.stream.filter && this.stream.filter.type.startsWith('VB:')) { this.stream.lastVBFilter = this.stream.filter; // Save the filter to be re-applied in case of unmute await this.stream.removeFilterAux(true); @@ -651,11 +651,11 @@ export class Publisher extends StreamManager { if (this.stream.isLocalStreamPublished) { // Only if the Publisher has been published is necessary to call native Web API RTCRtpSender.replaceTrack // If it has not been published yet, replacing it on the MediaStream object is enough - await this.replaceTrackInMediaStream(track, updateLastConstraints); + this.replaceTrackInMediaStream(track, updateLastConstraints); return await this.replaceTrackInRtcRtpSender(track); } else { // Publisher not published. Simply replace the track on the local MediaStream - return await this.replaceTrackInMediaStream(track, updateLastConstraints); + return this.replaceTrackInMediaStream(track, updateLastConstraints); } } catch (error) { track.enabled = trackOriginalEnabledValue; @@ -773,9 +773,18 @@ export class Publisher extends StreamManager { removedTrack.stop(); mediaStream.removeTrack(removedTrack); mediaStream.addTrack(track); - if (track.kind === 'video' && this.stream.isLocalStreamPublished && updateLastConstraints) { + const trackInfo = { + oldLabel: removedTrack?.label || '', + newLabel: track?.label || '' + }; + if (track.kind === 'video' && updateLastConstraints) { this.openvidu.sendNewVideoDimensionsIfRequired(this, 'trackReplaced', 50, 30); - this.session.sendVideoData(this.stream.streamManager, 5, true, 5); + this.openvidu.sendTrackChangedEvent(this,'trackReplaced', trackInfo.oldLabel, trackInfo.newLabel, 'videoActive'); + if(this.stream.isLocalStreamPublished) { + this.session.sendVideoData(this.stream.streamManager, 5, true, 5); + } + } else if(track.kind === 'audio' && updateLastConstraints) { + this.openvidu.sendTrackChangedEvent(this,'trackReplaced', trackInfo.oldLabel, trackInfo.newLabel, 'audioActive'); } }