Wowza/WebRTC - 如何在相机翻转时重新协商视频格式

Posted

技术标签:

【中文标题】Wowza/WebRTC - 如何在相机翻转时重新协商视频格式【英文标题】:Wowza/WebRTC - how to re-negotiate video format on camera flip 【发布时间】:2021-08-03 19:06:51 【问题描述】:

我遵循了来自 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 试图开始新的蒸汽。很难找到任何关于此的文档。

【问题讨论】:

【参考方案1】:

如果其他人遇到同样的问题,请在此处发布我的解决方案,我需要几天的反复试验才能得出解决方案。

我真正需要的只是切换相机而不重新协商RTCPeerConnection。我看到他们在 RTCRtpSender 上切换视频轨道的 javascript 示例,但这在 iOS 上不起作用,iOS 框架也没有浏览器的 javascript WebRTC 库中存在的 replaceVideoTrack 方法。

我的解决方案是在现有的RTCCameraVideoCapturer 上更新摄像头,从而保留现有的 RTCVideoSourceRTCVideoTrack

我最初创建视频轨道的电话是这样的:

    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.width))
         else 
            videoSize = CGSize(width: CGFloat(dims.width), height: CGFloat(dims.height))
        
        let fps = selectFrameRate(ranges: format.videoSupportedFrameRateRanges)
        capturer.startCapture(with: camera, format: format, fps: Int(fps))
    

...并且相机翻转在实时视频流中发挥了魅力,无需重新协商连接。

【讨论】:

以上是关于Wowza/WebRTC - 如何在相机翻转时重新协商视频格式的主要内容,如果未能解决你的问题,请参考以下文章

在录制视频时处理相机翻转而不停止它反应原生

使用 AVCaptureSession 和 AVAssetWriter 在翻转相机时无缝录制音频

IOS Swift 3:拍摄相机图片后水平翻转前置摄像头图像

当 z <= 0 时 glm::lookAt 垂直相机翻转

如何在 JavaScript 中水平翻转图像

相机冻结:如何重新初始化相机组件?