其他分享
首页 > 其他分享> > WebSocket + GatewayWorker 实现webRtc 通讯

WebSocket + GatewayWorker 实现webRtc 通讯

作者:互联网

本文使用 GatewayWorker 实现信令

使用WebSocket  与 GatewayWorker  创建信令通讯

 

废话少说,直接上代码吧 

配置好相应代码后请根据本文下面的使用方法进行使用,具体根据你业务进行修改

1. GatewayWorker 下载

2. 修改GatewayWorker  配置

  

  修改成 websocket 协议

 3. 修改 onConnect中的代码

  

//创建WebSocket连接后返回 事件event = bindUser给前端,前端通过client_id 绑定uid
$data['data'] = [
    'client_id' =>  $client_id
];
$data['event'] = 'bindUser';
Gateway::sendToClient($client_id, json_encode($data));

4. 修改 onMessage  

  

$request = json_decode($data,true);
$data = $request['data'];
$return_data = [
   'status' => 200,
   'msg' => '成功',
   'data' => $data,
   'event' => $request['cmd'],  //怎么传过来怎么返回, 前端事件通过事件创建通讯
   'from_uid' => $request['from_uid'], //发送人uid
   'to_uid' => $request['to_uid']   //接收人uid
];
switch ($request['cmd']) {
   case 'bindUser':  //绑定uid
       Gateway::bindUid($client_id, $request['from_uid']);
       $return_data['event'] = 'bindUserCallback';
       $return_data['msg'] = '绑定uid成功';
       $receive_uid = $request['from_uid'];
       break;
   default:
       $receive_uid = $request['to_uid'];
       break;
}
//发送人
Gateway::sendToUid($receive_uid, json_encode($return_data));

  到此为止 php  代码就写完了

5. 前端代码 首先我们先了解一下webRtc 连接的原理 大概就是这样

 

下面是前端代码

 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            border: 1px solid red;
        }
        video{
            width: 100%;
            height: 100%;
        }
        .call{
            line-height: 100px;
            width: 100px;
            height: 100px;
            border: 1px solid red;
            display: none;
        }
    </style>
