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端口。

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,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);
            });
        };

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,编解码,推拉流,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓ 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
百万级高并发WebRTC流媒体服务器设计与开发是一门涉及到视频通信、网络协议和Web开发的高级课程。该课程的目标是培养学生对大规模高并发视频流媒体服务器的设计和开发能力。 在这门课程中,学生将学习如何设计和构建一个支持数百万并发连接的流媒体服务器。课程将涵盖以下内容: 1. WebRTC基础知识:学生将学习WebRTC协议的基本原理和工作方式,了解传输控制协议(TCP)与用户数据报协议(UDP)之间的差异,以及实时通信协议(RTC)。 2. 服务器架构设计:学生将学习如何设计一种高可扩展性的架构,以处理大量并发连接和视频流的传输。他们将学习使用分布式系统和负载均衡来优化服务器的性能和可用性。 3. 流媒体编解码技术:学生将学习不同的视频编解码算法,并了解实时流媒体传输的特点和挑战。他们将学习如何处理音频和视频数据的编码和解码,并了解相关的压缩和解压缩技术。 4. 网络安全和数据隐私:学生将研究网络安全和数据隐私方面的问题,并学习如何在流媒体服务器中实施安全措施,保护用户的数据和隐私。 5. 实际项目开发:学生将参与实际的项目开发,设计并实现一个具有百万级高并发连接的WebRTC流媒体服务器。他们将学习如何在服务器上进行性能优化,并解决实时视频传输中遇到的各种问题。 这门课程将提供相关的教材、参考书籍和在线资源。学生将通过实际编程练习和团队项目来提高他们的实践能力,并通过课堂讨论和评估来加深对课程内容的理解。 以上是对百万级高并发WebRTC流媒体服务器设计与开发课程资源的简要回答,该课程将为学生提供深入了解WebRTC流媒体服务器的机会,并为他们在相关领域的职业发展打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值