基于WebRTC搭建直播系统源码

直播系统源码可以说是近年来最火的互联网项目,各大直播系统源码如雨后春笋般先后兴起,转眼间主播这一行业也成为最赚钱的代名词。那我们就来从0开始搭建一个直播系统源码吧。

WebRTC
WebRTC,名称源自网页实时通信(Web Real-Time Communication)。是一个支持网页浏览器进行实时语音对话或视频对话的技术,谷歌于2010年收购获得。2011年5月开放了工程的源代码,成为下一代视频通话的标准。

优点
WebRTC作为一个面向网页浏览器的实时语音视频技术,主要有以下几个优点:

具有良好的通用性,几乎在任何平台都可以正常使用。
其使用的Interactive Connectivity Establishment(ICE)能让各个设备之间自动匹配当前最好的通讯方式,这是很多别的技术都不具备的。
具备全双工的能力,即双向通讯(P2P),不仅可作为单向直播使用还能完成电子视频会议的双向音视频对话。
为Google旗下,具有良好的发展前景,最重要的:开源。

开始使用
导包
这里没有直接使用官方的原生库进行编译,因为太麻烦了,网上已经有组织提供了编译好的版本可以供我们直接使用,对库的提供者不是很了解,不知道是属于什么性质的,但是几乎市面上所有的Android端都是采用该库所以应该没有什么问题。

implementation 'io.pristine:libjingle:11139@aar'

快速开始
以下步骤都是经过分类和优化后整理出来的,加上注释,大多都能读懂,因此就不详细解释了。如有不清楚的地方可以留言问我。

初始化,Peer连接工厂类:

//初始化 关键
PeerConnectionFactory.initializeAndroidGlobals(context, true, true, true)
factory = PeerConnectionFactory()

获得Media,简单理解就是需要传输的音视频流:

//获取视频源
val videoCapture = VideoCapturerAndroid.create(CameraEnumerationAndroid.getNameOfBackFacingDevice())
val videoSource = factory.createVideoSource(videoCapture, MediaConstraints())
//获取音频源
val audioSource = factory.createAudioSource(MediaConstraints())
//获取封装MediaTrack
val videoTrack = factory.createVideoTrack("ARDAMSv0", videoSource)
val audioTrack = factory.createAudioTrack("ARDAMSa0", audioSource)
//封装媒体流
localMs = factory.createLocalMediaStream("ARDAMS")
localMs?.addTrack(videoTrack)
localMs?.addTrack(audioTrack)
//预览
preview?.invoke(localMs!!)

配置ICE,进行网络连接:

