我创建了多个对等连接并将公共媒体流添加到所有对等连接。通过套接字 io交换SDP和Candidate。我成功地从本地媒体流获取本地视频,但该流并未显示在每个对等连接上,只有最后连接的对等端才能显示我的流
创建多个连接
房间视图控制器
for (index, peerId) in RoomViewController.arrPeers.enumerated() {
if peerId != LocalStorage.myId?.vBarId{
let webRTCClient = WebRTCClient.init(iceServers: config.webRTCIceServers, arrTurnServer: config.turnServers, strUserName: config.userName, strPassword: config.password, remoteId: peerId, signalClient: socketIoObject!, streamId: LocalStorage.myId?.vBarId ?? "")
webRTCClient.delegate = self
if index > myIndex{
//offerCallToLowerPeers(client: webRTCClient, callFor: peerId)
}else{
webRTCClient.isAnswerAble = true
}
RoomViewController.arrPeerWebclients.append(webRTCClient)
}
}
Run Code Online (Sandbox Code Playgroud)
WebRTC客户端
if arrTurnServer.count > 0{
let trunServers = RTCIceServer.init(urlStrings: arrTurnServer, username:strUserName, credential: strPassword)
config.iceServers = [RTCIceServer(urlStrings: iceServers), trunServers]
}else{
config.iceServers = [RTCIceServer(urlStrings: iceServers)]
}
//config.iceServers = [RTCIceServer(urlStrings: iceServers)]
// Unified plan is more superior than planB
config.sdpSemantics = .planB
// gatherContinually will let WebRTC to listen to any network changes and send any new candidates to the other client
config.continualGatheringPolicy = .gatherContinually
let constraints = RTCMediaConstraints(mandatoryConstraints: nil,
optionalConstraints: ["DtlsSrtpKeyAgreement":kRTCMediaConstraintsValueTrue])
self.peerConnection = WebRTCClient.factory.peerConnection(with: config, constraints: constraints, delegate: nil)
Run Code Online (Sandbox Code Playgroud)
创建本地媒体流
if RoomViewController.localMediaStream == nil{
let audioTrack = self.createAudioTrack()
print(audioTrack)
self.peerConnection.add(audioTrack, streamIds: [streamId])
let videoTrack = self.createVideoTrack()
self.localVideoTrack = videoTrack
let mediaStream = WebRTCClient.factory.mediaStream(withStreamId: streamId)
mediaStream.addAudioTrack(audioTrack)
mediaStream.addVideoTrack(videoTrack)
RoomViewController.localMediaStream = mediaStream
}
self.peerConnection.add(RoomViewController.localMediaStream)
Run Code Online (Sandbox Code Playgroud)
查看本地和远程视频
guard let capturer = RoomViewController.arrPeerWebclients.first!.videoCapturer as? RTCCameraVideoCapturer else {
return
}
guard
let frontCamera = (RTCCameraVideoCapturer.captureDevices().first { $0.position == .front }),
// choose highest res
let format = (RTCCameraVideoCapturer.supportedFormats(for: frontCamera).sorted { (f1, f2) -> Bool in
let width1 = CMVideoFormatDescriptionGetDimensions(f1.formatDescription).width
let width2 = CMVideoFormatDescriptionGetDimensions(f2.formatDescription).width
return width1 < width2
}).last,
// choose highest fps
let fps = (format.videoSupportedFrameRateRanges.sorted { return $0.maxFrameRate < $1.maxFrameRate }.last) else {
return
}
capturer.startCapture(with: frontCamera,
format: format,
fps: Int(fps.maxFrameRate))
let localVideoFrame = CGRect.init(x: 15, y: 100, width: 100, height: 100)
#if arch(arm64)
// Using metal (arm64 only)
let localRenderer = RTCMTLVideoView(frame: localVideoFrame)
localRenderer.videoContentMode = .scaleAspectFill
#else
// Using OpenGLES for the rest
let localRenderer = RTCEAGLVideoView(frame: localVideoFrame)
#endif
RoomViewController.localMediaStream.videoTracks.first?.add(localRenderer)
self.view.addSubview(localRenderer)
for (index, stream) in RoomViewController.arrRemoteStreams.enumerated() {
switch index {
case 0:
#if arch(arm64)
// Using metal (arm64 only)
let remoteRenderer = RTCMTLVideoView(frame: CGRect.init(x: 15, y: 300, width: 100, height: 100))
remoteRenderer.videoContentMode = .scaleAspectFill
#else
// Using OpenGLES for the rest
let remoteRenderer = RTCEAGLVideoView(frame: CGRect.init(x: 15, y: 300, width: 100, height: 100))
#endif
stream.videoTracks.first?.add(remoteRenderer)
self.view.addSubview(remoteRenderer)
case 1:
#if arch(arm64)
// Using metal (arm64 only)
let remoteRenderer = RTCMTLVideoView(frame: CGRect.init(x: 160, y: 300, width: 100, height: 100))
remoteRenderer.videoContentMode = .scaleAspectFill
#else
// Using OpenGLES for the rest
let remoteRenderer = RTCEAGLVideoView(frame: CGRect.init(x: 160, y: 300, width: 100, height: 100))
#endif
stream.videoTracks.first?.add(remoteRenderer)
self.view.addSubview(remoteRenderer)
default:
print("default case")
}
}
Run Code Online (Sandbox Code Playgroud)
我已经检查了多个答案,主要基于网络而不是 ios
| 归档时间: |
|
| 查看次数: |
571 次 |
| 最近记录: |