一尘不染

如何使用适用于Android的WebRTC本机代码实现三方电话会议视频聊天?

java

我正在尝试使用适用于AndroidWebRTC本机代码包(即不使用WebView)在Android应用程序中实现三向视频聊天。我已经使用node.js编写了一个信令服务器,并使用了客户端应用程序内的Gottox socket.io
java客户端
库来连接到服务器,交换SDP数据包并建立2路视频聊天连接。

但是,现在我遇到了无法进行三通通话的问题。WebRTC本机代码包随附的AppRTCDemo应用程序仅演示双向呼叫(如果第三方尝试加入会议室,则会返回“
room full”消息)。

根据这个答案(与Android无关),我应该通过创建多个PeerConnections来做到这一点,因此每个聊天参与者都将连接到其他2个参与者。

但是,当我创建多个PeerConnectionClient(包装PeerConection的Java类,该类在libjingle_peerconnection_so.so的本机端实现)时,库内部会引发异常,这是因为它们都试图冲突存取相机:

E/VideoCapturerAndroid(21170): startCapture failed
E/VideoCapturerAndroid(21170): java.lang.RuntimeException: Fail to connect to camera service
E/VideoCapturerAndroid(21170):  at android.hardware.Camera.native_setup(Native Method)
E/VideoCapturerAndroid(21170):  at android.hardware.Camera.<init>(Camera.java:548)
E/VideoCapturerAndroid(21170):  at android.hardware.Camera.open(Camera.java:389)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid.startCaptureOnCameraThread(VideoCapturerAndroid.java:528)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid.access$11(VideoCapturerAndroid.java:520)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid$6.run(VideoCapturerAndroid.java:514)
E/VideoCapturerAndroid(21170):  at android.os.Handler.handleCallback(Handler.java:733)
E/VideoCapturerAndroid(21170):  at android.os.Handler.dispatchMessage(Handler.java:95)
E/VideoCapturerAndroid(21170):  at android.os.Looper.loop(Looper.java:136)
E/VideoCapturerAndroid(21170):  at org.webrtc.VideoCapturerAndroid$CameraThread.run(VideoCapturerAndroid.java:484)

即使在尝试建立连接之前初始化本地客户端时,也会发生这种情况,因此它与node.js,socket.io或任何信令服务器无关。

如何获得多个PeerConnections共享摄像机,以便可以将同一视频发送给多个同伴?

我曾经有一个想法是实现某种单例相机类来代替可以在多个连接之间共享的VideoCapturerAndroid,但是我什至不确定那是否可行,我想知道是否有一种方法可以做到3-在开始在库中进行黑客入侵之前,请使用API​​进行方式调用。

有可能吗?

更新:

我尝试在多个PeerConnectionClients之间共享一个VideoCapturerAndroid对象,仅为第一个连接创建该对象,然后将其传递给后续连接的初始化函数,但这导致此“捕捉器只能被使用一次!”
从VideoCapturer对象为第二个对等连接创建第二个VideoTrack时出现异常:

E/AndroidRuntime(18956): FATAL EXCEPTION: Thread-1397
E/AndroidRuntime(18956): java.lang.RuntimeException: Capturer can only be taken once!
E/AndroidRuntime(18956):    at org.webrtc.VideoCapturer.takeNativeVideoCapturer(VideoCapturer.java:52)
E/AndroidRuntime(18956):    at org.webrtc.PeerConnectionFactory.createVideoSource(PeerConnectionFactory.java:113)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient.createVideoTrack(PeerConnectionClient.java:720)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient.createPeerConnectionInternal(PeerConnectionClient.java:482)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient.access$20(PeerConnectionClient.java:433)
E/AndroidRuntime(18956):    at com.example.rtcapp.PeerConnectionClient$2.run(PeerConnectionClient.java:280)
E/AndroidRuntime(18956):    at android.os.Handler.handleCallback(Handler.java:733)
E/AndroidRuntime(18956):    at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime(18956):    at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime(18956):    at com.example.rtcapp.LooperExecutor.run(LooperExecutor.java:56)

尝试在PeerConnectionClients之间共享VideoTrack对象会导致本机代码出现此错误:

E/libjingle(19884): Local fingerprint does not match identity.
E/libjingle(19884): P2PTransportChannel::Connect: The ice_ufrag_ and the ice_pwd_ are not set.
E/libjingle(19884): Local fingerprint does not match identity.
E/libjingle(19884): Failed to set local offer sdp: Failed to push down transport description: Local fingerprint does not match identity.

在PeerConnectionClients之间共享MediaStream会导致应用突然关闭,而Logcat中不会出现任何错误消息。


阅读 344

收藏
2020-12-03

共1个答案

一尘不染

您遇到的问题是PeerConnectionClient 不是 PeerConnection 的包装,它 包含 PeerConnection。

我注意到这个问题没有得到回答,所以我想看看能否帮上忙。我查看了源代码,PeerConnectionClient对单个远程对等方进行了非常硬的编码。您将需要创建PeerConnection对象的集合,而不是下面的代码行:

private PeerConnection peerConnection;

如果环顾四周,您会发现它变得更加复杂。

createPeerConnectionInternal中的mediaStream逻辑仅应执行一次,并且您需要像这样在PeerConnection对象之间共享流:

peerConnection.addStream(mediaStream);

您可以查阅WebRTC规范或查看此问题,以确认PeerConnection类型设计为仅处理一个对等方。这里也隐约地暗示了这一点

因此,您只需维护一个mediaStream对象:

private MediaStream mediaStream;

因此,主要思想还是一个MediaStream对象以及与要连接的对等体一样多的PeerConnection对象。因此,您将不会使用多个PeerConnectionClient对象,而是修改单个PeerConnectionClient来封装多客户端处理。如果您出于某种原因想要设计多个PeerConnectionClient对象,则只需从中提取媒体流逻辑(以及仅应创建一次的任何支持类型)。

您还需要维护多个远程视频轨道,而不是现有的一个:

private VideoTrack remoteVideoTrack;

显然,您只关心渲染一台本地摄像机并为远程连接创建多个渲染器。

我希望这些信息足以使您重回正轨。

2020-12-03