Code Monkey home page Code Monkey logo

kurento-group-call-node's Introduction

kurento-group-call-node (DEFAULT SFU)

This code is an example, I did not optimize it.

Please contact me for more information.

Required

Node Version: Node 8.x

branch checkout

git checkout sfu

or

git checkout mcu

install


npm install bower -g

npm run get

edit

./server/index.js 

const argv = minimst(process.argv.slice(2), {
    default: {
        as_uri: 'https://localhost:3000',
        ws_uri: 'ws://127.0.0.1:8888/kurento'   // your KMS uri
    }
});

run

 node index.js 

Mobile Client ( React Native )

kurento-group-call-react-native

server-side Must be trusted https

or

modify the server-side code to http (Only Firefox support)

kurento-group-call-node's People

Contributors

chapin666 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kurento-group-call-node's Issues

/kurento-group-call-node-master/node_modules/core-js/modules/_typed-buffer.js:157 if(numberLength != byteLength)throw RangeError(WRONG_LENGTH);

When i am running node index.js, then this error came.

/kurento-group-call-node-master/node_modules/core-js/modules/_typed-buffer.js:157
if(numberLength != byteLength)throw RangeError(WRONG_LENGTH);

RangeError: Wrong length!
at validateArrayBufferArguments (/home/shahnawaz/nodejs/example/kurento-group-call-node-master/node_modules/core-js/modules/_typed-buffer.js:157:39)
at new ArrayBuffer (/home/shahnawaz/nodejs/example/kurento-group-call-node-master/node_modules/core-js/modules/_typed-buffer.js:247:29)
at zlib.js:344:28
at NativeModule.compileForInternalLoader (internal/bootstrap/loaders.js:276:7)
at NativeModule.compileForPublicLoader (internal/bootstrap/loaders.js:218:10)
at loadNativeModule (internal/modules/cjs/helpers.js:24:9)
at Function.Module._load (internal/modules/cjs/loader.js:870:15)
at Module.require (internal/modules/cjs/loader.js:1040:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object. (/home/shahnawaz/nodejs/example/kurento-group-call-node-master/node_modules/engine.io/lib/transports/polling.js:8:12)

How to make chrome to receive modified sdp from webrtcpeer.js?

I want to send modified sdp to chrome. However it is not receiving that modified sdp which is changed in sdp_pattern.txt

  v=0
  o=mozilla...THIS_IS_SDPARTA-65.0 2266787997050267451 0 IN IP4 0.0.0.0
  s=-
  t=0 0
  a=sendrecv
  a=fingerprint:sha-256 79:3F:28:AD:AE:2A:B7:05:60:8D:53:CF:88:3B:88:32:9A:04:71:04:A3:B9:F3:08:D2:41:0C:38:95:41:21:F5
  a=group:BUNDLE 0 1 2 // Specify the mids to bundle
  a=ice-options:trickle
  a=msid-semantic:WMS *

  m=audio 63259 UDP/TLS/RTP/SAVPF 109 9 0 8 101 // For 1st audio track
  c=IN IP4 192.168.0.12
  a=candidate:0 1 UDP 2122252543 192.168.0.12 63259 typ host
  ... some candidates
  a=candidate:1 2 TCP 2105524478 192.168.0.12 9 typ host tcptype active
  a=sendrecv
  a=end-of-candidates
  a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
  ... some extmap
  a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
  a=fmtp:101 0-15
  a=ice-pwd:foo
  a=ice-ufrag:bar
  a=mid:0 // Identifier of m-line. Thus each m-line has one mid.
  a=msid:{aaaaa} {bbbbb} // Media Stream ID. There is msid in each m-line.
  a=rtcp-mux
  a=rtpmap:109 opus/48000/2
  ... some rtpmap
  a=setup:actpass
  a=ssrc:45563795 cname:{ccccc} // Except simulcast case, there is one ssrc in each m-line

  m=audio 63259 UDP/TLS/RTP/SAVPF 109 9 0 8 101 // For 2nd audio track
  c=IN IP4 192.168.0.12
  a=sendrecv
  a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
  ... some extmap
  a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
  a=fmtp:101 0-15
  a=ice-pwd:foo
  a=ice-ufrag:bar
  a=mid:1 // Identifier of m-line. Thus each m-line has one mid.
  a=msid:{ddddd} {eeeee} // Media Stream ID. There is msid in each m-line.
  a=rtcp-mux
  a=rtpmap:109 opus/48000/2
  ... some rtpmap
  a=setup:actpass
  a=ssrc:12345678 cname:{fffff} // Except simulcast case, there is one ssrc in each m-line

  m=video 63259 UDP/TLS/RTP/SAVPF 120 121 126 97 // For video track
  c=IN IP4 192.168.0.12
  a=sendrecv
  a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
  ... some extmap
  a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
  ... some fmtp
  a=ice-pwd:foo
  a=ice-ufrag:bar
  a=mid:2
  a=msid:{ggggg} {hhhhh}
  a=rtcp-fb:120 nack
  ... some rtcp-fb
  a=rtcp-mux
  a=rtpmap:120 VP8/90000
  ... some rtpmap
  a=setup:actpass
  a=ssrc:1242852923 cname:{iiiii}

webrtcpeer.js

var freeice = require('freeice');
var inherits = require('inherits');
var UAParser = require('ua-parser-js');
var uuid = require('uuid');
var hark = require('hark');
var EventEmitter = require('events').EventEmitter;
var recursive = require('merge').recursive.bind(undefined, true);
var sdpTranslator = require('sdp-translator');
try {
    require('kurento-browser-extensions');
} catch (error) {
    if (typeof getScreenConstraints === 'undefined') {
        console.warn('screen sharing is not available');
        getScreenConstraints = function getScreenConstraints(sendSource, callback) {
            callback(new Error('This library is not enabled for screen sharing'));
        };
    }
}
var MEDIA_CONSTRAINTS = {
        audio: true,
        video: {
            width: 640,
            framerate: 15
        }
    };
var ua = window && window.navigator ? window.navigator.userAgent : '';
var parser = new UAParser(ua);
var browser = parser.getBrowser();
var usePlanB = false;
if (browser.name === 'Chrome' || browser.name === 'Chromium') {
    console.log(browser.name + ': using SDP PlanB');
    usePlanB = true;
}
function noop(error) {
    if (error)
        console.error(error);
}
function trackStop(track) {
    track.stop && track.stop();
}
function streamStop(stream) {
    stream.getTracks().forEach(trackStop);
}
var dumpSDP = function (description) {
    if (typeof description === 'undefined' || description === null) {
        return '';
    }
    return 'type: ' + description.type + '\r\n' + description.sdp;
};
function bufferizeCandidates(pc, onerror) {
    var candidatesQueue = [];
    pc.addEventListener('signalingstatechange', function () {
        if (this.signalingState === 'stable') {
            while (candidatesQueue.length) {
                var entry = candidatesQueue.shift();
                this.addIceCandidate(entry.candidate, entry.callback, entry.callback);
            }
        }
    });
    return function (candidate, callback) {
        callback = callback || onerror;
        switch (pc.signalingState) {
        case 'closed':
            callback(new Error('PeerConnection object is closed'));
            break;
        case 'stable':
            if (pc.remoteDescription) {
                pc.addIceCandidate(candidate, callback, callback);
                break;
            }
        default:
            candidatesQueue.push({
                candidate: candidate,
                callback: callback
            });
        }
    };
}
function removeFIDFromOffer(sdp) {
    var n = sdp.indexOf('a=ssrc-group:FID');
    if (n > 0) {
        return sdp.slice(0, n);
    } else {
        return sdp;
    }
}
function getSimulcastInfo(videoStream) {
    var videoTracks = videoStream.getVideoTracks();
    if (!videoTracks.length) {
        console.warn('No video tracks available in the video stream');
        return '';
    }
    var lines = [
            'a=x-google-flag:conference',
            'a=ssrc-group:SIM 1 2 3',
            'a=ssrc:1 cname:localVideo',
            'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id,
            'a=ssrc:1 mslabel:' + videoStream.id,
            'a=ssrc:1 label:' + videoTracks[0].id,
            'a=ssrc:2 cname:localVideo',
            'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id,
            'a=ssrc:2 mslabel:' + videoStream.id,
            'a=ssrc:2 label:' + videoTracks[0].id,
            'a=ssrc:3 cname:localVideo',
            'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id,
            'a=ssrc:3 mslabel:' + videoStream.id,
            'a=ssrc:3 label:' + videoTracks[0].id
        ];
    lines.push('');
    return lines.join('\n');
}
function WebRtcPeer(mode, options, callback) {
    if (!(this instanceof WebRtcPeer)) {
        return new WebRtcPeer(mode, options, callback);
    }
    WebRtcPeer.super_.call(this);
    if (options instanceof Function) {
        callback = options;
        options = undefined;
    }
    options = options || {};
    callback = (callback || noop).bind(this);
    var self = this;
    var localVideo = options.localVideo;
    var remoteVideo = options.remoteVideo;
    var videoStream = options.videoStream;
    var audioStream = options.audioStream;
    var mediaConstraints = options.mediaConstraints;
    var connectionConstraints = options.connectionConstraints;
    var pc = options.peerConnection;
    var sendSource = options.sendSource || 'webcam';
    var dataChannelConfig = options.dataChannelConfig;
    var useDataChannels = options.dataChannels || false;
    var dataChannel;
    var guid = uuid.v4();
    var configuration = recursive({ iceServers: freeice() }, options.configuration);
    var onicecandidate = options.onicecandidate;
    if (onicecandidate)
        this.on('icecandidate', onicecandidate);
    var oncandidategatheringdone = options.oncandidategatheringdone;
    if (oncandidategatheringdone) {
        this.on('candidategatheringdone', oncandidategatheringdone);
    }
    var simulcast = options.simulcast;
    var multistream = options.multistream;
    var interop = new sdpTranslator.Interop();
    var candidatesQueueOut = [];
    var candidategatheringdone = false;
    Object.defineProperties(this, {
        'peerConnection': {
            get: function () {
                return pc;
            }
        },
        'id': {
            value: options.id || guid,
            writable: false
        },
        'remoteVideo': {
            get: function () {
                return remoteVideo;
            }
        },
        'localVideo': {
            get: function () {
                return localVideo;
            }
        },
        'dataChannel': {
            get: function () {
                return dataChannel;
            }
        },
        'currentFrame': {
            get: function () {
                if (!remoteVideo)
                    return;
                if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA)
                    throw new Error('No video stream data available');
                var canvas = document.createElement('canvas');
                canvas.width = remoteVideo.videoWidth;
                canvas.height = remoteVideo.videoHeight;
                canvas.getContext('2d').drawImage(remoteVideo, 0, 0);
                return canvas;
            }
        }
    });
    if (!pc) {
        pc = new RTCPeerConnection ({ sdpSemantics : "unified-plan" });
        if (useDataChannels && !dataChannel) {
            var dcId = 'WebRtcPeer-' + self.id;
            var dcOptions = undefined;
            if (dataChannelConfig) {
                dcId = dataChannelConfig.id || dcId;
                dcOptions = dataChannelConfig.options;
            }
            dataChannel = pc.createDataChannel(dcId, dcOptions);
            if (dataChannelConfig) {
                dataChannel.onopen = dataChannelConfig.onopen;
                dataChannel.onclose = dataChannelConfig.onclose;
                dataChannel.onmessage = dataChannelConfig.onmessage;
                dataChannel.onbufferedamountlow = dataChannelConfig.onbufferedamountlow;
                dataChannel.onerror = dataChannelConfig.onerror || noop;
            }
        }
    }
    pc.addEventListener('icecandidate', function (event) {
        var candidate = event.candidate;
        if (EventEmitter.listenerCount(self, 'icecandidate') || EventEmitter.listenerCount(self, 'candidategatheringdone')) {
            if (candidate) {
                var cand;
                if (multistream && usePlanB) {
                    cand = interop.candidateToUnifiedPlan(candidate);
                } else {
                    cand = candidate;
                }
                self.emit('icecandidate', cand);
                candidategatheringdone = false;
            } else if (!candidategatheringdone) {
                self.emit('candidategatheringdone');
                candidategatheringdone = true;
            }
        } else if (!candidategatheringdone) {
            candidatesQueueOut.push(candidate);
            if (!candidate)
                candidategatheringdone = true;
        }
    });
    pc.onaddstream = options.onaddstream;
    pc.onnegotiationneeded = options.onnegotiationneeded;
    this.on('newListener', function (event, listener) {
        if (event === 'icecandidate' || event === 'candidategatheringdone') {
            while (candidatesQueueOut.length) {
                var candidate = candidatesQueueOut.shift();
                if (!candidate === (event === 'candidategatheringdone')) {
                    listener(candidate);
                }
            }
        }
    });
    var addIceCandidate = bufferizeCandidates(pc);
    this.addIceCandidate = function (iceCandidate, callback) {
        var candidate;
        if (multistream && usePlanB) {
            candidate = interop.candidateToPlanB(iceCandidate);
        } else {
            candidate = new RTCIceCandidate(iceCandidate);
        }
        console.log('ICE candidate received');
        callback = (callback || noop).bind(this);
        addIceCandidate(candidate, callback);
    };
    this.generateOffer = function (callback) {
        callback = callback.bind(this);
        var offerAudio = true;
        var offerVideo = true;
        if (mediaConstraints) {
            offerAudio = typeof mediaConstraints.audio === 'boolean' ? mediaConstraints.audio : true;
            offerVideo = typeof mediaConstraints.video === 'boolean' ? mediaConstraints.video : true;
        }
        var browserDependantConstraints = browser.name === 'Firefox' && browser.version > 34 ? {
                offerToReceiveAudio: mode !== 'sendonly' && offerAudio,
                offerToReceiveVideo: mode !== 'sendonly' && offerVideo
            } : {
                mandatory: {
                    OfferToReceiveAudio: mode !== 'sendonly' && offerAudio,
                    OfferToReceiveVideo: mode !== 'sendonly' && offerVideo
                },
                optional: [{ DtlsSrtpKeyAgreement: true }]
            };
        var constraints = recursive(browserDependantConstraints, connectionConstraints);
        console.log('constraints: ' + JSON.stringify(constraints));
        pc.createOffer(constraints).then(function (offer) {
            console.log('Created SDP offer');
            offer = mangleSdpToAddSimulcast(offer);
            return pc.setLocalDescription(offer);
        }).then(function () {
            var localDescription = pc.localDescription;
            console.log('Local description set', localDescription.sdp);
            if (multistream && usePlanB) {
                localDescription = interop.toUnifiedPlan(localDescription);
                console.log('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription));
            }
            callback(null, localDescription.sdp, self.processAnswer.bind(self));
        }).catch(callback);
    };
    this.getLocalSessionDescriptor = function () {
        return pc.localDescription;
    };
    this.getRemoteSessionDescriptor = function () {
        return pc.remoteDescription;
    };
    function setRemoteVideo() {
        if (remoteVideo) {
            var stream = pc.getRemoteStreams()[0];
            var url = stream;
            remoteVideo.pause();
            remoteVideo.srcObject = url;
            remoteVideo.load();
            console.log('Remote URL:', url);
        }
    }
    this.showLocalVideo = function () {
        localVideo.srcObject = videoStream;
        localVideo.muted = true;
    };
    this.send = function (data) {
        if (dataChannel && dataChannel.readyState === 'open') {
            dataChannel.send(data);
        } else {
            console.warn('Trying to send data over a non-existing or closed data channel');
        }
    };
    this.processAnswer = function (sdpAnswer, callback) {
        callback = (callback || noop).bind(this);
        var answer = new RTCSessionDescription({
                type: 'answer',
                sdp: sdpAnswer
            });
        if (multistream && usePlanB) {
            var planBAnswer = interop.toPlanB(answer);
            console.log('asnwer::planB', dumpSDP(planBAnswer));
            answer = planBAnswer;
        }
        console.log('SDP answer received, setting remote description');
        if (pc.signalingState === 'closed') {
            return callback('PeerConnection is closed');
        }
        pc.setRemoteDescription(answer, function () {
            setRemoteVideo();
            callback();
        }, callback);
    };
    this.processOffer = function (sdpOffer, callback) {
        callback = callback.bind(this);
        var offer = new RTCSessionDescription({
                type: 'offer',
                sdp: sdpOffer
            });
        if (multistream && usePlanB) {
            var planBOffer = interop.toPlanB(offer);
            console.log('offer::planB', dumpSDP(planBOffer));
            offer = planBOffer;
        }
        console.log('SDP offer received, setting remote description');
        if (pc.signalingState === 'closed') {
            return callback('PeerConnection is closed');
        }
        pc.setRemoteDescription(offer).then(function () {
            return setRemoteVideo();
        }).then(function () {
            return pc.createAnswer();
        }).then(function (answer) {
            answer = mangleSdpToAddSimulcast(answer);
            console.log('Created SDP answer');
            return pc.setLocalDescription(answer);
        }).then(function () {
            var localDescription = pc.localDescription;
            if (multistream && usePlanB) {
                localDescription = interop.toUnifiedPlan(localDescription);
                console.log('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription));
            }
            console.log('Local description set', localDescription.sdp);
            callback(null, localDescription.sdp);
        }).catch(callback);
    };
    function mangleSdpToAddSimulcast(answer) {
        if (simulcast) {
            if (browser.name === 'Chrome' || browser.name === 'Chromium') {
                console.log('Adding multicast info');
                answer = new RTCSessionDescription({
                    'type': answer.type,
                    'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream)
                });
            } else {
                console.warn('Simulcast is only available in Chrome browser.');
            }
        }
        return answer;
    }
    function start() {
        if (pc.signalingState === 'closed') {
            callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
        }
        if (videoStream && localVideo) {
            self.showLocalVideo();
        }
        if (videoStream) {
            pc.addStream(videoStream);
        }
        if (audioStream) {
            pc.addStream(audioStream);
        }
        var browser = parser.getBrowser();
        if (mode === 'sendonly' && (browser.name === 'Chrome' || browser.name === 'Chromium') && browser.major === 39) {
            mode = 'sendrecv';
        }
        callback();
    }
    if (mode !== 'recvonly' && !videoStream && !audioStream) {
        function getMedia(constraints) {
            if (constraints === undefined) {
                constraints = MEDIA_CONSTRAINTS;
            }
            getUserMedia(constraints, function (stream) {
                videoStream = stream;
                start();
            }, callback);
        }
        if (sendSource === 'webcam') {
            getMedia(mediaConstraints);
        } else {
            getScreenConstraints(sendSource, function (error, constraints_) {
                if (error)
                    return callback(error);
                constraints = [mediaConstraints];
                constraints.unshift(constraints_);
                getMedia(recursive.apply(undefined, constraints));
            }, guid);
        }
    } else {
        setTimeout(start, 0);
    }
    this.on('_dispose', function () {
        if (localVideo) {
            localVideo.pause();
            localVideo.srcObject = '';
            localVideo.load();
            localVideo.muted = false;
        }
        if (remoteVideo) {
            remoteVideo.pause();
            remoteVideo.srcObject = '';
            remoteVideo.load();
        }
        self.removeAllListeners();
        if (window.cancelChooseDesktopMedia !== undefined) {
            window.cancelChooseDesktopMedia(guid);
        }
    });
}
inherits(WebRtcPeer, EventEmitter);
function createEnableDescriptor(type) {
    var method = 'get' + type + 'Tracks';
    return {
        enumerable: true,
        get: function () {
            if (!this.peerConnection)
                return;
            var streams = this.peerConnection.getLocalStreams();
            if (!streams.length)
                return;
            for (var i = 0, stream; stream = streams[i]; i++) {
                var tracks = stream[method]();
                for (var j = 0, track; track = tracks[j]; j++)
                    if (!track.enabled)
                        return false;
            }
            return true;
        },
        set: function (value) {
            function trackSetEnable(track) {
                track.enabled = value;
            }
            this.peerConnection.getLocalStreams().forEach(function (stream) {
                stream[method]().forEach(trackSetEnable);
            });
        }
    };
}
Object.defineProperties(WebRtcPeer.prototype, {
    'enabled': {
        enumerable: true,
        get: function () {
            return this.audioEnabled && this.videoEnabled;
        },
        set: function (value) {
            this.audioEnabled = this.videoEnabled = value;
        }
    },
    'audioEnabled': createEnableDescriptor('Audio'),
    'videoEnabled': createEnableDescriptor('Video')
});
WebRtcPeer.prototype.getLocalStream = function (index) {
    if (this.peerConnection) {
        return this.peerConnection.getLocalStreams()[index || 0];
    }
};
WebRtcPeer.prototype.getRemoteStream = function (index) {
    if (this.peerConnection) {
        return this.peerConnection.getRemoteStreams()[index || 0];
    }
};
WebRtcPeer.prototype.dispose = function () {
    console.log('Disposing WebRtcPeer');
    var pc = this.peerConnection;
    var dc = this.dataChannel;
    try {
        if (dc) {
            if (dc.signalingState === 'closed')
                return;
            dc.close();
        }
        if (pc) {
            if (pc.signalingState === 'closed')
                return;
            pc.getLocalStreams().forEach(streamStop);
            pc.close();
        }
    } catch (err) {
        console.warn('Exception disposing webrtc peer ' + err);
    }
    this.emit('_dispose');
};
function WebRtcPeerRecvonly(options, callback) {
    if (!(this instanceof WebRtcPeerRecvonly)) {
        return new WebRtcPeerRecvonly(options, callback);
    }
    WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback);
}
inherits(WebRtcPeerRecvonly, WebRtcPeer);
function WebRtcPeerSendonly(options, callback) {
    if (!(this instanceof WebRtcPeerSendonly)) {
        return new WebRtcPeerSendonly(options, callback);
    }
    WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback);
}
inherits(WebRtcPeerSendonly, WebRtcPeer);
function WebRtcPeerSendrecv(options, callback) {
    if (!(this instanceof WebRtcPeerSendrecv)) {
        return new WebRtcPeerSendrecv(options, callback);
    }
    WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback);
}
inherits(WebRtcPeerSendrecv, WebRtcPeer);
function harkUtils(stream, options) {
    return hark(stream, options);
}
exports.bufferizeCandidates = bufferizeCandidates;
exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
exports.hark = harkUtils;

