视频预览的自定义形状:AVCaptureVideoPreviewLayer?
Posted
技术标签:
【中文标题】视频预览的自定义形状:AVCaptureVideoPreviewLayer?【英文标题】:Custom shape for video preview: AVCaptureVideoPreviewLayer? 【发布时间】:2019-11-19 10:24:09 【问题描述】:是否可以像剪辑图像一样剪辑视频预览层?
image
.clipShape(Circle())
.overlay(Circle().stroke(Color.green, lineWidth: 1))
视频预览层的来源:
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = CGRect(x: 20, y: 60, width: 335, height: 200)
previewLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(previewLayer)
我一直在寻找,但没有运气。谢谢!
【问题讨论】:
试过.mask
? hackingwithswift.com/quick-start/swiftui/…
.mask 适用于图像类型。它似乎不适用于 avcapturepreviewlayer 或 frame 或 layer。我对这个修饰符有什么遗漏吗?
您有任何更新吗?谢谢
【参考方案1】:
在 macOS 10.15 Catalina 上测试
下面的演示代码是针对 SwiftUI/macOS 的,但它可能会有所帮助,因为只需对代码进行一些小改动即可使其与 ios 保持一致。
注意:这是一个演示,所以代码有点粗糙
结果如下:
这里是演示模块代码:
import SwiftUI
import AppKit
import AVFoundation
class PreviewView: NSView
private var captureSession: AVCaptureSession?
init()
super.init(frame: .zero)
var allowedAccess = false
let blocker = DispatchGroup()
blocker.enter()
AVCaptureDevice.requestAccess(for: .video) flag in
allowedAccess = flag
blocker.leave()
blocker.wait()
if !allowedAccess
print("!!! NO ACCESS TO CAMERA")
return
// setup session
let session = AVCaptureSession()
session.beginConfiguration()
// this part might be different in iOS
let videoDevice = AVCaptureDevice.default(for: .video)
guard let videoDeviceInput = try? AVCaptureDeviceInput(device: videoDevice!),
session.canAddInput(videoDeviceInput)
else return
session.addInput(videoDeviceInput)
session.commitConfiguration()
self.captureSession = session
// instead of below, use layerClass on iOS
self.wantsLayer = true
self.layer = AVCaptureVideoPreviewLayer()
required init?(coder: NSCoder)
fatalError("init(coder:) has not been implemented")
var videoPreviewLayer: AVCaptureVideoPreviewLayer
return layer as! AVCaptureVideoPreviewLayer
override func viewDidMoveToSuperview() // on iOS .didMoveToSuperview
super.viewDidMoveToSuperview()
if nil != self.superview
self.videoPreviewLayer.session = self.captureSession
self.videoPreviewLayer.videoGravity = .resizeAspect
self.captureSession?.startRunning()
else
self.captureSession?.stopRunning()
// for iOS NSView just rename to UIView
struct PreviewHolder: NSViewRepresentable
func makeNSView(context: NSViewRepresentableContext<PreviewHolder>) -> PreviewView
PreviewView()
func updateNSView(_ uiView: PreviewView, context: NSViewRepresentableContext<PreviewHolder>)
typealias NSViewType = PreviewView
struct DemoPreviewLayer: View
var body: some View
VStack
PreviewHolder()
.mask(Circle())
.frame(width: 400, height: 300)
struct DemoPreviewLayer_Previews: PreviewProvider
static var previews: some View
DemoPreviewLayer()
【讨论】:
只是想补充一点,如果您想将它与外部 Mac 相机一起使用,而不是按照示例中的默认设置,它真的非常简单。只需将 AVCaptureDevice.default 替换为以下内容。let videoDevice = AVCaptureDevice.DiscoverySession.init(deviceTypes: [.builtInWideAngleCamera, .externalUnknown], mediaType: .video, position: .unspecified)
然后在结果列表中选择第一个可用的设备..以上是关于视频预览的自定义形状:AVCaptureVideoPreviewLayer?的主要内容,如果未能解决你的问题,请参考以下文章
Android 实时视频采集—Camera预览采集与显示(平台系统camera功能理解分享)