SRS流媒体服务器——SRS4.0 WebRTC一对一通话环境搭建与逻辑分析

目录

  1. 环境搭建

  2. SRS4.0 WebRTC1对1通话逻辑分析

环境搭建

1. 安装go语⾔环境

  1. 在Go语⾔官⽹找到对应的安装包(Downloads - The Go Programming Language
  2. 下载和解析(使用的是阿里云的Ubuntu系统):
cd /usr/local/
wget https://dl.google.com/go/go1.16.5.linux-amd64.tar.gz --no-check-certificate
tar -C /usr/local -xzf go1.16.5.linux-amd64.tar.gz

3.需要配置 GOROOT 和 PATH环境变量,在/etc/profile中配置。

vim /etc/profile

# 将环境变量添加到/etc/profile⽂件末尾。
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin:$GOBIN

4.然后使用 source /etc/profile 命令使配置文件生效,就可以在任意⽬录使用Go语言命令。

source /etc/profile 

5.执行go version可以查看安装go是否成功。

2. 编译和启动srs

git clone -b v4.0.123 https://gitee.com/winlinvip/srs.oschina.git
srs.4.0.123
cd srs.4.0.123/trunk
./configure
make
./objs/srs -c conf/rtc.conf

3. 编译和启动信令服务器

  1. 进行srs/trunk目录下。
cd 3rdparty/signaling
make
./objs/signaling

在这里插入图片描述 注意:云服务器需要先开通1989端口。

CSDN站内私信我,领取最新最全C++音视频学习提升资料,内容包括(C/C++Linux 服务器开发,FFmpeg webRTC rtmp hls rtsp ffplay srs

4. 编译和启动web服务器

  1. 需要server.crt和server.key,如果没有则⽤openssl⽣成。
  2. 进入srs/trunk/3rdparty/httpx-static目录,执行:
# ⽣成 server.key
openssl genrsa -out server.key 2048

# ⽣成 server.crt
openssl req -new -x509 -key server.key -out server.crt -days 3650

 3.编译和启动web服务器

cd 3rdparty/httpx-static
make
./objs/httpx-static -http 80 -https 443 -ssk server.key -ssc server.crt \
-proxy http://127.0.0.1:1989/sig -proxy http://127.0.0.1:1985/rtc \
-proxy http://127.0.0.1:8080/

 

5. 进入测试页面

  1. 打开demo地址:
https://localhost/demos/
https://192.xxx.3.6/demos/  #公网ip

 

2.输入Room和Display就可以进行1对1通话。
 

3. SRS4.0 WebRTC1对1通话逻辑分析
按f12打开一对一通话http页面源码,在 one2one.html?autostart=true&room=fbe219e 中可以看到,“开始通话”按钮id是btn_start,当点击按钮后,执行startDemo函数。
startDemo函数如下:

        var startDemo = async function () {
            var host = $('#txt_host').val(); //获取ip或者域名,房间id,参与者名字
            var room = $('#txt_room').val();
            var display = $('#txt_display').val();

            // Connect to signaling first. //关闭先前的websock连接
            if (sig) {
                sig.close(); //见srs.sig.js close部分
            }
            sig = new SrsRtcSignalingAsync(); //创建SrsRtcSignalingAsync,RTC信令
            sig.onmessage = function (msg) { //onmessage订阅新的信令消息
                console.log('Notify: ', msg);

                if (msg.event === 'leave') {
                    $('#player').hide();
                }

                if (msg.event === 'publish') { //房间已经存在的参与者,收到publish信令后再去订阅新加入者
                    if (msg.peer && msg.peer.publishing && msg.peer.display !== display) {
                        startPlay(host, room, msg.peer.display);
                    }
                }

                if (msg.event === 'control') {
                    if (msg.param === 'refresh') {
                        setTimeout(function () {
                            window.location.reload();
                        }, 500);
                    } else if (msg.param === 'alert') {
                        alert('From ' + msg.peer.display + ': ' + msg.data);
                    }
                }

                if (msg.participants.length >= 2) {
                    $('.srs_merge').show();
                } else {
                    $('.srs_merge').hide();
                }
            };
            await sig.connect(conf.wsSchema, conf.wsHost, room, display); //连接websock,见下面SrsRtcSignalingAsync代码

            control_refresh_peer = async function () {
                let r1 = await sig.send({action:'control', room:room, display:display, call:'refresh'});
                console.log('Signaling: control peer to refresh ok', r1);
            };
            control_alert_peer = async function () {
                let r1 = await sig.send({action:'control', room:room, display:display, call:'alert', data:$('#txt_alert').val()});
                console.log('Signaling: control peer to alert ok', r1);
            };

            let r0 = await sig.send({action:'join', room:room, display:display}); //向信令服务器发送join信令,会返回房间列表,包括当前房间id,房间人数和每个display的名字和是否推流,见下图。
            console.log('Signaling: join ok', r0);

            // For one to one demo, alert and ignore when room is full. 判断房间人数是否超过2个,因为是1v1场景
            if (r0.participants.length > 2) {
                alert('Room is full, already ' + (r0.participants.length - 1) + ' participants');
                sig.close();
                return;
            }

            // Start publish media if signaling is ok.
            await startPublish(host, room, display); //向srs流媒体服务器开始推流,代码见下面
            let r1 = await sig.send({action:'publish', room:room, display:display}); //向信令服务器发送publish信令
            console.log('Signaling: publish ok', r1);

            // Play the stream already in room. 对于新建的房间,会拉取房间内另一个人的流
            r0.participants.forEach(function(participant) {
                if (participant.display === display || !participant.publishing) return;
                startPlay(host, room, participant.display); //向srs流媒体拉房间内另一个人的流
            });

            if (r0.participants.length >= 2) {
                $('.srs_merge').show();
            }
        };

2.SrsRtcSignalingAsync代码:

// Async-await-promise based SRS RTC Signaling.
function SrsRtcSignalingAsync() {
    var self = {};

    // The schema is ws or wss, host is ip or ip:port, display is nickname
    // of user to join the room.
    self.connect = async function (schema, host, room, display) {
        var url = schema + '://' + host + '/sig/v1/rtc'; //如:wss://8.xxx.75.248/sig/v1/rtc
        self.ws = new WebSocket(url + '?room=' + room + '&display=' + display); //建立websock连接,地址为:wss://8.xxx.75.248/sig/v1/rtc?room=123&display=zhangsan

        self.ws.onmessage = function(event) {
            var r = JSON.parse(event.data);
            var promise = self._internals.msgs[r.tid];
            if (promise) {
                promise.resolve(r.msg);
                delete self._internals.msgs[r.tid];
            } else {
                self.onmessage(r.msg);
            }
        };

        return new Promise(function (resolve, reject) {
            self.ws.onopen = function (event) {
                resolve(event);
            };

            self.ws.onerror = function (event) {
                reject(event);
            };
        });
    };

    // The message is a json object.
    self.send = async function (message) {
        return new Promise(function (resolve, reject) {
            var r = {tid: Number(parseInt(new Date().getTime()*Math.random()*100)).toString(16).substr(0, 7), msg: message};
            self._internals.msgs[r.tid] = {resolve: resolve, reject: reject};
            self.ws.send(JSON.stringify(r));
        });
    };

    self.close = function () {
        self.ws && self.ws.close();
        self.ws = null;

        for (const tid in self._internals.msgs) {
            var promise = self._internals.msgs[tid];
            promise.reject('close');
        }
    };

    // The callback when got messages from signaling server.
    self.onmessage = function (msg) {
    };

    self._internals = {
        // Key is tid, value is object {resolve, reject, response}.
        msgs: {}
    };

    return self;
}

3.join信息返回信息。
 

4.startPublish和startPlay代码。

       var startPublish = function (host, room, display) {
            $(".ff_first").each(function(i,e) {
                $(e).text(display);
            });

            var url = 'webrtc://' + host + '/' + room + '/' + display + conf.query; //如: webrtc://8.xxx.75.248/123/wangwu
            $('#rtc_media_publisher').show();
            $('#publisher').show();

            if (publisher) {
                publisher.close();
            }
            publisher = new SrsRtcPublisherAsync(); //创建RTC异步推流
            $('#rtc_media_publisher').prop('srcObject', publisher.stream);

            return publisher.publish(url).then(function(session){
                $('#self').text('Self: ' + url);
            }).catch(function (reason) {
                publisher.close();
                $('#rtc_media_publisher').hide();
                console.error(reason);
            });
        };

        var startPlay = function (host, room, display) {
            $(".ff_second").each(function(i,e) {
                $(e).text(display);
            });

            var url = 'webrtc://' + host + '/' + room + '/' + display + conf.query; //
            $('#rtc_media_player').show();
            $('#player').show();

            if (player) {
                player.close();
            }

            player = new SrsRtcPlayerAsync();
            $('#rtc_media_player').prop('srcObject', player.stream);

            player.play(url).then(function(session){
                $('#peer').text('Peer: ' + display);
                $('#rtc_media_player').prop('muted', false);
            }).catch(function (reason) {
                player.close();
                $('#rtc_media_player').hide();
                console.error(reason);
            });
        };

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/124691647