基于WebRTC开源框架的实时视频聊天项目,搭建私人实时通信服务
Posted 邓大帅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于WebRTC开源框架的实时视频聊天项目,搭建私人实时通信服务相关的知识,希望对你有一定的参考价值。
本项目是一个 Web 应用,使用安全且可扩展的 WebRTC 构建,提供视频和音频通信、文件共享、屏幕共享、白板和实时 P2P 和群聊消息的实时通信。WebRTC 是一个开源框架,可在 Web 和本机应用程序中实现音频、视频和数据的实时通信。 它使用户能够通过视频和音频会议、网络研讨会、播客等与他人交流。
尽管任何 WebRTC 应用程序都使用 4 种类型的服务器:
- 应用程序服务器- 托管 Connect Web 应用程序!
- 信令服务器- WebRTC 信令是指建立、控制和终止通信会话的过程。为了让两个端点开始相互交谈,必须交换三种类型的信息: 会话控制信息确定何时初始化、关闭和修改通信会话。
- NAT Traversal Server (STUN & TURN) - WebRTC 在连接同一本地网络中的浏览器时表现出色。但是,一旦您开始到达您的网络之外——例如,进入企业防火墙——您将需要更多的火力。如果不使用 STUN(用于 NAT 的会话遍历实用程序)或 TURN(使用围绕 NAT 的中继的遍历)协议,防火墙配置不会让 WebRTC 进入。这就是您需要 STUN/TURN 服务器的原因。
- 媒体服务器- 媒体服务器派上用场,因为它有助于减少客户端需要发送的流的数量,通常为一个,甚至可以减少客户端需要接收的流的数量,具体取决于媒体服务器的功能。
但是目前 Connect 默认提供免费信令服务器,因此 Application Server 和 NAT Traversal Server 两台服务器即可。
一、环境依赖
由于应用程序是使用 Laravel 7 构建的,因此它需要具备 Laravel 7 的所有先决条件。 Laravel 的依赖项之一是Composer。以下是脚本的核心依赖项:
此外,还有一些文件和文件夹需要脚本的“写”权限。
.env 文件位于根文件夹中
storage/framework 文件夹及其子文件夹
storage/logs 文件夹及其子文件夹
bootstrap/cache 文件夹及其子文件夹
resources/lang文件夹及其子文件夹
二、基本部署
以宝塔环境为例,首先宝塔面板直接安装: PM2管理器
以及对应版本的数据库、php。安装完成后重启服务器以生效:
# 1.安装宝塔
yum install -y wget && wget -O install.sh http://download.bt.cn/install/install.sh && sh install.sh
# 2.配置宝塔
(a) 安装Fileinfo扩展 # 如果Fileinfo拓展安装失败,就是内存太小,添加swap
(b) 禁用函数: proc_open、symlink、putenv、pcntl_signal、passthru
(c) 创建站点
其中值得注意的是,宝塔面板默认安装MySQL 8.0要求2核4G内存,低配服务器可以通过如下方式安装MySQL 8.0:
wget http://download.bt.cn/install/0/mysql.sh;
bash mysql.sh install 8.0
这样低内存服务器在宝塔面板安装Mysql8.0就实现了!
请注意:如果你已经安装了数据库,上面的命令会卸载删除当前数据库及数据,请提前备份,一定要提前备份!
# 3.安装Composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
# 4.编辑环境变量:修改.env文件数据库连接内容
# 5.创建数据库、创建站点、申请ssl证书、进入域名目录拉取项目
git clone https://github.com/DXJian/P2PChat.git -b master
# 6.创建上传目录软链接
php artisan storage:link
期间报错按照错误提示安装PHP拓展以及解除禁用函数即可,如:
# 7.设置storage目录权限为777
chmod -R 0777 storage
# 8.修改网站运行目录public ,取消防跨站攻击
# 9.添加网站伪静态如下:
location /
try_files $uri $uri/ /index.php$is_args$query_string;
三、线上部署
- 第一步检测环境是否合格,如若不合格按照不合格的选项整改即可。
- 第二步连接数据库
- 第三步创建管理员账户
- 第四步要求填入访问代码,随意输入即可。
项目上线后,进入设置(config)页面,(任意)填入Pusher Credential
选项中的信息。
四、建立通信
instant meeting
——start a meeting
——Live Class
之后的报错不需要理会,instant meeting
——meeting history
此时可以看到之前创建的代码为444的聊天室
五、新用户加入
新用户通过注册页面注册成功后,需要管理员激活新用户。
六、项目展示
激动人心的实时通信:
其他可以辅助参考的信息:
- codecanyon-27525559-connect-live-class-meeting-webinar-online-training-web-conference
- https://kodemintserviceshelp.freshdesk.com/support/solutions/81000097241
- https://www.youtube.com/watch?v=QY_VdHvBsSI
至此,本文也就进入尾声了。希望本文能够起到抛砖引玉之效,也欢迎大家的批评交流。
如果您有任何疑问或者好的建议,期待你的留言、评论与关注!
基于WebRtc实现安卓视频一对一聊天
WebRtc是谷歌2010年收购GlobalIPSolutions公司而获得的一项实时语音对话或视频对话的技术。之后谷歌将其开源,有很好的跨平台性。官方网址:https://webrtc.org/
最近由于公司项目需求,刚刚接触webrtc,由于国内这方面的资料少之又少,学习起来也有点困难。这一个月来对webrtc也稍微有点了解吧,特此写个博客纪念下,结合自己写的小Demo给刚入坑的新人一点建议。
基本流程
使用webrtc###
1. Maven
<dependency> <groupId>org.webrtc</groupId> <artifactId>google-webrtc</artifactId> <version>1.0.20723</version> <type>pom</type> </dependency>
注意:安卓6.0以上请自行处理CAMERA、RECORD_AUDIO、WRITE_EXTERNAL_STORAGE等危险权限。
介绍Webrtc一些关键类###
1. PeerConnectionFactory
webrtc核心类,用于创建其他关键类,稍后在做介绍。在使用PeerConnectionFactory之前,请先初始化,类似这样。
PeerConnectionFactory.initialize( PeerConnectionFactory.InitializationOptions.builder(getApplicationContext()) .setEnableVideoHwAcceleration(true) .createInitializationOptions()); PeerConnectionFactory.InitializationOptions作为PeerConnectionFactory初始化传入参数,该类采用构造模式,可以对初始化参数进行一些配置。初始化之后就可以创建PeerConnectionFactory实例了。 PeerConnectionFactory.Options options = new PeerConnectionFactory.Options(); mPeerConnectionFactory = new PeerConnectionFactory(options);
2. VideoCapturer
视频捕捉器的一个顶级接口,它的的子接口为CameraVideoCapturer,封装了安卓相机的使用方法,使用它们可以轻松的获取设备相机数据,切换摄像头,获取摄像头数量等。该对象的创建如下。
private CameraVideoCapturer createVideoCapture(Context context) { CameraEnumerator enumerator; if (Camera2Enumerator.isSupported(context)) { enumerator = new Camera2Enumerator(context); } else { enumerator = new Camera1Enumerator(true); final String[] deviceNames = enumerator.getDeviceNames(); for (String deviceName : deviceNames) { if (enumerator.isFrontFacing(deviceName)) { CameraVideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null); if (videoCapturer != null) { return videoCapturer; } } } for (String deviceName : deviceNames) { if (!enumerator.isFrontFacing(deviceName)) { CameraVideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null); if (videoCapturer != null) { return videoCapturer; } } } return null; }
3. VideoSource/VideoTrack
VideoSource为视频源,通过核心类PeerConnectionFactory创建,VideoTrack是对VideoSource的包装,可以方便的将视频源在本地进行播放,添加到MediaStream中进行网络传输。
CameraVideoCapturer mVideoCapturer = createVideoCapture(this); VideoSource videoSource = mPeerConnectionFactory.createVideoSource(mVideoCapturer); VideoTrack mVideoTrack = mPeerConnectionFactory.createVideoTrack("videtrack", videoSource);
4. AudioSource/AudioTrack
AudioSource/AudioTrack和上面的VideoSource/VideoTrack类似,从名字上面就知道是对音频的获取和处理了,AudioSource的创建很简单,直接用PeerConnectionFactory创建就可以了。
AudioSource audioSource = mPeerConnectionFactory.createAudioSource(new MediaConstraints()); AudioTrack mAudioTrack = mPeerConnectionFactory.createAudioTrack("audiotrack", audioSource);
AudioSource 创建的时候需要传入MediaConstraints这个对象的实例,其用于对媒体的一些约束限制,创建的时候可以直接使用默认的。如果你想自己定义,就需要自己填入相应的键值对了。
MediaConstraints audioConstraints = new MediaConstraints(); //回声消除 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googEchoCancellation", "true")); //自动增益 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googAutoGainControl", "true")); //高音过滤 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googHighpassFilter", "true")); //噪音处理 audioConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googNoiseSuppression", "true"));
5. MediaStream
音视频的媒体流,通过PeerConnectionFactory创建,用于PeerConnection通过网络传输发送给另一方。在媒体流传输之前,需要将前面获取的VideoTrack和AudioTrack添加进去。
MediaStream mMediaStream = mPeerConnectionFactory.createLocalMediaStream("localstream");
mMediaStream.addTrack(mVideoTrack);
mMediaStream.addTrack(mAudioTrack);
6. PeerConnection
用于p2p网络传输,双方信令的交换。webrtc是基于p2p的,因此在双方通信之前需要服务器帮助传递信令,并且需要添加STUN和TURN服务器网络穿透。在双方通道打开之后就可以将媒体流发送给另一方了。下面是PeerConnection的创建,并将媒体流添加到其中用于网络传输。
PeerConnection peerConnection = mPeerConnectionFactory.createPeerConnection(iceServers, pcConstraints, this); peerConnection.addStream(mMediaStream);
参数说明如下:
iceServers连接到外网和网络穿用到的,添加STUN和TURN服务器可以帮助你连接。
constraints是一个MediaConstrains的实例。应该包含offerToRecieveAudio和offerToRecieveVideo。
observer是一个PeerConnectionObserver的实例,对PeerConnection的一些连接状态的监听。
信令交换###
在实现媒体流的网络传输之前,需要交换双方信令,将连接通道打开,下面介绍一下webrtc的信令交换机制。
A向B发起建立连接的请求,通过PeerConnection的createOffer()方法创建一个offer信令,创建成功后调用SdpObserver监听中的onCreateSuccess()回调函数,调用PeerConnection的setLocalDescription方法设置自己的offer信令,同时将offer信令通过服务器转发给B。
peerConnection.createOffer(sdpObserver, sdpMediaConstraints); //SdpObserver @Override public void onCreateSuccess(SessionDescription sessionDescription) { peerConnection.setLocalDescription(this, sessionDescription); JSONObject jsonObject = new JSONObject(); try { jsonObject.put("type", sessionDescription.type.canonicalForm()); jsonObject.put("description", sessionDescription.description); } catch (JSONException e) { e.printStackTrace(); } mSocket.emit("SdpInfo", jsonObject.toString()); }
B收到A的offer信令后,创建一个SessionDescription(SDP描述符包含媒体信息,如分辨率、编解码能力等)对象将A的offer信令解析出来,并调用PeerConnection的setRemoteDescription方法设置A的SDP描述符,然后B通过PeerConnection的createAnswer()方法创建一个answer信令,创建成功后调用SdpObserver监听中的onCreateSuccess()回调函数,调用PeerConnection的setLocalDescription方法设置自己的answer信令,同时将answer信令通过服务器转发给A。
@Override public void call(Object... args) { if (mPeer == null) { mPeer = new Peer(); } try { JSONObject jsonObject = new JSONObject(args[0].toString()); SessionDescription description = new SessionDescription (SessionDescription.Type.fromCanonicalForm(jsonObject.getString("type")), jsonObject.getString("description")); mPeer.peerConnection.setRemoteDescription(mPeer, description); if (!isOffer) { mPeer.peerConnection.createAnswer(mPeer, sdpConstraints); } } catch (JSONException e) { e.printStackTrace(); } }
A收到B的answer信令后,解析B的answer信令再调用PeerConnection的setRemoteDescription方法设置B的SDP描述符。这样双方的信令交换就算完成了。
在非局域网下,信令的交换还需要借助于STUN和TURN服务器网络穿透,创建PeerConnection的时候需要传入iceServers这个参数,这里面存放的就是穿透地址变换的服务器地址了,类似的,Ice穿透也需要信令的交换,过程大致如下。
当A和B创建好配置了iceServers的PeerConnection实例后,当网络候可用时,回调PeerConnection.Observer的onIceCandidate()函数,在回调函数里面将IceCandidate对象发送给对方。
在收到对方的IceCandidate信令后,解析出来并用PeerConnection的addIceCandidate()方法设置对方的信令。
@Override public void onIceCandidate(IceCandidate iceCandidate) { try { JSONObject jsonObject = new JSONObject(); jsonObject.put("label", iceCandidate.sdpMLineIndex); jsonObject.put("id", iceCandidate.sdpMid); jsonObject.put("candidate", iceCandidate.sdp); mSocket.emit("IceInfo", jsonObject.toString()); } catch (JSONException e) { e.printStackTrace(); } } @Override public void call(Object... args) { try { JSONObject jsonObject = new JSONObject(args[0].toString()); IceCandidate candidate = null; candidate = new IceCandidate( jsonObject.getString("id"), jsonObject.getInt("label"), jsonObject.getString("candidate") ); mPeer.peerConnection.addIceCandidate(candidate); } catch (JSONException e) { e.printStackTrace(); } }
现在,双方的连接通道就完全打开了,PeerConnection.Observer就会调用onAddStream()响应函数,里面包含对方的媒体流Mediastream,将媒体流播放就可以了。
@Override public void onAddStream(MediaStream mediaStream) { remoteVideoTrack = mediaStream.videoTracks.get(0); remoteVideoTrack.addRenderer(new VideoRenderer(remoteView)); }
播放媒体流###
媒体流的播放需要用到webrtc封装的控件SurfaceViewRenderer,它继承于安卓的SurfaceView。
在播放之前,需要对该控件初始化和配置一些属性。
localView = findViewById(R.id.localVideoView); //创建EglBase对象 mEglBase = EglBase.create(); //初始化localView localView.init(mEglBase.getEglBaseContext(), null); localView.setKeepScreenOn(true); localView.setMirror(true); localView.setZOrderMediaOverlay(true); localView.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT); localView.setEnableHardwareScaler(false);
注意:SurfaceViewRenderer的初始化需要在主线程
初始化完成后,将localView包装成VideoRenderer对象并添加到VideoTrack中就可以进行播放了。
mVideoTrack.addRenderer(new VideoRenderer(localView));
Demo###
demo里面包含了用IoSocket简单写的java服务器(webrtc文件夹),里面的地址改成自己电脑的本机ip4地址即可测试。
demo地址:demo传送门
附上demo运行效果图
原文链接:https://blog.csdn.net/qq_35054800/article/details/78647545
以上是关于基于WebRTC开源框架的实时视频聊天项目,搭建私人实时通信服务的主要内容,如果未能解决你的问题,请参考以下文章
实时音视频互动系列(下):基于 WebRTC 技术的实战解析