php swoole实现webrtc支持内网外网p2p视频通话的html代码
webrt内网不需要turn及stun服务器就能实现p2p链接,但是如果是通讯设备在各种的内网中的话就需要stun及turn来进行打通或中继了,首先
1、交换sdp信息
SDP(会话描述协议)信息包含了一些关键的元数据,用于建立和维护音视频通信会话。SDP通常包括以下主要信息:
会话名称(Session Name): 会话的名称或标识符,用于标识这个会话。
会话信息(Session Information): 会话的一般信息,通常是一段描述性的文本。
媒体类型(Media Types): 描述会话中使用的媒体类型,通常包括音频和视频。媒体类型通常由"M="行指定,例如"M=audio 12345 RTP/AVP 0"表示音频。
媒体描述(Media Description): 描述媒体流的详细信息,包括媒体格式、端口号、传输协议等。媒体描述通常由"a=rtpmap"和"a=fmtp"等行指定。
媒体连接信息(Connection Information): 描述媒体的连接信息,包括IP地址和端口号。这对于NAT穿越和防火墙遍历非常重要。
会话带宽(Session Bandwidth): 描述会话的带宽要求,以确保适当的网络资源分配。
时间描述(Timing Description): 描述会话的时间信息,通常包括会话的开始时间和结束时间。
加密和安全性信息(Encryption and Security Information): 描述媒体流的加密和安全性设置,用于确保通信的安全性和隐私。
ICE(Interactive Connectivity Establishment)候选者(ICE Candidates): 描述网络候选者,用于建立P2P连接,包括IP地址和端口号。
传输层协议(Transport Layer Protocol): 描述用于传输媒体的协议,通常是RTP(实时传输协议)。
媒体方向(Media Direction): 描述媒体流的方向,包括发送方向、接收方向或双向。
其他定制属性(Custom Attributes): 可能包括其他自定义的SDP属性,用于特定的应用或需求。
通过offer与answer来交换,这时候需要用到信令服务器进行sdp的交换
sdp交换完成后就尝试p2p直连,首先尝试局域网,连不上就打洞进行互联网直连,还是连不上就直接走中继服务器中转数据。
代码如下:
首先搭建一个信令服务器,我们采用swoole来搭建一个websocket服务器
<?php $userlist = []; $server = new Swoole\Websocket\Server("0.0.0.0", 9502, SWOOLE_BASE, SWOOLE_SOCK_TCP | SWOOLE_SSL); $server->set([ 'ssl_cert_file' => '/data/cert/6284283_web.debug.only.bfw.wiki.pem', 'ssl_key_file' => '/data/cert/6284283_web.debug.only.bfw.wiki.key', ]); $server->on('open', function($server, $req) { $_get = $req->get; $_username = $_get['username']; global $userlist; $userlist[$_username] = $req->fd; echo "connection open: {$req->fd}{$_username}\n"; }); $server->on('message', function($server, $frame) { $data = json_decode($frame->data, true); //消息类型 $type = $data["type"]; $_ret = ["type" => $type]; //to user $toUser = $data["toUser"]; $fromUser = $data["fromUser"]; $msg = isset($data["msg"])?$data["msg"]:""; //msg $sdp = isset($data["sdp"])?$data["sdp"]:""; //sdp $iceCandidate = isset($data["iceCandidate"])?$data["iceCandidate"]:""; //ice //对方挂断 if ("hangup" == $type) { $_ret['fromUser'] = $fromUser; $_ret['msg'] = "对方挂断"; } //视频通话请求 if ("call_start" == $type) { $_ret['fromUser'] = $fromUser; $_ret['msg'] = "1"; } //视频通话请求回应 if ("call_back" == $type) { $_ret['fromUser'] = $fromUser; $_ret['msg'] = $msg; } //offer if ("offer" == $type) { $_ret['fromUser'] = $toUser; $_ret['sdp'] = $sdp; } //answer if ("answer" == $type) { $_ret['fromUser'] = $toUser; $_ret['sdp'] = $sdp; } //ice if ("_ice" == $type) { $_ret['fromUser'] = $toUser; $_ret['iceCandidate'] = $iceCandidate; } if ($toUser != "") { global $userlist; if (!isset($userlist[$toUser])) { $_ret['msg'] = "Sorry,呼叫的用户不在线!"; $_ret['type'] = "call_back"; $_ret['fromUser'] = "系统消息"; $_senddata = json_encode($_ret); $server->push($frame->fd, $_senddata); } else { foreach ($userlist as $key => $val) { if ($key == $toUser) { $_senddata = json_encode($_ret); echo "send message: {$_senddata}\n"; $server->push($val, $_senddata); } } } } // echo "received message: {$frame->data}\n"; }); $server->on('close', function($server, $fd) { echo "connection close: {$fd}\n"; }); $server->start();实现sdp及ice的信息交换
编写html代码实现p2p视频通话
<!DOCTYPE html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> <style> html,body{ margin: 0; padding: 0; } #main{ position: absolute; width: 370px; height: 550px; } #localVideo{ position: absolute; background: #757474; top: 10px; right: 10px; width: 100px; height: 150px; z-index: 2; } #remoteVideo{ position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; background: #222; } #buttons{ z-index: 3; bottom: 20px; left: 90px; position: absolute; } #toUser{ border: 1px solid #ccc; padding: 7px 0px; border-radius: 5px; padding-left: 5px; margin-bottom: 5px; } #toUser:focus{ border-color: #66afe9; outline: 0; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6); box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6) } #call{ width: 70px; height: 35px; background-color: #00BB00; border: none; margin-right: 25px; color: white; ...
点击查看剩余70%
网友评论