Android平台WebRTC中如何向PeerConnection添加多条媒体轨道?
问题描述
我需要向远端对等端发送多条媒体轨道(videoTrack、audioTrack、shareScreenTrack),已配置UNIFIED_PLAN模式:
val rtcConfig = PeerConnection.RTCConfiguration( arrayListOf(PeerConnection.IceServer.builder("stun:stun.l.google.com:19302").createIceServer()) ).apply { sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN }
通过以下方式添加轨道:
peerConnection?.addTrack(videoTrack) peerConnection?.addTrack(audioTrack) peerConnection?.addTrack(captureScreenVideoTrack)
但只有第一条轨道能成功传输,远端onTrack仅触发一次(仅videoTrack生效),audioTrack和captureScreenVideoTrack均未触发回调。远端调试代码如下:
override fun onTrack(transceiver: RtpTransceiver?) { super.onTrack(transceiver) val track = transceiver?.receiver?.track() ?: return when (track.kind()){ MediaStreamTrack.VIDEO_TRACK_KIND ->{ //videoTrack or captureScreenVideoTrack } MediaStreamTrack.AUDIO_TRACK_KIND ->{ //audioTrack } else -> {} } }
解决方法
1. 添加轨道时关联MediaStream
UNIFIED_PLAN模式下,建议将轨道关联到MediaStream后再添加,或者在addTrack时指定目标流标识:
// 方式1:统一添加到同一个MediaStream val mediaStream = peerConnection?.createLocalMediaStream("multi-track-stream") mediaStream?.addTrack(videoTrack) mediaStream?.addTrack(audioTrack) mediaStream?.addTrack(captureScreenVideoTrack) // 方式2:逐个添加时指定流标识 peerConnection?.addTrack(videoTrack, listOf("multi-track-stream")) peerConnection?.addTrack(audioTrack, listOf("multi-track-stream")) peerConnection?.addTrack(captureScreenVideoTrack, listOf("multi-track-stream"))
这样SDP协商时会生成对应所有轨道的m-line,确保远端能识别到多条轨道。
2. 手动创建独立RtpTransceiver
自动生成的transceiver可能存在复用问题,手动为每条轨道创建独立的传输器:
// 为音频轨道创建transceiver peerConnection?.addTransceiver( audioTrack, RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.SEND_ONLY) ) // 为摄像头视频轨道创建transceiver peerConnection?.addTransceiver( videoTrack, RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.SEND_ONLY) ) // 为屏幕共享轨道创建transceiver peerConnection?.addTransceiver( captureScreenVideoTrack, RtpTransceiverInit(RtpTransceiver.RtpTransceiverDirection.SEND_ONLY) )
手动指定传输方向为SEND_ONLY(仅发送场景),保证每条轨道拥有独立的传输通道。
3. 验证SDP是否包含所有轨道
创建Offer后打印SDP内容,确认是否存在音频、两条视频对应的m-line:
peerConnection?.createOffer(object : SdpObserver { override fun onCreateSuccess(desc: SessionDescription?) { desc?.let { println("Offer SDP: ${it.description}") peerConnection?.setLocalDescription(this, it) } } override fun onCreateFailure(error: String?) {} override fun onSetSuccess() {} override fun onSetFailure(error: String?) {} }, MediaConstraints())
如果SDP中只有一个m-line,检查轨道是否处于活跃状态(track.enabled需为true)。
4. 修正远端onTrack回调处理
UNIFIED_PLAN模式下每条轨道会单独触发onTrack,需确保远端同样启用UNIFIED_PLAN,同时避免默认父类方法的干扰:
override fun onTrack(transceiver: RtpTransceiver?) { val track = transceiver?.receiver?.track() ?: return when (track.kind()) { MediaStreamTrack.VIDEO_TRACK_KIND -> { // 通过track.id区分摄像头和屏幕共享轨道 if (track.id() == captureScreenVideoTrack.id()) { // 处理屏幕共享轨道 } else { // 处理摄像头视频轨道 } } MediaStreamTrack.AUDIO_TRACK_KIND -> { // 处理音频轨道 } else -> {} } }
内容的提问来源于stack exchange,提问作者cafer yıldız
相关产品推荐
相关产品推荐

