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%
网友评论