php swoole实现webrtc支持内网外网p2p视频通话的html代码

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直连,首先尝试局域网,连不上就打洞进行互联网直连,还是连不上就直接走中继服务器中转数据。

800_auto

代码如下:

首先搭建一个信令服务器,我们采用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%

{{collectdata}}

网友评论