I want to offer above mentioned sdp , however chrome is offering its defualt sdp. Also I have updated to unified plan in webrtcpeer.js , however chrome is running on planb.


in console I get:

This appears to be Chrome
WebRtcPeer.js:30 Chrome: using SDP PlanB

Demo starts but rooms are empty

I followed your instructions, demo starts correctly but if i open 2 different windows and inserting a name and "room1" in the first one and a different name and "room1" in the second one, i only get a blue window with the room name and the button "leave room", and nothing else.
I followed your instructions but it does not work, what im doing wrong?

Timout Error when number of users is reached [Error: Request has timed out]

How many users can the kurento handle when using SFU of kurento-group-call node?

I tried to implement the group call node SFU on a local server. I'm running the KMS server on a virtual machine with 4GB dedicated memory. I was able to successfully enter up to 15 users without errors. But when the 16th user tries to enter, I get the timeout error and the remote videos from other users did not appear.

{ [Error: Request has timed out]
request: '{"jsonrpc":"2.0","method":"invoke","params":{"object":"c2ba9879-d04e-446b-abb7-66629eb41119_kurento.MediaPipeline/413426fd-927c-41de-acc7-47d52654719a_kurento.WebRtcEndpoint","operation":"connect","operationParams":{"sink":"c2ba9879-d04e-446b-abb7-66629eb41119_kurento.MediaPipeline/d233ed2d-ca10-4783-9dc3-bd5de656e07c_kurento.WebRtcEndpoint"},"sessionId":"26449ab3-433e-4335-88b9-86e435578e04"},"id":792}',
retry: [Function: retry] }