</head>
<body>
    <div><video id="localVideo" autoplay></video></div>
    <div><video id="remoteVideo" autoplay class="hidden"></video></div>
    <button onclick="call()">呼叫</button>

    <div class="call">
        <button onclick="received()">接听</button>
        <button onclick="refuse()">拒绝</button>
    </div>
   
    

    <script src="./jquery-3.6.0.min.js"></script>
    <script>
        var ws_url = '';
        var localVideo = document.getElementById('localVideo');
        var remoteVideo = document.getElementById('remoteVideo');

        var from_uid = getUrlParam('from_uid');  //自己的uid
        var to_uid = getUrlParam('to_uid'); // 好友的uid
        

        var ws = new WebSocket(ws_url);
        ws.onopen = function(){
            console.log('创建WebSocket成功');
        };

        ws.onmessage = function(e){
            var data = JSON.parse(e.data);
            console.log(data)

            // eval(package.event+'(' + JSON.stringify(package.data) + ')')
            switch(data.event){
                case 'bindUser':
                    send('bindUser', {});
                    break;
                case 'bindUserCallback':
                    console.log('uid绑定成功!')
                    break;
                case 'videoChat':
                    let type = data.data.type;
                    if(data.status != 200){
                        alert(data.msg);
                    }
                    !to_uid ? to_uid = data.to_uid : '';

                    data = data.data

                    //收到呼叫
                    if(type == 'call'){
                        called();
                    }else if(type == 'received'){
                        webRtc.createOffer(function(data){
                            console.log('呼叫方创建offer');
                            send('videoChat',{data: data,type: 'offer'})
                        })
                    }else if(type == 'candidate'){
                        console.log('保存candidate');
                        webRtc.addIceCandidate(data.data)
                    }else if(type == 'offer'){
                        console.log('被呼叫方收到offer,创建answer');
                        webRtc.createAnswer(data.data,function(data){
                            send('videoChat',{data: data,type: 'answer'})
                        });
                    }else if(type == 'answer'){
                        console.log('呼叫方保存answer');
                        webRtc.addAnswer(data.data);
                    }

                    break;
            }
 
        }


        function send(cmd,data){
            ws.send(JSON.stringify({
                cmd: cmd,
                data: data,
                from_uid: from_uid,
                to_uid: to_uid
            }))
        }

        //呼叫
        function call(){
            media.call()
            if(!to_uid){
                alert('接收人不能为空!');
                return;
            }
            send('videoChat',{type: 'call'});
        }
        
        function called(){
            console.log('收到呼叫')
            $('.call').show();
        }

        function received(){
            media.called();
            console.log('接听')
        }

      
        function refuse(){
            send('call',{type: 'refuse'});
            to_uid ? to_uid = 0 : '';
            console.log('拒绝')
        }
       
        let media = {
            candidate: {},
            offer: {},
            //呼叫方
            call(){
                let that = this;
                that.authorize(function(){
                    webRtc.createRtc(function(data){
                        console.log('呼叫方创建连接成功')
                    },function(data){
                        send('videoChat',{data: data,type: 'candidate'});
                    });
                })
            },
            //被呼叫 - 接听
            called(){
                let that = this;
                that.authorize(function(){
                    webRtc.createRtc(function(data){
                        console.log('被呼叫创建连接成功')
                        send('videoChat',{type: 'received'});
                    },function(data){
                        send('videoChat',{data: data, type: 'candidate'} );
                    });
                })
            },
            authorize(c){
                navigator.mediaDevices.getUserMedia({
                    audio: true,
                    video: true
                }).then(function (stream) {
                    localVideo.srcObject = stream;
                    webRtc.stream = stream;
                    c();

                    localVideo.addEventListener('loadedmetadata', function () {
                        console.log('加载视频流');
                    });
                }).catch(function (e) {
                    alert(e);
                });
            }
        }

        
        let webRtc = {
            stream: {},
            pc: {},
            createRtc(c,candidataCallback){
                let that = this;
                var configuration = {
                    iceServers: [{
                        urls: 'stun:stun.xten.com'
                    }]
                };
                let pc = new RTCPeerConnection(configuration);
                c(pc);
                pc.onicecandidate = function (event) {
                    if (event.candidate) {
                        candidataCallback(event.candidate)
                    }
                };
                try{
                    pc.addStream(that.stream);
                }catch(e){
                    var tracks = that.stream.getTracks();
                    for(var i=0;i<tracks.length;i++){
                        pc.addTrack(tracks[i], that.stream);
                    }
                }
                pc.onaddstream = function (e) {
                    console.log('回调视频流');
                    remoteVideo.srcObject = e.stream;
                };
                this.pc = pc
            },
    
            //保存Candidate
            addIceCandidate(data){
                this.pc.addIceCandidate(new RTCIceCandidate(data), function(){}, function(e){alert(e);});
            },
            //创建offer
            createOffer(c){
                let pc = this.pc
                pc.createOffer({
                    offerToReceiveAudio: 1,
                    offerToReceiveVideo: 1
                }).then(function (desc) {
                    pc.setLocalDescription(desc).then(
                        function () {
                            c(pc.localDescription);
                        }
                    ).catch(function (e) {
                        alert(e);
                    });
                }).catch(function (e) {
                    alert(e);
                });
            },
            //根据offer 创建 answer
            createAnswer(data,c){
                let pc = this.pc
                let answer = 0;
                pc.setRemoteDescription(new RTCSessionDescription(data), function(){
                    if (answer == 0) {
                        pc.createAnswer(function (desc) {
                            pc.setLocalDescription(desc, function () {
                                c(pc.localDescription);
                            }, function(e){
                                alert(e);
                            });
                        }
                        ,function(e){
                            alert(e);
                        });
                        answer = 1;
                    }
                }, function(e){
                    alert(e);
                });
            },
            addAnswer(data){
                this.pc.setRemoteDescription(new RTCSessionDescription(data),function(){}, function(e){
                    alert(e);
                });
            }
        }
 

        function getUrlParam(name) {
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
            var r = window.location.search.substr(1).match(reg);
            if (r != null) return unescape(r[2]);
            return null;
        }


    </script>
</body>
</html>

  

设置WebSocket 连接地址  GatewayWorker 默认端口是8282
winwods 双击下面文件运行 ,liunx 进入下面这个目录 执行 php start.php start -d 以守护进程方式运行

 

注意!注意!注意!

同个电脑不同的浏览器不能同时打开摄像头

所以这里建议放到服务器上,并设置wss连接,否则不能使用

修改liunx 配置文件,添加下面代码

location /wss/ {
proxy_pass http://127.0.0.1:8282;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}

 然后WebSocket 的地址为服务器域名就行 

 

使用方法:

1. 发送方   https://域名/index.html?from_uid=1&to_uid=2

2. 接收方   https://域名/index.html?from_uid=2

3. 发送方点击呼叫,接收方会出现接口拒绝按钮,点击接听既可创建通信

标签:function,WebSocket,uid,type,webRtc,console,data,GatewayWorker,log
来源: https://www.cnblogs.com/quan846951943/p/16273637.html