Buid Group video calling using WebRTC

Viewed 382

WebSocket Using WebRTC easy to implement peer to peer video calling. But how to implement group video calling using WebRTC and WebSocket in Spring Boot.?

                import org.springframework.context.annotation.Configuration;
                import org.springframework.web.socket.config.annotation.EnableWebSocket;
                import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
                import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
                
                import com.call.event.ConnectionHandler;
                
                @Configuration
                @EnableWebSocket
                public class WebSocketConfiguration implements WebSocketConfigurer {
                
                    @Override
                    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
                        registry.addHandler(new ConnectionHandler(), "/call").setAllowedOrigins("*");
                    }
                }
           

ConnectionHandler Here Socket Handler.We handle all user session and socket and payoads.

            import java.io.IOException;
            import java.util.List;
            import java.util.concurrent.CopyOnWriteArrayList;
                                    System.out.println("Got signal - " + message.getPayload());

            import org.springframework.stereotype.Component;
            import org.springframework.web.socket.CloseStatus;
            import org.springframework.web.socket.TextMessage;
            import org.springframework.web.socket.WebSocketSession;
            import org.springframework.web.socket.handler.TextWebSocketHandler;
            
            @Component
            public class ConnectionHandler extends TextWebSocketHandler {
                List<WebSocketSession>sessions = new CopyOnWriteArrayList<>();
            
                @Override
                public void handleTextMessage(WebSocketSession session, TextMessage message)
                  throws InterruptedException, IOException {
                    System.out.println("Got signal - " + message.getPayload());
                    for (WebSocketSession webSocketSession : sessions) {
                        if (webSocketSession.isOpen() && !session.getId().equals(webSocketSession.getId())) {
                            webSocketSession.sendMessage(message);
                        }
                    }
                }
            
                @Override
                public void afterConnectionEstablished(WebSocketSession session) throws Exception {
                    sessions.add(session);
                    System.out.println("-----------------------------------------------------------------------------");
                    System.out.println("Connection opened!");
                    System.out.println("-----------------------------------------------------------------------------");
                }
                @Override
                public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
                    System.out.println("-----------------------------------------------------------------------------");
                    System.out.println("Connection Closed!");
                    System.out.println("-----------------------------------------------------------------------------");
                    sessions.add(session);
                }
            }
        
        

WebRTC code Here WebRTC code for Peer to Peer connection. We using webRTC for getUserMedia and DataChanells.

        let peerConnection=null;
        let localVideo;
        let localStream;
        let videoTrack;
        let audioTrack;
        let stream;
        let signal;
        var signalingWebsocket = new WebSocket("ws://localhost:8080/call");
        
        signalingWebsocket.onmessage = function(msg) {
            console.log("Got message", msg.data);
            signal = JSON.parse(msg.data);
            switch (signal.type) {
                 
                case "offer":
                    handleOffer(signal);
                    break;
                case "answer":
                    handleAnswer(signal);
                    break;
                // In local network, ICE candidates might not be generated.
                case "candidate":
                    handleCandidate(signal);
                    break;
                default:
                    break;
            }
        };
        
        signalingWebsocket.onopen = init();
        
        
        function sendSignal(signal) {
            if (signalingWebsocket.readyState == 1) {
                signalingWebsocket.send(JSON.stringify(signal));
        
            }
        };
        
        /*
         * Initialize
         */
        function init() {
            console.log("Connected to signaling endpoint. Now initializing.");    
            preparePeerConnection();
            displayLocalStream(true);
        
        };
        
        /*
         * Prepare RTCPeerConnection & setup event handlers.
         */
        function preparePeerConnection() {
            
             // Using free public google STUN server.
            const configuration = {
                iceServers: [{
                    urls: 'stun:stun.l.google.com:19302'
                }]
            };
        
            // Prepare peer connection object
            peerConnection = new webkitRTCPeerConnection(configuration, {optional: [{RtpDataChannels: true}]});
            peerConnection.onnegotiationneeded = async () => {
                console.log('onnegotiationneeded');
                sendOfferSignal();
               
            };
            peerConnection.onicecandidate = function(event) {
                if (event.candidate) {
                    sendSignal(event);
                }
            };
        
             peerConnection.addEventListener('track', displayRemoteStream);
        
        };
        
        async function displayLocalStream(firstTime) {
            console.log('Requesting local stream');
            localVideo = document.getElementById('localVideo');
            try {
                stream = await navigator.mediaDevices.getUserMedia({
                    video: {
                        width: 500,
                        height: 300
                    },
                    audio: false
                });
                console.log('Received local stream');
                localVideo.srcObject = stream;
                localStream = stream;
                videoAudioTrackInfo(localStream);
                console.log(stream);
                // For first time, add local stream to peer connection.
                if (firstTime) {
                    setTimeout(
                        function() {
                            addLocalStreamToPeerConnection(localStream);
                        }, 2000);
                }
        
                // Send offer signal to signaling server endpoint.
                sendOfferSignal();
        
            } catch (e) {
                alert(`getUserMedia() error: ${e.name}`);
                throw e;
            }
            console.log('Start complete');
        }
        
        function videoAudioTrackInfo(localStream) {
            videoTrack = localStream.getVideoTracks();
            audioTrack = localStream.getAudioTracks();
            if (videoTrack.length > 0) {
                console.log(`Using video device: ${videoTrack[0].label}`);
            }
            if (audioTrack.length > 0) {
                console.log(`Using audio device: ${audioTrack[0].label}`);
            }
        }
        
        
        async function addLocalStreamToPeerConnection(localStream) {
            console.log('Starting addLocalStreamToPeerConnection');
            localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));
            console.log('localStream tracks added');
        };
        
        
        function sendOfferSignal() {
            peerConnection.createOffer(function(offer) {
                sendSignal(offer);
                peerConnection.setLocalDescription(offer);
            }, function(error) {
                alert("Error creating an offer");
            });
        };
        
        function handleOffer(offer) {
            peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
            peerConnection.createAnswer(function(answer) {
                peerConnection.setLocalDescription(answer);
                sendSignal(answer);
            }, function(error) {
                alert("Error creating an answer");
            });
        };
        
        function handleAnswer(answer) {
            peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
            console.log("connection established successfully!!");
        };
        
        function handleCandidate(candidate) {
            alert("handleCandidate");
            peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
            
        };
        
        function displayRemoteStream(e) {
            console.log('displayRemoteStream');
            const remoteVideo = document.getElementById('remoteVideo');
            if (remoteVideo.srcObject !== e.streams[0]) {
                remoteVideo.srcObject = e.streams[0];
                console.log('pc2 received remote stream');
            }
        };
        
        
        function leaveMeeting() {
            let cnf=confirm("Are you sure for leave meeting!")
            if(cnf==true){
                console.log('Ending call');
                peerConnection.close();
                signalingWebsocket.close();
                window.location.href = '/';
            }else{
                console.log('you are in meeting....');
            }
        };
0 Answers
Related