From dd0016671e8965f5eb53eac76a1f03191d80bc72 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 24 Sep 2018 11:04:54 +0200 Subject: [PATCH] openvidu-node-client: advanced Subscriber with webrtc props support --- openvidu-node-client/src/OpenVidu.ts | 73 ++++++++++++++++++---------- openvidu-node-client/src/Session.ts | 24 ++++++++- 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts index 76a25e8d..ea52e671 100644 --- a/openvidu-node-client/src/OpenVidu.ts +++ b/openvidu-node-client/src/OpenVidu.ts @@ -17,6 +17,7 @@ import axios from 'axios'; import { Connection } from './Connection'; +import { Publisher } from './Publisher'; import { Recording } from './Recording'; import { RecordingProperties } from './RecordingProperties'; import { Session } from './Session'; @@ -482,22 +483,26 @@ export class OpenVidu { const addWebRtcStatsToConnections = (connection: Connection, connectionsExtendedInfo: any) => { const connectionExtended = connectionsExtendedInfo.find(c => c.connectionId === connection.connectionId); if (!!connectionExtended) { - connection['publishersWebRtc'] = []; + const publisherArray = []; connection.publishers.forEach(pub => { const publisherExtended = connectionExtended.publishers.find(p => p.streamId === pub.streamId); const pubAux = {}; // Standard properties pubAux['streamId'] = pub.streamId; pubAux['createdAt'] = pub.createdAt; - pubAux['audioActive'] = pub.audioActive; - pubAux['videoActive'] = pub.videoActive; - pubAux['hasAudio'] = pub.hasAudio; - pubAux['hasVideo'] = pub.hasVideo; - pubAux['typeOfVideo'] = pub.typeOfVideo; - pubAux['frameRate'] = pub.frameRate; - pubAux['videoDimensions'] = pub.videoDimensions; + const mediaOptions = { + audioActive: pub.audioActive, + videoActive: pub.videoActive, + hasAudio: pub.hasAudio, + hasVideo: pub.hasVideo, + typeOfVideo: pub.typeOfVideo, + frameRate: pub.frameRate, + videoDimensions: pub.videoDimensions + }; + pubAux['mediaOptions'] = mediaOptions; + const newPublisher = new Publisher(pubAux); // WebRtc properties - pubAux['webRtc'] = { + newPublisher['webRtc'] = { kms: { events: publisherExtended.events, localCandidate: publisherExtended.localCandidate, @@ -506,12 +511,13 @@ export class OpenVidu { webrtcTagName: publisherExtended.webrtcTagName } }; + newPublisher['localCandidatePair'] = parseRemoteCandidatePair(newPublisher['webRtc'].kms.remoteCandidate); if (!!publisherExtended.serverStats) { - pubAux['webRtc'].kms.serverStats = publisherExtended.serverStats; + newPublisher['webRtc'].kms.serverStats = publisherExtended.serverStats; } - connection['publishersWebRtc'].push(pubAux); + publisherArray.push(newPublisher); }); - connection['subscribersWebRtc'] = []; + const subscriberArray = []; connection.subscribers.forEach(sub => { const subscriberExtended = connectionExtended.subscribers.find(s => s.streamId === sub); const subAux = {}; @@ -529,14 +535,32 @@ export class OpenVidu { webrtcTagName: subscriberExtended.webrtcTagName } }; + subAux['localCandidatePair'] = parseRemoteCandidatePair(subAux['webRtc'].kms.remoteCandidate); if (!!subscriberExtended.serverStats) { subAux['webRtc'].kms.serverStats = subscriberExtended.serverStats; } - connection['subscribersWebRtc'].push(subAux); + subscriberArray.push(subAux); }); + connection.publishers = publisherArray; + connection.subscribers = subscriberArray; } }; + const parseRemoteCandidatePair = (candidateStr: string) => { + if (!candidateStr) { + return 'ERROR: No remote candidate available'; + } + const array = candidateStr.split(/\s+/); + return { + portNumber: array[5], + ipAddress: array[4], + transport: array[2].toLowerCase(), + candidateType: array[7], + priority: array[3], + raw: candidateStr + }; + }; + return new Promise((resolve, reject) => { axios.get( 'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_SESSIONS + '?webRtcStats=true', @@ -567,20 +591,19 @@ export class OpenVidu { }); if (!!storedSession) { const fetchedSession: Session = new Session().resetSessionWithJson(session); - let changed = !storedSession.equalTo(fetchedSession); - fetchedSession.activeConnections.forEach((connection, index1) => { + fetchedSession.activeConnections.forEach(connection => { addWebRtcStatsToConnections(connection, session.connections.content); - if (!changed) { // Check if server webrtc information has changed in any Publisher/Subscriber - for (let index2 = 0; (index2 < connection['publishersWebRtc'].length && !changed); index2++) { - changed = changed || JSON.stringify(connection['publishersWebRtc'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['publishersWebRtc'][index2]['webRtc']); - } - if (!changed) { - for (let index2 = 0; (index2 < connection['subscribersWebRtc'].length && !changed); index2++) { - changed = changed || JSON.stringify(connection['subscribersWebRtc'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['subscribersWebRtc'][index2]['webRtc']); - } - } - } }); + + let changed = !storedSession.equalTo(fetchedSession); + if (!changed) { // Check if server webrtc information has changed in any Publisher object (Session.equalTo does not check Publisher.webRtc auxiliary object) + fetchedSession.activeConnections.forEach((connection, index1) => { + for (let index2 = 0; (index2 < connection['publishers'].length && !changed); index2++) { + changed = changed || JSON.stringify(connection['publishers'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['publishers'][index2]['webRtc']); + } + }); + } + if (changed) { storedSession = fetchedSession; this.activeSessions[sessionIndex] = storedSession; diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index af3047a3..91340477 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -274,7 +274,17 @@ export class Session { if (!!connectionClosed) { connectionClosed.publishers.forEach(publisher => { this.activeConnections.forEach(con => { - con.subscribers = con.subscribers.filter(subscriber => subscriber !== publisher.streamId); + con.subscribers = con.subscribers.filter(subscriber => { + // tslint:disable:no-string-literal + if (!!subscriber['streamId']) { + // Subscriber with advanced webRtc configuration properties + return (subscriber['streamId'] !== publisher.streamId); + // tslint:enable:no-string-literal + } else { + // Regular string subscribers + return subscriber !== publisher.streamId; + } + }); }); }); } else { @@ -334,7 +344,17 @@ export class Session { // Try to remove the Publisher from the Connection publishers collection connection.publishers = connection.publishers.filter(pub => pub.streamId !== streamId); // Try to remove the Publisher from the Connection subscribers collection - connection.subscribers = connection.subscribers.filter(sub => sub !== streamId); + if (!!connection.subscribers && connection.subscribers.length > 0) { + // tslint:disable:no-string-literal + if (!!connection.subscribers[0]['streamId']) { + // Subscriber with advanced webRtc configuration properties + connection.subscribers = connection.subscribers.filter(sub => sub['streamId'] !== streamId); + // tslint:enable:no-string-literal + } else { + // Regular string subscribers + connection.subscribers = connection.subscribers.filter(sub => sub !== streamId); + } + } }); console.log("Stream '" + streamId + "' unpublished"); resolve();