【问题标题】:How to capture screenshot for Publish stream using WebRTC in iOS?如何在 iOS 中使用 WebRTC 捕获发布流的屏幕截图?
【发布时间】:2020-01-14 11:41:16
【问题描述】:

在 iOS 的 WebRTC 中,我使用 RTCCameraPreviewView 播放发布流和 RTCMTLVideoView 播放远程流。

我可以使用以下代码为 Remote steam 拍摄快照:

UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 2.0f);
 [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
 UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();

但是当我使用相同的代码捕获本地流的快照时,我得到一个空白图像。

请建议,如何为本地流拍摄快照。

【问题讨论】:

  • 请查看以下链接,这些链接可以帮助您回答stackoverflow.com/questions/27646689/snap-shot-is-not-working,以了解为什么屏幕截图适用于远程流但不适用于本地流是因为视频编解码器。当您尝试捕获本地流视频的编解码器是 H264 时,当您获取远程流时,视频的编解码器将是 VP8 或 VP9。如果您需要其他帮助,请告诉我
  • @SumitMeena,因为我用于发布流的视频编解码器仅为 -VP8。但它不起作用。我找到了替代方案及其工作。
  • 好,但据我所知,ios h264 中 localtrack 的视频渲染

标签: ios objective-c swift webrtc


【解决方案1】:

在 webRTC 中使用 RTCCameraPreviewView 显示发布流时,您无法拍摄快照因为 ** RTCCameraPreviewView** 通过 AVCaptureVideoPreviewLayer 进行处理,并且它实现为 OpenGL层,因此您不能使用常规 CoreGraphic 的上下文在 RTCCameraPreviewView 上拍摄快照。 但是我们可以覆盖 RTCCameraPreviewView captchaSession 并在我们的控制器中设置 AVCaptureVideoDataOutput 委托,并获得 Frame 作为 CMSampleBufferRef。 为了让它工作,我们需要从“RTCCameraPreviewView”对象中获取“AVCaptureSession”引用。

RTCCameraPreviewView *publisherView = [[RTCCameraPreviewView alloc]initWithFrame:self.frame];
       AVCaptureSession *session = publisherView.captureSession;

现在我们可以从 ** AVCaptureSession** 获取可用的 ** AVCaptureVideoDataOutput** 列表

NSArray *dataOutputList = session.outputs

在获取 dataOutputList 列表后,过滤该数组并找到正确的 AVCaptureVideoDataOutput,您的发布者在其上播放视频。

例如让我们假设

AVCaptureVideoDataOutput*captureVideoOutput = dataOutputList[0];

这意味着索引“0”具有本地发布者视频AVCaptureVideoDataOutput 现在参考如下设置的旧代表

id capTchadelegate = captureVideoOutput.sampleBufferDelegate;

然后覆盖 AVCaptureVideoDataOutputSampleBufferDelegate 如下

[captureVideoOutput setSampleBufferDelegate:self  queue:dispatch_get_main_queue()];

覆盖委托后实现AVCaptureVideoDataOutputSampleBufferDelegate 在你的班级ab下面

- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;

这里我们将获取 CMSampleBufferRef 并将其转换为 UIImage

在为 AVCaptureVideoDataOutputSampleBufferDelegate 获得所需的 CMSampleBufferRef 图像集委托后,这样您的发布流就不会在同一呼叫中为其他接收者卡住

[captureVideoOutput setSampleBufferDelegate:capTchadelegate queue:dispatch_get_main_queue()];

【讨论】:

    【解决方案2】:

    在你的 viewController.swift 文件中

    func takeScreenshot(_ shouldSave: Bool = true) {
           var screenshotImage :UIImage?
           let layer = UIApplication.shared.keyWindow!.layer
           let scale = UIScreen.main.scale
           UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale)
        self.view.drawHierarchy(in: self.view.bounds, afterScreenUpdates: true)
           screenshotImage = UIGraphicsGetImageFromCurrentImageContext()
           UIGraphicsEndImageContext()
           if let image = screenshotImage, shouldSave {
               UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
           }
       }
    

    【讨论】:

    • 取决于帧大小,而不是缓冲区图像的大小
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 2015-04-06
    相关资源
    最近更新 更多