Many Viewers

Hello,

How can I add many viewers in this project ? I'm new on kurento. I want to start one presenter first and then it will be more presenter with many viewers. I want to understand logic.

Thank you :)

Is this SFU or Mesh?

Hey,

I've reviewed your code and it doesn't look like sfu to me. It is Mesh topology again as shown in kurento examples. Please correct me if I am wrong.

Record Video

I focus on the mobile app, please code for record room.

Error gathering candidates

Hi , First of all thanks for providing an example for making a group call using node. my problem is whenever a new user enters the room node gives me this error " Error gathering candidates". The problem is coming from this line endpoint.gatherCandidates(error => {
if (error) {
return callback(error);
}
});
and There are no videos working on the page except for the local one.
Thanks in advance

recording Room

Can you help me figure out how to record all the participants of the room?

Thanks

ERROR : Failed to execute createObjectURL on chrome

Hi Chapin666,

This is the error we are facing when inspect the chrome browser for errors with your nodejs group call server.

Uncaught TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided.
at WebRtcPeerSendonly.WebRtcPeer.showLocalVideo (WebRtcPeer.js:304)

Please do let me know if you have any suggestions.

Thanks & Regards,
Sudhish
[email protected]

Add filters

How can I add a filter? for example the faceOverlayFilter (or others)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.