使用WebRTC iOS Swift在视频通话期间在iPhoneX上纠正远程视频大小

时间:2019-06-24 14:02:09

标签: ios swift video-streaming webrtc webrtc-ios

我正在使用webRTC进行视频通话。一切运行顺利,但 我正在为iPhoneX,XSMax上的远程视频的纵横比而苦苦挣扎。我看到很多视频放大。您能帮我解决如何在有陷波功能的设备上管理远程视频吗?下面是我处理远程大小的代码。

func videoView(_ videoView: RTCEAGLVideoView, didChangeVideoSize size: CGSize) {
    print(size)

    let defaultAspectRatio: CGSize = CGSize(width: 4, height: 3)
    let aspectRatio: CGSize = size.equalTo(CGSize.zero) ? defaultAspectRatio : size
    let videoRect: CGRect = self.view.bounds
    let maxFloat = CGFloat.maximum(self.view.frame.width, self.view.frame.height)
    let newAspectRatio = aspectRatio.width / aspectRatio.height
    var frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
    if (aspectRatio.width < aspectRatio.height) {
        frame.size.width = maxFloat;
        frame.size.height = frame.size.width / newAspectRatio;
    } else {
        frame.size.height = maxFloat;
        frame.size.width = frame.size.height * newAspectRatio;
    }
    frame.origin.x = (self.view.frame.width - frame.size.width) / 2
    frame.origin.y = (self.view.frame.height - frame.size.height) / 2

self.remoteView.frame = frame

}

3 个答案:

答案 0 :(得分:1)

根据@Eysner的回答,对我有用的是最终代码(使用swift 5编写):

import UIKit
import WebRTC


final class WebRTCView: UIView, RTCVideoViewDelegate {
    let videoView = RTCEAGLVideoView(frame: .zero)
    var videoSize = CGSize.zero

    override init(frame: CGRect) {
        super.init(frame: frame)
        videoView.delegate = self
        addSubview(videoView)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        videoView.delegate = self
        addSubview(videoView)
    }

    func videoView(_ videoView: RTCVideoRenderer, didChangeVideoSize size: CGSize) {
        self.videoSize = size
        setNeedsLayout()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        guard videoSize.width > 0 && videoSize.height > 0 else {
            videoView.frame = bounds
            return
        }

        var videoFrame = AVMakeRect(aspectRatio: videoSize, insideRect: bounds)
        let scale = videoFrame.size.aspectFitScale(in: bounds.size)
        videoFrame.size.width = videoFrame.size.width * CGFloat(scale)
        videoFrame.size.height = videoFrame.size.height * CGFloat(scale)

        videoView.frame = videoFrame
        videoView.center = CGPoint(x: bounds.midX, y: bounds.midY)
    }
}


extension CGSize {
    func aspectFitScale(in container: CGSize) -> CGFloat {

        if height <= container.height && width > container.width {
            return container.width / width
        }
        if height > container.height && width > container.width {
            return min(container.width / width, container.height / height)
        }
        if height > container.height && width <= container.width {
            return container.height / height
        }
        if height <= container.height && width <= container.width {
            return min(container.width / width, container.height / height)
        }
        return 1.0
    }
}

有aspectFitScale函数,它只是描述逻辑,如果需要,您可以对其进行重构。

我在演示中使用了这种方法: https://github.com/Maxatma/Walkie-Talkie/

答案 1 :(得分:0)

您可以通过表演视频上课-

class SomeVideoView: UIView, RTCVideoViewDelegate {
    let videoView = RTCEAGLVideoView(frame: .zero)
    var videoSize = CGSize.zero

使用初始化方法

override init(frame: CGRect) {
    super.init(frame: frame)
    videoView.delegate = self
    self.addSubview(videoView)
   ...

像这样处理委托方法videoView:didChangeVideoSize(我们不需要在UI中更改框架,只需标记needLayout)

func videoView(_ videoView: RTCEAGLVideoView, didChangeVideoSize size: CGSize) {
    if (self.videoView == videoView) {
        self.videoSize = size
    }
    self.setNeedsLayout()
}

并覆盖layoutSubviews方法

override func layoutSubviews() {
    if (self.videoSize.width > 0 && self.videoSize.height > 0) {
        var videoFrame = AVMakeRect(aspectRatio: self.videoSize, insideRect: bounds)
        var scale = 1.0
        if (videoFrame.size.width > videoFrame.size.height) {
            scale = bounds.size.height / videoFrame.size.height
        } else {
            scale = bounds.size.width / videoFrame.size.width
        }
        videoFrame.size.width = videoFrame.size.width * scale
        videoFrame.size.height = videoFrame.size.height * scale
        self.videoView.frame = videoFrame
        self.videoView.center = CGPointMake(bounds.midX, bounds.midY)
    } else {
        self.videoView.frame = bounds
    }

    ...
}

并设置SomeVideoView为全屏显示(此链接可以为您提供帮助)
Safe Area of Xcode 9

答案 2 :(得分:0)

使用 AVMakeRect 很简单

//TODO: Default mobile
if size.width < size.height{
     newSize = aspectFill(aspectRatio: size, minimumSize: UIScreen.main.bounds.size)
}else{
            //Default computer
     newSize = AVMakeRect(aspectRatio: size, insideRect: UIScreen.main.bounds).size
 }

有时用户可能会从网站上打来电话,所以我没有填写

func aspectFill(aspectRatio : CGSize, minimumSize: CGSize) -> CGSize {
        let mW = minimumSize.width / aspectRatio.width;
        let mH = minimumSize.height / aspectRatio.height;
        
        var temp = minimumSize
        if( mH > mW ) {
            temp.width = minimumSize.height / aspectRatio.height * aspectRatio.width;
        }
        else if( mW > mH ) {
            temp.height = minimumSize.width / aspectRatio.width * aspectRatio.height;
        }
        
        return temp;
    }