写点什么

Android 技术分享| 实现视频连麦直播

发布于: 2021 年 08 月 03 日

视频连麦产品端核心步骤分析

  • 游客申请连麦/取消申请

  • 主播同意/拒绝申请

  • 音视频发布取消

  • 支持很多观众观看

  • 支持多人连麦

  • 低延时

  • IM 弹幕

视频连麦技术端调研

emmm,大致可以分为视频采集、编码,传输,解码,渲染 %¥#@¥%…………%……¥……%¥%……¥%%……%#¥%#%¥&%&……%……&%……¥?卒



所以经过调研,发现市场上已经有很多成熟的商业解决方案,并且成本很低就可以接入使用。


对比了很久,最后采用 anyRTC 公司的两个 SDK 来完成视频连麦中的音视频通许和信令传输。


信令交互


首先利用 RTM SDK,主播和游客端都分别加入同一个频道,这样就能实现频道内的成员心令交互。实现申请连麦/取消申请连麦的话,只需要和主播端约定好信令格式即可,代码如下。

游客

//申请连麦fun applyLine() {        RtmManager.instance.sendPeerMessage(hostId,            "{\"cmd\": \"apply\", \"avatar\": \"$userAvatar\", \"userName\": \"$userNickname\"}"        )    }    //取消申请连麦fun cancelApply() {        RtmManager.instance.sendPeerMessage( hostId,"{\"cmd\": \"cancelApply\"}"        )    }
//收到信令回调通知override fun onP2PMessageReceived(var1: RtmMessage?, var2: String?) { val params = JSONObject(var1.text) when (params.get("cmd")) { "acceptLine" -> { //主播同意 } "rejectLine" -> { //主播拒绝 } } }
复制代码

主播

//拒绝游客连麦fun rejectLine(uid: String) {        RtmManager.instance.sendPeerMessage(uid, "{\"cmd\": \"rejectLine\"}"        )    }
//同意主播连麦fun acceptLine(uid: String) { RtmManager.instance.sendPeerMessage(uid, "{\"cmd\": \"acceptLine\"}" ) } override fun onP2PMessageReceived(var1: RtmMessage?, var2: String?) { val params = JSONObject(var1.text) when (params.get("cmd")) { "apply" -> { //收到游客申请连麦 } "cancelApply" -> { //游客取消申请连麦 } } }
复制代码


以上,就完成了最简单的信令交互,实际业务场景中,会有更多更复杂的,只需商定好,通过 RTM 发送交互就行。

音视频推流


游客只观看主播的时候,是不需要发布音视频的,所以在加入房间后,将自己的身份设置为游客(CLIENT_ROLE_AUDIENCE)即可。申请连麦并且主播同意后,再将身份设置为(CLIENT_ROLE_BROADCASTER)就会自动发布音视频。这样就能与直播互动了。


anyRTC 音视频 SDK 有 2 种直播模式,分别如下:

1.RTC

RTC(Real Time Communication)实时音视频通信,最大的特点就是延迟极低,基本都是基于 WebRTC 标准,使用私有协议进行推流的。

主播

进入视频页面,打开自己的视频并加入房间。


//初始化 SDK 引擎RtcManager.instance.initRtc(ctx)//打开视频模块RtcManager.instance.enableVideo()//打开本地摄像头设置视图显示RtcManager.instance.setupLocalVideo(VideoCanvas(textureView))//加入房间RtcManager.instance.joinChannel(rtcToken, roomId, userId, isHost)
复制代码


加入房间成功之后,如果有人申请连麦并上麦后,会收到 onUserJoin 回调,只需要在合适的回调中显示移除上麦人的视图即可。


//在这显示上麦的人的视频override fun onUserJoined(uid: String?, elapsed: Int) {          // add remote user}
//移除他人视频override fun onUserOffline(uid: String?, reason: Int) { //remove remote user }
复制代码

游客

主播同意上麦申请后,应将自己的身份设置为 CLIENT_ROLE_BROADCASTER,并将自己的视频模块打开并添加到视图中。


//转换身份RtcManager.instance.setClientRole(Constants.CLIENT_ROLE_BROADCASTER)
//添加自己的视频val clientTexture = RtcEngine.CreateRendererView(this) addVideoView( binding.rlHostView, clientTexture, yourself = true, setupLocalVideo = true ) binding.apply.text = "下麦"
复制代码


使用 RTC 模式实现非常的简单,只需要关注几个重要的回调即可。

2.RTMP+CDN

RTMP (Real Time Messaging Protocol)是基于 TCP 的流媒体传输协议,最大的特点是与 CDN 的强绑定,需要借助 CDN 的负载均衡系统将内容推送到接近用户的边缘节点,使用户就近取得所需内容,提高用户访问的响应速度和成功率,解决因分布、带宽、服务器性能带来的访问延迟问题。更多适用于站点加速、点播、短视频等场景。


使用该模式比 RTC 模式代码要写的多一点,因为主播短要设置上麦人的视频合流参数,观众需要添加一个 anyRTC 内置的播放器用来拉 rtmp 流。


rtmp 会比 RTC 延时要高一些,但是连麦不会,因为连麦后还是走的 RTC 模式,因此,连麦的人和主播之间的延时会很小。其他观众拉流的话,并不会察觉到主播和上麦者之间有什么延迟。

主播推流到 CDN

//加入频道成功override fun joinChannelSuccess() {  //设置合流参数  publishPushLiveTranscoding()  //添加推流地址  RtcManager.instance.addPublishStreamUrl(cdnUrl, true)}
private fun publishPushLiveTranscoding( transcodingArr: List<LiveTranscoding.TranscodingUser>, canvasInfo: CDNStreamLayoutInfo ) { rtcEngine?.setLiveTranscoding(LiveTranscoding().apply { width = canvasInfo.width height = canvasInfo.height }.apply { transcodingArr.forEach { addUser(it) } }) } //游客上麦override fun onUserJoin(uid: String) { //更新合流布局 updatePushLiveTranscoding()}
//游客下麦override fun onUserOffline(uid: String) { //更新合流布局 updatePushLiveTranscoding()}
复制代码


这里需要注意的是合流布局参数的设置,具体可以查看文末 github 仓库代码。

游客拉流播放

//创建播放器并播放主播的流 RtcManager.instance.initMediaPlayer().apply {            open(cdnUrl, 0)            setView(textureView)            play()        }
复制代码


游客上下麦还是和上麦的流程一致,变的只是界面上的效果。具体可以参考 Demo

效果图展示

Demo 代码地址

发布于: 2021 年 08 月 03 日阅读数: 8
用户头像

实时交互,万物互联! 2020.08.10 加入

实时交互,万物互联,全球实时互动云服务商领跑者!

评论

发布
暂无评论
Android技术分享| 实现视频连麦直播