//Ice NAT穿透
val iceList = ArrayList<PeerConnection.IceServer>()
iceList.add(PeerConnection.IceServer("stun:23.21.150.121"))
iceList.add(PeerConnection.IceServer("stun:stun.l.google.com:19302"))
//媒体限制
val constraints = MediaConstraints()
constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"))
constraints.mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"))
constraints.optional.add(MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"))
pc = factory.createPeerConnection(iceList, constraints, Observer())
pc?.addStream(localMs)

这里使用的是stun方式,ICE逻辑判断逻辑很复杂,主要分为两种方式:STUN、TURN。

STUN是将本地地址转换成外部可访问的公网地址,说白了有点像内网穿透的意思。

TURN则是需要自己搭建,由公共的中介服务器分配地址。

创建Offer:

pc?.createOffer(Observer(), MediaConstraints())

WebRTC模型中Peer之间需要进行信令交换,而承载信令的载体就是Offer/Answer,这里因为是实现的直播系统源码推流端,因此创建的是Offer,如果是观看端则需要创建Answer。

信令交换:

private inner class Observer : SdpObserver, PeerConnection.Observer {
//创建offer成功
  override fun onCreateSuccess(p0: SessionDescription?) {
    log("offer:${p0?.description}")
    pc?.setLocalDescription(Observer(), p0)
    val jsonObject = JSONObject()
    jsonObject.put("id", "presenter")
    jsonObject.put("sdpOffer", p0?.description)
    SocketUtils.sendMsg(jsonObject.toString())
    log("json:$jsonObject")
  }

//创建offer失败
  override fun onCreateFailure(p0: String?) {
    log("error: create offer $p0")
  }

//当网络可用即Ice穿透成功
  override fun onIceCandidate(p0: IceCandidate?) {
    val jsonObject = JSONObject()
    jsonObject.put("id", "onIceCandidate")
    val ice = JSONObject()
    ice.put("sdpMid", p0?.sdpMid)
    ice.put("sdpMLineIndex", p0?.sdpMLineIndex)
    ice.put("usernameFragment", p0?.sdp?.substringAfter("ufrag ")?.substring(0, 4))
    ice.put("candidate", p0?.sdp)
    jsonObject.put("candidate", ice)
    SocketUtils.sendMsg(jsonObject.toString())
    log("iceCandidate:$p0")
    log("json:$jsonObject")
  }
}

通过Socket获得:

  private fun setRemoteSdp(sdp: String) {
      val answer = SessionDescription(SessionDescription.Type.ANSWER, sdp)
      pc?.setRemoteDescription(Observer(), answer)
  }

  private fun setRemoteIce(ice: EventIceCandidate) {
      ice.candidate?.let {
          pc?.addIceCandidate(IceCandidate(
                  it.sdpMid,
                  it.sdpMLineIndex,
                  it.candidate
          ))
      }
  }

显示画面

 gl_view.preserveEGLContextOnPause = true
  gl_view.keepScreenOn = true
  VideoRendererGui.setView(gl_view) {
      RtcClient(this).preview = { localMs ->
          // local and remote render
          val localRender = VideoRendererGui.createGui(
                  LOCAL_X_CONNECTED, LOCAL_Y_CONNECTED,
                  LOCAL_WIDTH_CONNECTED, LOCAL_HEIGHT_CONNECTED,
                  RendererCommon.ScalingType.SCALE_ASPECT_FILL,
                  false)
          localMs.videoTracks[0].addRenderer(localRender)
      }
  }

主要流程
直播端
初始化,Peer连接工厂类。
获取Media,创建GL渲染器,进入显示就绪状态。
配置ICE并监听,当Candidate收集完成发送给远程端。
创建Offer,当Offer创建完成发送给远程端。
接收远程端发送的ICE信息,并设置给PeerConnection对象。
接收远程端返回的Answer,并设置给PeerConnection对象。
建立连接,开始直播。

观看端
初始化,Peer连接工厂类。
获取Media,创建GL渲染器,进入显示就绪状态。
配置ICE并监听,当Candidate收集完成发送给远程端。
接收远程端发送的ICE信息,并设置给PeerConnection对象。
接收远程端发送的Offer,并设置给PeerConnection对象。
创建Answer,当Answer创建完成发送给远程端。
建立连接,开始直播。

以上就是基于WebRTC搭建直播系统源码的全部内容了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
概述: iShow是一套基于P2P技术的在线视频直播系统,iShow依存于web网页,无需下载插件,可实现低延时高清的视频语音直播体验。现已广泛应用于教育、娱乐、客服等各个行业,随着国内带宽的提升和各类新技术的加入,视频直播技术已经逐渐成为下一代互联网的主流,多媒体在线直播体验势必将会涵盖各类终端,成为全民参与的新一代互联网主旋律。 随着国家网络带宽的升级,民用宽带的价格逐渐降低以及微博等即时交流的网络媒体的兴盛,视频多媒体将将成为下一代网络的主流力量,iShow作为国内第一个也是唯一一个使用点对点视频技术开发的网站应用,正在引领一股新的流媒体平民化浪潮。 功能列表: 1、即时视频语音直播 2、视频状态检测 3、局域网内的P2P直播,不消耗任何外网带宽 4、可设置的视频清晰度和缓冲时间 5、无延时的即时文字和表情传输 6、礼物/消费/主播结算/房间类型等功能 7、播放录像功能 iShow的技术优势: 1、直播低延时、文本数据即时传输 2、多媒体直播不耗费任何服务器资源,对服务器无负载 3、带宽占用低 4、视频高清,采用高清编码,影响更清晰,传输更流畅 5、无需架设额外的视频流媒体服务器,节省60%~90%的运营开支 6、可扩展,可跨平台同步直播 7、兼容任何开发语言,简单几步可与任何网站进行对接整合 8、智能识别用户的在线状态 9、可脱离动态程序和数据库独立运行,如:无需任何架设,即可直接集成到任何网站,进行直播或文字沟通 目前同行业唯一一款成熟产品,处于行业绝对领跑者

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值