一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话

03-13 1441阅读 0评论

一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话

        • 1. 运行结果
        • 2. 实现
          • 2.1 后端实现
          • 2.2 前端页面实现
          • 3. 总结
            1. 运行结果

            SpringBoot+WebSocket+WebRTC实现视频通话

            一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话,一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,设置,前端,第1张
            (图片来源网络,侵删)

            上述运行结果中是有声音(比较小而已)及动的画面的(画面不是静止的)。

            网上关于webrtc的文档(文章)和视频也挺多的,但是用SpringBoot结合WebRTC的却屈指可数,前一段时间小编我学习了一下WebRTC的相关知识,于是用SpringBoot+WebRTC实现了一个多人的线上自习室(有画面,但是没有声音的那种,开启声音也挺简单,在js代码里设置一下即可[运行结果在最后的总结里])。最近CSDN有活动,正好把前一段时间学习的知识运用起来(下述代码只是实现了,但是其中的逻辑是存在一定问题的,所以如果读者用下述代码,切记需要改动改动哈!)。既然是WebRTC,为什么又和WebSocket扯上关系了呢?因为利用WebSocket技术来发送消息具有实时性,你看我在这端发送一个消息出去,只要另一端处于连接状态,那么就可以接收到这个消息。而如果使用的是http、https等的话,这一端你发送一个消息,另外一段需要刷新一下页面才能看到消息(当然可以搞个定时器)。结合WebSocket技术,能很快速地实现一个视频通话功能。

            2. 实现

            导入相关jar包的依赖,如下:

            
                4.0.0
                
                    org.springframework.boot
                    spring-boot-starter-parent
                    2.7.10
                     
                
                com.example
                demo
                0.0.1-SNAPSHOT
                demo
                Demo project for Spring Boot
                
                    1.8
                
                
                    
                        org.springframework.boot
                        spring-boot-starter-web
                    
                    
                        org.springframework.boot
                        spring-boot-starter-test
                        test
                    
                    
                        org.springframework.boot
                        spring-boot-devtools
                        runtime
                        true
                    
                    
                        org.springframework.boot
                        spring-boot-starter-thymeleaf
                    
                    
                        org.springframework.boot
                        spring-boot-starter-websocket
                    
                    
                        org.projectlombok
                        lombok
                    
                
                
                    
                        
                            org.springframework.boot
                            spring-boot-maven-plugin
                        
                    
                
            
            

            上述jar包可能有一些不需要的喔!

            2.1 后端实现

            websocket 配置类

            GetHttpSessionConfig.class

            一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话,一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,设置,前端,第2张
            (图片来源网络,侵删)
            package com.example.demo.websocket2;
            import javax.servlet.http.HttpSession;
            import javax.websocket.HandshakeResponse;
            import javax.websocket.server.HandshakeRequest;
            import javax.websocket.server.ServerEndpointConfig;
            public class GetHttpSessionConfig extends ServerEndpointConfig.Configurator {
                @Override
                public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
                    HttpSession httpSession = (HttpSession) request.getHttpSession();
                    // 获取httpsession对象
                    sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
                }
            }
            

            ServerEndpointExporter Bean的定义 Config.class

            package com.example.demo.websocket2;
            import org.springframework.context.annotation.Bean;
            import org.springframework.context.annotation.Configuration;
            import org.springframework.web.socket.server.standard.ServerEndpointExporter;
            @Configuration
            public class Config {
                @Bean
                public ServerEndpointExporter serverEndpointExporter() {
                    return new ServerEndpointExporter();
                }
            }
            

            *websocket服务器类 WebSocketServer *

            package com.example.demo.websocket2;
            import org.springframework.stereotype.Component;
            import javax.servlet.http.HttpSession;
            import javax.websocket.*;
            import javax.websocket.server.ServerEndpoint;
            import java.io.IOException;
            import java.util.Map;
            import java.util.Set;
            import java.util.concurrent.ConcurrentHashMap;
            @Component
            @ServerEndpoint(value = "/video",configurator = GetHttpSessionConfig.class)
            public class WebSocketServer {
                //存储客户端的连接对象,每个客户端连接都会产生一个连接对象
                private static ConcurrentHashMap map = new ConcurrentHashMap();
                //每个连接都会有自己的会话
                private Session session;
                private String account;
                @OnOpen
                public void open(Session session,EndpointConfig config){
                    HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
                    String account = String.valueOf(httpSession.getAttribute("account"));
                    map.put(account,this);
                    this.session = session;
                    this.account = account;
                }
                @OnClose
                public void close(){
                    map.remove(account);
                }
                @OnError
                public void error(Throwable error){
                    error.printStackTrace();
                }
                @OnMessage
                public void getMessage(String message) throws IOException {
                    Set entries = map.entrySet();
                    for (Map.Entry entry : entries) {
                        if(!entry.getKey().equals(account)){//将消息转发到其他非自身客户端
                            entry.getValue().send(message);
                        }
                    }
                }
                public void send(String message) throws IOException {
                    if(session.isOpen()){
                        session.getBasicRemote().sendText(message);
                    }
                }
                public int  getConnetNum(){
                    return map.size();
                }
            }
            
            2.2 前端页面实现

            登录界面的代码就不在这儿粘贴了,下面主要展示视频通话界面的代码(包括css样式和js代码都在的)

            
                main
                
            
            
                body {
                    background: #eee;
                    padding: 5% 0;
                }
                video {
                    background: black;
                    border: 1px solid gray;
                }
                .call-page {
                    position: relative;
                    display: block;
                    margin: 0 auto;
                    width: 500px;
                    height: 500px;
                }
                #localVideo {
                    width: 150px;
                    height: 150px;
                    position: absolute;
                    top: 15px;
                    right: 15px;
                }
                #remoteVideo {
                    width: 500px;
                    height: 500px;
                }
            
            
            
            Call Hang Up
            //our username var connectedUser; //connecting to our signaling server var conn = new WebSocket("ws://localhost:9999/video"); conn.onopen = function () { console.log("Connected to the signaling server"); }; //when we got a message from a signaling server conn.onmessage = function (msg) { console.log("Got message", msg.data); var data = JSON.parse(msg.data); switch(data.type) { case "login": handleLogin(data.success); break; //when somebody wants to call us case "offer": handleOffer(data.offer, data.name); break; case "answer": handleAnswer(data.answer); break; //when a remote peer sends an ice candidate to us case "candidate": handleCandidate(data.candidate); break; case "leave": handleLeave(); break; default: break; } }; conn.onerror = function (err) { console.log("Got error", err); }; //alias for sending JSON encoded messages function send(message) { //attach the other peer username to our messages if (connectedUser) { message.name = connectedUser; } conn.send(JSON.stringify(message)); } //****** //UI selectors block //****** var callPage = document.querySelector("#callPage"); var callToUsernameInput = document.querySelector("#callToUsernameInput"); var callBtn = document.querySelector("#callBtn"); var hangUpBtn = document.querySelector("#hangUpBtn"); var localVideo = document.querySelector("#localVideo"); var remoteVideo = document.querySelector("#remoteVideo"); var yourConn; var stream; // callPage.style.display = "none"; var PeerConnection = (window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.RTCPeerConnection || undefined); var RTCSessionDescription = (window.webkitRTCSessionDescription || window.mozRTCSessionDescription || window.RTCSessionDescription || undefined); navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); //********************** //Starting a peer connection //********************** //getting local video stream navigator.getUserMedia({ video: true, audio: true }, function (myStream) { stream = myStream; //displaying local video stream on the page localVideo.srcObject = stream; //using Google public stun server var configuration = { "iceServers": [] }; yourConn = new PeerConnection(configuration); // setup stream listening yourConn.addStream(stream); //when a remote user adds stream to the peer connection, we display it yourConn.onaddstream = function (e) { remoteVideo.srcObject = e.stream; }; // Setup ice handling yourConn.onicecandidate = function (event) { if (event.candidate) { send({ type: "candidate", candidate: event.candidate }); } }; }, function (error) { console.log(error); }); //initiating a call callBtn.addEventListener("click", function () { var callToUsername = callToUsernameInput.value; if (callToUsername.length > 0) { connectedUser = callToUsername; // create an offer yourConn.createOffer(function (offer) { send({ type: "offer", offer: offer }); yourConn.setLocalDescription(offer); }, function (error) { alert("Error when creating an offer"); }); } }); //when somebody sends us an offer function handleOffer(offer, name) { connectedUser = name; yourConn.setRemoteDescription(new RTCSessionDescription(offer)); //create an answer to an offer yourConn.createAnswer(function (answer) { yourConn.setLocalDescription(answer); send({ type: "answer", answer: answer }); }, function (error) { alert("Error when creating an answer"); }); } //when we got an answer from a remote user function handleAnswer(answer) { yourConn.setRemoteDescription(new RTCSessionDescription(answer)); } //when we got an ice candidate from a remote user function handleCandidate(candidate) { yourConn.addIceCandidate(new RTCIceCandidate(candidate)); } //hang up hangUpBtn.addEventListener("click", function () { send({ type: "leave" }); handleLeave(); }); function handleLeave() { connectedUser = null; remoteVideo.src = null; yourConn.close(); yourConn.onicecandidate = null; yourConn.onaddstream = null; }
            3. 总结

            上述前端代码参考来自这里:webrtc视频演示,上述代码中如果有不懂的读者可以去仔细看看这个链接里的知识,里面关于webrtc有详细的介绍及实现,不过,没有讲多人的,它只讲了一对一的,不过,前一段时间小编在参考一些大佬的实现思路及自己思考下,也实现了一个多人的,运行结果如下:

            基于SpringBoot,WebSocket,WebRTC实现多人自习室功能

            一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话,一小时教你用SpringBoot+WebSocket+WebRTC实现视频通话,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,设置,前端,第3张
            (图片来源网络,侵删)

免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1441人围观)

还没有评论,来说两句吧...

目录[+]