Swift IOS 使用 AVFoundation 录制视频和音频
Posted
技术标签:
【中文标题】Swift IOS 使用 AVFoundation 录制视频和音频【英文标题】:Swift IOS Record Video and Audio with AVFoundation 【发布时间】:2016-03-05 04:38:05 【问题描述】:按照这个问题,我能够成功抓取录制的视频 here
基本上
-
从
AVCaptureFileOutputRecordingDelegate
原型继承
循环访问可用设备
使用相机创建会话
开始录制
停止录制
通过实现上述原型的方法获取录制视频
但该文件不附带音频。
根据this的问题,我必须单独录制音频并使用提到的类合并视频和音频
但我不知道如何同时实现视频和音频录制。
for device in devices
// Make sure this particular device supports video
if (device.hasMediaType(AVMediaTypeVideo))
// Finally check the position and confirm we've got the back camera
if(device.position == AVCaptureDevicePosition.Back)
captureDevice = device as? AVCaptureDevice
if captureDevice != nil
print("Capture device found")
beginSession()
在这个循环中,只有可用的设备类型是 .Front 和 .Back
【问题讨论】:
【参考方案1】:以下是使用 AVFoundation 框架录制带音频的视频的方法。步骤是:
1.准备会议:
self.captureSession = AVCaptureSession()
2。准备可用的视频和音频设备:
let session = AVCaptureDevice.DiscoverySession.init(deviceTypes:[.builtInWideAngleCamera, .builtInMicrophone], mediaType: AVMediaType.video, position: AVCaptureDevice.Position.unspecified)
let cameras = (session.devices.compactMap$0)
for camera in cameras
if camera.position == .front
self.frontCamera = camera
if camera.position == .back
self.rearCamera = camera
try camera.lockForConfiguration()
camera.focusMode = .continuousAutoFocus
camera.unlockForConfiguration()
3.准备会话输入:
guard let captureSession = self.captureSession else
throw CameraControllerError.captureSessionIsMissing
if let rearCamera = self.rearCamera
self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera)
if captureSession.canAddInput(self.rearCameraInput!)
captureSession.addInput(self.rearCameraInput!)
self.currentCameraPosition = .rear
else
throw CameraControllerError.inputsAreInvalid
else if let frontCamera = self.frontCamera
self.frontCameraInput = try AVCaptureDeviceInput(device: frontCamera)
if captureSession.canAddInput(self.frontCameraInput!)
captureSession.addInput(self.frontCameraInput!)
self.currentCameraPosition = .front
else
throw CameraControllerError.inputsAreInvalid
else
throw CameraControllerError.noCamerasAvailable
// Add audio input
if let audioDevice = self.audioDevice
self.audioInput = try AVCaptureDeviceInput(device: audioDevice)
if captureSession.canAddInput(self.audioInput!)
captureSession.addInput(self.audioInput!)
else
throw CameraControllerError.inputsAreInvalid
4.准备输出:
self.videoOutput = AVCaptureMovieFileOutput()
if captureSession.canAddOutput(self.videoOutput!)
captureSession.addOutput(self.videoOutput!)
captureSession.startRunning()
5.开始录制:
func recordVideo(completion: @escaping (URL?, Error?) -> Void)
guard let captureSession = self.captureSession, captureSession.isRunning else
completion(nil, CameraControllerError.captureSessionIsMissing)
return
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let fileUrl = paths[0].appendingPathComponent("output.mp4")
try? FileManager.default.removeItem(at: fileUrl)
videoOutput!.startRecording(to: fileUrl, recordingDelegate: self)
self.videoRecordCompletionBlock = completion
6.停止录制:
func stopRecording(completion: @escaping (Error?) -> Void)
guard let captureSession = self.captureSession, captureSession.isRunning else
completion(CameraControllerError.captureSessionIsMissing)
return
self.videoOutput?.stopRecording()
7.实现委托:
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?)
if error == nil
//do something
else
//do something
我从这里得到想法:https://www.appcoda.com/avfoundation-swift-guide/
这是完整的项目https://github.com/rubaiyat6370/ios-Tutorial/
【讨论】:
【参考方案2】:找到答案了,这个答案是this代码
这可以简单地完成
-
声明另一个捕获设备变量
遍历设备并初始化摄像头和音频捕获设备变量
向会话添加音频输入
代码
var captureDevice : AVCaptureDevice?
var captureAudio :AVCaptureDevice?
循环设备并初始化捕获设备
var captureDeviceVideoFound: Bool = false
var captureDeviceAudioFound:Bool = false
// Loop through all the capture devices on this phone
for device in devices
// Make sure this particular device supports video
if (device.hasMediaType(AVMediaTypeVideo))
// Finally check the position and confirm we've got the front camera
if(device.position == AVCaptureDevicePosition.Front)
captureDevice = device as? AVCaptureDevice //initialize video
if captureDevice != nil
print("Capture device found")
captureDeviceVideoFound = true;
if(device.hasMediaType(AVMediaTypeAudio))
print("Capture device audio init")
captureAudio = device as? AVCaptureDevice //initialize audio
captureDeviceAudioFound = true
if(captureDeviceAudioFound && captureDeviceVideoFound)
beginSession()
内部会议
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
try captureSession.addInput(AVCaptureDeviceInput(device: captureAudio))
这将输出带有音频的视频文件。无需合并音频或做任何事情。
这个苹果文档helps
【讨论】:
【参考方案3】:遵循@Mumu 的回答,但它对我不起作用,因为对 AVCaptureDevice.DiscoverySession.init 的调用仅返回视频设备。
这是我在 iOS 14 Swift 5 上运行的版本:
var captureSession: AVCaptureSession? = nil
var camera: AVCaptureDevice? = nil
var microphone: AVCaptureDevice? = nil
var videoOutput: AVCaptureFileOutput? = nil
var previewLayer: AVCaptureVideoPreviewLayer? = nil
func findDevices()
camera = nil
microphone = nil
//Search for video media type and we need back camera only
let session = AVCaptureDevice.DiscoverySession.init(deviceTypes:[.builtInWideAngleCamera],
mediaType: AVMediaType.video, position: AVCaptureDevice.Position.back)
var devices = (session.devices.compactMap$0)
//Search for microphone
let asession = AVCaptureDevice.DiscoverySession.init(deviceTypes:[.builtInMicrophone],
mediaType: AVMediaType.audio, position: AVCaptureDevice.Position.unspecified)
//Combine all devices into one list
devices.append(contentsOf: asession.devices.compactMap$0)
for device in devices
if device.position == .back
do
try device.lockForConfiguration()
device.focusMode = .continuousAutoFocus
device.flashMode = .off
device.whiteBalanceMode = .continuousAutoWhiteBalance
device.unlockForConfiguration()
camera = device
catch
if device.hasMediaType(.audio)
microphone = device
func initVideoRecorder()->Bool
captureSession = AVCaptureSession()
guard let captureSession = captureSession else return false
captureSession.sessionPreset = .hd4K3840x2160
findDevices()
guard let camera = camera else return false
do
let cameraInput = try AVCaptureDeviceInput(device: camera)
captureSession.addInput(cameraInput)
catch
self.camera = nil
return false
if let audio = microphone
do
let audioInput = try AVCaptureDeviceInput(device: audio)
captureSession.addInput(audioInput)
catch
videoOutput = AVCaptureMovieFileOutput()
if captureSession.canAddOutput(videoOutput!)
captureSession.addOutput(videoOutput!)
captureSession.startRunning()
videoOutput?.connection(with: .video)?.videoOrientation = .landscapeRight
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer?.videoGravity = .resizeAspect
previewLayer?.connection?.videoOrientation = .landscapeRight
return true
return false
func startRecording()->Bool
guard let captureSession = captureSession, captureSession.isRunning else return false
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let fileUrl = paths[0].appendingPathComponent(getVideoName())
try? FileManager.default.removeItem(at: fileUrl)
videoOutput?.startRecording(to: fileUrl, recordingDelegate: self)
return true
【讨论】:
【参考方案4】:我也遇到了这个问题,但是当我分组添加视频输入和声音输入之后,音频工作了。这是我添加输入的代码。
if (cameraSession.canAddInput(deviceInput) == true && cameraSession.canAddInput(audioDeviceInput) == true) //detects if devices can be added
cameraSession.addInput(deviceInput)//adds video
cameraSession.addInput(audioDeviceInput)//adds audio
另外我发现你必须先有视频输入,否则不会有音频。我最初将它们放在两个 if 语句中,但我发现将它们放在一个中可以将视频和音频记录在一起。希望这会有所帮助。
【讨论】:
【参考方案5】:用音频录制视频
//获取视频设备
if let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice]
for device in devices
if device.hasMediaType(AVMediaTypeVideo)
if device.position == AVCaptureDevicePosition.back
videoCaptureDevice = device
if videoCaptureDevice != nil
do
// Add Video Input
try self.captureSession.addInput(AVCaptureDeviceInput(device: videoCaptureDevice))
// Get Audio Device
let audioInput = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio)
//Add Audio Input
try self.captureSession.addInput(AVCaptureDeviceInput(device: audioInput))
self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.portrait
self.videoView.layer.addSublayer(self.previewLayer)
//Add File Output
self.captureSession.addOutput(self.movieOutput)
captureSession.startRunning()
catch
print(error)
更多详情请参考此链接:
https://medium.com/@santhosh3386/ios-avcapturesession-record-video-with-audio-23c8f8c9a8f8
【讨论】:
以上是关于Swift IOS 使用 AVFoundation 录制视频和音频的主要内容,如果未能解决你的问题,请参考以下文章
iOS Swift 3:导入 AVFoundation 产生了不需要的下划线按钮文本
Swift:使用系统AVFoundation实现二维码扫描和生成
使用 AVFoundation 裁剪 AVAsset 视频不工作 iOS 8