问题描述
我遵循了 here 的一些提示,在 iOS 上通过 WebRTC 进行演示/流式传输时使相机从前向后翻转。翻转本身有效,但是当 RTcmediaStream
中的视频轨道发生变化时,RTCPeerConnection
会再次调用 peerConnectionShouldNegotiate
委托方法。这是我当前的实现(它适用于前置摄像头视频的初始调用,但在视频翻转时第二次调用时失败):
func peerConnectionShouldNegotiate(_ peerConnection: RTCPeerConnection) {
guard let stream = liveStream else {
return
}
print("peerConnectionShouldNegotiate")
peerConnection.offer(for: mediaConstraints) { (desc,err) in
if let error = err {
print("peerConnectionShouldNegotiate error",error)
} else if let desc = desc {
self.con?.setLocalDescription(desc,completionHandler: { (err) in
if let error = err {
print("set local desc error",error)
} else {
let message: [String: Any] = [
"direction": "publish","command": "sendOffer","streamInfo": [
"applicationName": stream.appName,"streamName": stream.streamName,"sessionId": self.sessionId
],"sdp": [
"type": RTCSessionDescription.string(for: desc.type),"sdp": desc.sdp
],"userData": [
"param1": "value1"
]
]
let messageData = try! JSONSerialization.data(withJSONObject: message,options: [])
let messageStr = String(data: messageData,encoding: .utf8)!
self.socket?.write(string: messageStr)
}
})
} else {
print("this is a no no")
}
}
}
来自信令服务器的 web-socket 响应带有错误和消息 Stream name is already in use: [my-stream-id]
我不知道我应该向 Wowza 的信令服务器发送什么样的消息来更新现有流中的视频格式。看来 sendOffer
试图开始一个新的蒸汽。很难找到任何关于此的文档。
解决方法
如果其他人遇到同样的问题,请在此处发布我的解决方案,我花了几天的反复试验才找到解决方案。
我真正需要的是在不重新协商 RTCPeerConnection
的情况下切换相机。我看到 javascript 示例,他们在 RTCRtpSender
上切换视频轨道,但这在 iOS 上不起作用,而且 iOS 框架也没有 replaceVideoTrack
方法存在于浏览器的 javascript WebRTC 库中。
我的解决方案是仅更新现有 RTCCameraVideoCapturer
上的相机,从而保留现有 RTCVideoSource
和 RTCVideoTrack
。
我最初创建视频轨道的调用是这样的:
func createVideoTrack() -> RTCVideoTrack? {
let devices = RTCCameraVideoCapturer.captureDevices()
guard
let camera = selectedCamera(devices: devices)
else {
return nil
}
let source = rtcPCFactory.videoSource()
let format = selectFormat(formats: camera.formats)
let dims = CMVideoFormatDescriptionGetDimensions(format.formatDescription)
if dims.width > dims.height {
videoSize = CGSize(width: CGFloat(dims.height),height: CGFloat(dims.width))
} else {
videoSize = CGSize(width: CGFloat(dims.width),height: CGFloat(dims.height))
}
let fps = selectFrameRate(ranges: format.videoSupportedFrameRateRanges)
source.adaptOutputFormat(toWidth: 512,height: 288,fps: Int32(fps))
let videoTrack = rtcPCFactory.videoTrack(with: source,trackId: internalStreamId + "v0")
let capturer = RTCCameraVideoCapturer(delegate: source)
capturer.startCapture(with: camera,format: format,fps: Int(fps))
cameraPreviewView.captureSession = capturer.captureSession
videoCapturer = capturer
return videoTrack
}
它成功地协商了对等连接,然后在翻转相机时我做到了:
func updateCapturerCamera() {
let devices = RTCCameraVideoCapturer.captureDevices()
guard
let camera = selectedCamera(devices: devices),let capturer = videoCapturer
else {
return
}
let format = selectFormat(formats: camera.formats)
let dims = CMVideoFormatDescriptionGetDimensions(format.formatDescription)
if dims.width > dims.height {
videoSize = CGSize(width: CGFloat(dims.height),height: CGFloat(dims.height))
}
let fps = selectFrameRate(ranges: format.videoSupportedFrameRateRanges)
capturer.startCapture(with: camera,fps: Int(fps))
}
...并且相机翻转功能在实时视频流中发挥了魅力,无需重新协商连接。