安卓webrtc在P2P场景下实现屏幕+系统声音共享 背景

背景

用webrtc实现P2P的屏幕+声音共享,不使用云端信令服务器,分享屏幕的同时,推送当前系统播放的声音,实现类似云渲染的效果。

分析

  1. 信令
  • 信令服务是必须存在的,否则无法在设备间交换WEBRTC的SDP和ICE Candidate以及业务的通话指令,在局域网,可以在其中一个设备上,把自己当成信令服务器,让其它端通过IP地址或者扫码连接的方式,连接上这个信令服务器,建立socket或者websocket连接。
  • 在github可以找到现成的,局域网内直接能用的扫码连接P2P通话的工程:github.com/meshenger-a…
  1. 编码
  • 低端手机上,性能不够,所以需要选择合适的硬编码器,提升编码效率,最新版本的官方SDK已经支持H265硬编码了,所以在编码器的优先级设置上,把H265设置为优先选项,具体逻辑参考工程内的:
    HardwareExtendedVideoEncoderFactory.kt
  1. 延迟
  • webrtc内部使用jitter做抖动缓冲,但是也间接的导致了延迟的增加,在部分场景下,宁愿牺牲流畅性,换来更低的延时,之前测试过在webrtc的m115版本中,可以通过字段设置,减少延迟,实测收益能达到30ms以上
1
2
3
4
5
6
kotlin复制代码strFieldTrails += "WebRTC-ForcePlayoutDelay/min_ms:0,max_ms:50/"

PeerConnectionFactory.InitializationOptions.builder(callActivity!!.getContext())
.setEnableInternalTracer(true)
.setFieldTrials(strFieldTrails)
.createInitializationOptions()

这里需要注意的是,之前在iOS上设置这个字段,实际效果远不如Android,主要有几个方面

  • 延迟并没有明显降低 — 可以通过修改C++层代码解决,实测能达到和Android接近的效果
  • 导致开画速度很慢 — 可以通过修改C++层代码解决,实测能达到和Android接近的效果
  • 导致渲染掉帧(objc层的渲染是保留最后一帧,但是渲染的触发是按刷新率来的,例如33ms渲染一次,减少延迟导致这33ms期间有多帧已经准备好了,但是没有渲染的机会) — 可以通过修改objc层代码解决,实测能达到和Android接近的效果
  1. 系统声音
  • 直接用webrtc的API,就能很方便的创建本地音频
1
rust复制代码MediaConstraints->AudioSource->AudioTrack->RtpSender

但是这样创建的本地音轨,使用的是设备的麦克风,在通话场景中是合适的,但是在类似云渲染的场景下,要同时把屏幕和设备内部的播放声音一起推流出来,就需要做定制(不修改官方的SDK源码),在业务层,通过ForegroundService + mediaProjection + AudioRecord 录制系统内部音频。我们不生产代码,我们只是代码的搬运工,前面所说的录制系统声音部分,直接从github.com/ant-media/W… 这个代码仓库搬运过来即可。核心代码参考工程内的:
WebRtcAudioRecord.java

其它

  1. 原工程使用的是摄像头呼叫的效果,把新代码中的isScreencast改成false就能回滚到原工程效果,使用摄像头呼叫通话
  2. demo直接运行起来,就能进行点对点的屏幕+声音分享,代码仓库:github.com/baihua666/m…

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%