画面采集
导入AVFoundation
1.在Main.storyboard上拖入3个按钮,一个是开始录制
,一个是暂停录制
,一个是旋转镜头
.
2.将按钮拉线到工程内,分别为
startCapture
,
stopCapture
,
rotateCamera
3.采集画面
// 创建一个录制会话对象
fileprivate lazy var session : AVCaptureSession = AVCaptureSession()
// 创建一个预览图层
fileprivate lazy var preViewLayer : AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.session)
// 创建全局队列
fileprivate lazy var queue = DispatchQueue.global()
fileprivate lazy var audioQueue = DispatchQueue.global()
// 创建视频输入源
fileprivate var videoInput : AVCaptureDeviceInput?
// 创建视频输出源
fileprivate var videoOutPut : AVCaptureVideoDataOutput?
// 创建音频输入源
fileprivate var audioInput : AVCaptureDeviceInput?
// 创建音频输出源
fileprivate var audioOutPut : AVCaptureAudioDataOutput?
开始采集画面
fileprivate func setUpVideo(){
// 会话输入源(获取摄像头)
// 获取设备
guard let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice] else {
print("模拟器无效")
return
}
// 获取前置摄像头
guard let deviece = devices.filter({ $0.position == .front }).first else {
return
}
// 获取AVCaptureDeviceInput 输入源
guard let input : AVCaptureDeviceInput = try? AVCaptureDeviceInput(device: deviece) else {
return
}
// 设置视频输入源 全局变量
self.videoInput = input
// 判断视频会话对象是否能添加输入源
if self.session.canAddInput(input){
self.session.addInput(input)
}
// 会话输出源
let outPut : AVCaptureVideoDataOutput = AVCaptureVideoDataOutput()
// 设置输出源的代理
outPut.setSampleBufferDelegate(self, queue: self.queue)
// 判断视频录制会话对象是否能添加输出源
if self.session.canAddOutput(outPut){
self.session.addOutput(outPut)
}
self.videoOutPut = outPut
旋转镜头
// 添加镜头旋转的动画
@IBAction func rotateCamera(_ sender: AnyObject) {
// 添加旋转摄像头的动画
let rotaionAnim = CATransition()
rotaionAnim.type = "oglFlip"
rotaionAnim.subtype = "fromLeft"
rotaionAnim.duration = 0.5
view.layer.add(rotaionAnim, forKey: nil)
// 获取之前的镜头
guard var position = self.videoInput?.device.position else {return}
// 设置相反的位置的镜头
position = position == .front ? .back : .front
// 根据现在摄像头的位置创建新的device
let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice]
guard let device = devices?.filter({$0.position == position}).first else {return}
// 创建新的输入源
guard let input = try? AVCaptureDeviceInput(device: device) else {return}
// 在session中切换input
session.beginConfiguration()
session.removeInput(self.videoInput)
if session.canAddInput(self.videoInput) {
session.addInput(input)
}
self.videoInput = input
session.commitConfiguration()
}
4.采集音频
fileprivate func setUpAudio(){
// 创建音频输入源(话筒)
// 获取设备
guard let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio) else {return}
// 创建输入源
guard let input = try? AVCaptureDeviceInput(device: device) else {return}
self.audioInput = input
// 判断是否能添加输入源
if session.canAddInput(input) {
session.addInput(input)
}
// 创建输出源
let outPut = AVCaptureAudioDataOutput()
// 设置代理
outPut.setSampleBufferDelegate(self, queue: self.audioQueue)
self.audioOutPut = outPut
// 判断是否能添加输出源
if session.canAddOutput(outPut){
session.addOutput(outPut)
}
//
遵守音频录制和视频录制的代理,两个代理方法是同一个
// 遵守录制视频输出会话的代理,sampleBuffer就是美颜所修改的东西
extension ViewController : AVCaptureVideoDataOutputSampleBufferDelegate,AVCaptureAudioDataOutputSampleBufferDelegate{
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
if connection == self.videoOutPut?.connection(withMediaType: AVMediaTypeVideo) {
print("输出视频画面")
}else{
print("获取音频!")
}
}
}
5.停止录制
// 停止录制
@IBAction func stopCapture(_ sender: AnyObject) {
self.session.stopRunning()
self.preViewLayer.removeFromSuperlayer()
self.fileOutPut?.stopRecording()
// 移除输入源和舒楚媛
self.session.removeInput(self.videoInput)
self.session.removeOutput(self.videoOutPut)
self.session.removeInput(self.audioInput)
self.session.removeOutput(self.audioOutPut)
self.session.removeOutput(self.fileOutPut)
}
将程序跑到真机上,点击开始录制即可以录制成功!
Demo