如何使用 AVCaptureDeviceDiscoverySession 获取前置摄像头、后置摄像头和音频
How to get front camera, back camera and audio with AVCaptureDeviceDiscoverySession
在 iOS 10 出来之前,我使用以下代码为我的录像机获取视频和音频捕获:
for device in AVCaptureDevice.devices()
{
if (device as AnyObject).hasMediaType( AVMediaTypeAudio )
{
self.audioCapture = device as? AVCaptureDevice
}
else if (device as AnyObject).hasMediaType( AVMediaTypeVideo )
{
if (device as AnyObject).position == AVCaptureDevicePosition.back
{
self.backCameraVideoCapture = device as? AVCaptureDevice
}
else
{
self.frontCameraVideoCapture = device as? AVCaptureDevice
}
}
}
当iOS 10终于出来的时候,我在运行我的代码中收到了以下警告。请注意,我的录像机在大约 2 周内仍能正常工作。
'devices()' was deprecated in iOS 10.0: Use AVCaptureDeviceDiscoverySession instead.
因为我今天早上 运行 我的代码,所以我的录像机停止工作了。 xCode8 没有给我任何错误,但相机捕获的 previewLayer 是完全白色的。当我开始录制时,我收到以下错误:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x17554440 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12780)}
我认为这与我使用的是已弃用的方法有关 AVCaptureDevice.devices()
。因此,我想知道如何使用 AVCaptureDeviceDiscoverySession
来代替?
提前感谢您的帮助!
您可以通过以下方式获取前置摄像头:
AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .front)
后置摄像头:
AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
还有麦克风:
AVCaptureDevice.default(.builtInMicrophone, for: AVMediaType.audio, position: .unspecified)
对于我的视频捕获应用程序,我使用以下代码获取麦克风、前置和后置摄像头,并且我已经从 iOS 7 到 10.0.2 测试了此代码。
var frontCamera : AVCaptureDevice?
var rearCamera : AVCaptureDevice?
captureSession = AVCaptureSession()
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
let audioDevices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeAudio)
for mic in audioDevices {
audioDevice = mic as? AVCaptureDevice
audioCapturePossible = true
}
for device in devices {
if device.position == AVCaptureDevicePosition.Front {
frontCamera = device as? AVCaptureDevice
hasFrontCamera = true
}
else if device.position == AVCaptureDevicePosition.Back {
rearCamera = device as? AVCaptureDevice
hasRearCamera = true
}
}
这是我获取相机位置的代码 (Swift 3) :
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(_ position: AVCaptureDevicePosition) -> AVCaptureDevice?
{
if let deviceDescoverySession = AVCaptureDeviceDiscoverySession.init(deviceTypes: [AVCaptureDeviceType.builtInWideAngleCamera],
mediaType: AVMediaTypeVideo,
position: AVCaptureDevicePosition.unspecified) {
for device in deviceDescoverySession.devices {
if device.position == position {
return device
}
}
}
return nil
}
如果需要,您还可以通过更改 deviceTypes 数组从 iPhone 7+(双摄像头)获取新的 devicesTypes。
尝试以下代码获取相机 ID:
NSString *cameraID = nil;
NSArray *captureDeviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera];
AVCaptureDeviceDiscoverySession *captureDevice =
[AVCaptureDeviceDiscoverySession
discoverySessionWithDeviceTypes:captureDeviceType
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionUnspecified];
cameraID = [captureDevice.devices.lastObject localizedName];
Swift 3
用于选择后置摄像头:(也可以根据需要更改.back)
要选择另一个设备类型,只需将其添加到 [ ] 内(即:
[deviceTypeCamera, AVCaptureDeviceType.builtInMicrophone]
(或者像我在代码中用后置摄像头做的那样创建一个私人出租屋)
private let position = AVCaptureDevicePosition.back
private let deviceTypeBackCamera = AVCaptureDeviceType.builtInWideAngleCamera
private func selectCaptureDevice() -> AVCaptureDevice? {
return AVCaptureDeviceDiscoverySession(deviceTypes: [deviceTypeBackCamera], mediaType: AVMediaTypeVideo, position: position).devices.first
}
Swift 4, iOS 10+ 和 Xcode 10.1 替换
if let cameraID = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)?.localizedName {
//cameraID = "Front Camera"
}
AVCaptureDevice.DiscoverySession实施
if let cameraID = AVCaptureDevice.DiscoverySession.init(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: .video, position: .front).devices.first?.localizedName{
//cameraID = "Front Camera"
}
需要用#available(iOS 10,*) check.
包裹起来
适用于 Xcode 9.2 和 Swift 4
AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
https://developer.apple.com/documentation/avfoundation/avcapturedevice/2361508-default
示例:iOS11Swift4
override func viewDidLoad() {
super.viewDidLoad()
// Get the back-facing camera for capturing videos
// AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
let deviceDiscoverySession = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
guard let captureDevice = deviceDiscoverySession else {
print("Failed to get the camera device")
return
}
do {
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
let input = try AVCaptureDeviceInput(device: captureDevice)
// Set the input device on the capture session.
captureSession.addInput(input)
} catch {
// If any error occurs, simply print it out and don't continue any more.
print(error)
return
}
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
// Start video capture.
captureSession.startRunning()
Swift 4 (xCode 10.1)
这就是 Swift 最新版本中对我有用的东西。我没有看到这个答案,我花了一段时间才弄清楚,所以这里是如何获得前置摄像头。
if let device = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera , mediaType: AVMediaTypeVideo, position: .front) {
//Do the camera thing here..
}
05/2019 :
//video
self.session = AVCaptureSession()
guard
let videoDeviceInput = try? AVCaptureDeviceInput(device: device!),
self.session!.canAddInput(videoDeviceInput)
else { return }
self.session!.addInput(videoDeviceInput)
//audio
guard
let audioDeviceInput = try? AVCaptureDeviceInput(device: mic!),
self.session!.canAddInput(audioDeviceInput)
else { return }
self.session!.addInput(audioDeviceInput)
简体:
func getCamera(with position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let deviceDescoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera], mediaType: .video, position: .unspecified)
return deviceDescoverySession.devices.first(where: { [=10=].position == position })
}
// and you can use like that:
guard let device = getCamera(with: .back) else { return }
在Swift 5更容易
AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .front)
在 iOS 10 出来之前,我使用以下代码为我的录像机获取视频和音频捕获:
for device in AVCaptureDevice.devices()
{
if (device as AnyObject).hasMediaType( AVMediaTypeAudio )
{
self.audioCapture = device as? AVCaptureDevice
}
else if (device as AnyObject).hasMediaType( AVMediaTypeVideo )
{
if (device as AnyObject).position == AVCaptureDevicePosition.back
{
self.backCameraVideoCapture = device as? AVCaptureDevice
}
else
{
self.frontCameraVideoCapture = device as? AVCaptureDevice
}
}
}
当iOS 10终于出来的时候,我在运行我的代码中收到了以下警告。请注意,我的录像机在大约 2 周内仍能正常工作。
'devices()' was deprecated in iOS 10.0: Use AVCaptureDeviceDiscoverySession instead.
因为我今天早上 运行 我的代码,所以我的录像机停止工作了。 xCode8 没有给我任何错误,但相机捕获的 previewLayer 是完全白色的。当我开始录制时,我收到以下错误:
Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x17554440 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}, NSLocalizedFailureReason=An unknown error occurred (-12780)}
我认为这与我使用的是已弃用的方法有关 AVCaptureDevice.devices()
。因此,我想知道如何使用 AVCaptureDeviceDiscoverySession
来代替?
提前感谢您的帮助!
您可以通过以下方式获取前置摄像头:
AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .front)
后置摄像头:
AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
还有麦克风:
AVCaptureDevice.default(.builtInMicrophone, for: AVMediaType.audio, position: .unspecified)
对于我的视频捕获应用程序,我使用以下代码获取麦克风、前置和后置摄像头,并且我已经从 iOS 7 到 10.0.2 测试了此代码。
var frontCamera : AVCaptureDevice?
var rearCamera : AVCaptureDevice?
captureSession = AVCaptureSession()
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
let audioDevices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeAudio)
for mic in audioDevices {
audioDevice = mic as? AVCaptureDevice
audioCapturePossible = true
}
for device in devices {
if device.position == AVCaptureDevicePosition.Front {
frontCamera = device as? AVCaptureDevice
hasFrontCamera = true
}
else if device.position == AVCaptureDevicePosition.Back {
rearCamera = device as? AVCaptureDevice
hasRearCamera = true
}
}
这是我获取相机位置的代码 (Swift 3) :
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(_ position: AVCaptureDevicePosition) -> AVCaptureDevice?
{
if let deviceDescoverySession = AVCaptureDeviceDiscoverySession.init(deviceTypes: [AVCaptureDeviceType.builtInWideAngleCamera],
mediaType: AVMediaTypeVideo,
position: AVCaptureDevicePosition.unspecified) {
for device in deviceDescoverySession.devices {
if device.position == position {
return device
}
}
}
return nil
}
如果需要,您还可以通过更改 deviceTypes 数组从 iPhone 7+(双摄像头)获取新的 devicesTypes。
尝试以下代码获取相机 ID:
NSString *cameraID = nil;
NSArray *captureDeviceType = @[AVCaptureDeviceTypeBuiltInWideAngleCamera];
AVCaptureDeviceDiscoverySession *captureDevice =
[AVCaptureDeviceDiscoverySession
discoverySessionWithDeviceTypes:captureDeviceType
mediaType:AVMediaTypeVideo
position:AVCaptureDevicePositionUnspecified];
cameraID = [captureDevice.devices.lastObject localizedName];
Swift 3
用于选择后置摄像头:(也可以根据需要更改.back)
要选择另一个设备类型,只需将其添加到 [ ] 内(即:
[deviceTypeCamera, AVCaptureDeviceType.builtInMicrophone]
(或者像我在代码中用后置摄像头做的那样创建一个私人出租屋)
private let position = AVCaptureDevicePosition.back
private let deviceTypeBackCamera = AVCaptureDeviceType.builtInWideAngleCamera
private func selectCaptureDevice() -> AVCaptureDevice? {
return AVCaptureDeviceDiscoverySession(deviceTypes: [deviceTypeBackCamera], mediaType: AVMediaTypeVideo, position: position).devices.first
}
Swift 4, iOS 10+ 和 Xcode 10.1 替换
if let cameraID = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front)?.localizedName {
//cameraID = "Front Camera"
}
AVCaptureDevice.DiscoverySession实施
if let cameraID = AVCaptureDevice.DiscoverySession.init(deviceTypes: [AVCaptureDevice.DeviceType.builtInWideAngleCamera], mediaType: .video, position: .front).devices.first?.localizedName{
//cameraID = "Front Camera"
}
需要用#available(iOS 10,*) check.
包裹起来适用于 Xcode 9.2 和 Swift 4
AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
https://developer.apple.com/documentation/avfoundation/avcapturedevice/2361508-default
示例:iOS11Swift4
override func viewDidLoad() {
super.viewDidLoad()
// Get the back-facing camera for capturing videos
// AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
let deviceDiscoverySession = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back)
guard let captureDevice = deviceDiscoverySession else {
print("Failed to get the camera device")
return
}
do {
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
let input = try AVCaptureDeviceInput(device: captureDevice)
// Set the input device on the capture session.
captureSession.addInput(input)
} catch {
// If any error occurs, simply print it out and don't continue any more.
print(error)
return
}
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
// Start video capture.
captureSession.startRunning()
Swift 4 (xCode 10.1)
这就是 Swift 最新版本中对我有用的东西。我没有看到这个答案,我花了一段时间才弄清楚,所以这里是如何获得前置摄像头。
if let device = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera , mediaType: AVMediaTypeVideo, position: .front) {
//Do the camera thing here..
}
05/2019 :
//video
self.session = AVCaptureSession()
guard
let videoDeviceInput = try? AVCaptureDeviceInput(device: device!),
self.session!.canAddInput(videoDeviceInput)
else { return }
self.session!.addInput(videoDeviceInput)
//audio
guard
let audioDeviceInput = try? AVCaptureDeviceInput(device: mic!),
self.session!.canAddInput(audioDeviceInput)
else { return }
self.session!.addInput(audioDeviceInput)
简体:
func getCamera(with position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let deviceDescoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera], mediaType: .video, position: .unspecified)
return deviceDescoverySession.devices.first(where: { [=10=].position == position })
}
// and you can use like that:
guard let device = getCamera(with: .back) else { return }
在Swift 5更容易
AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .front)