畫面采集
導(dǎo)入AVFoundation
1.在Main.storyboard上拖入3個按鈕,一個是開始錄制
,一個是暫停錄制
,一個是旋轉(zhuǎn)鏡頭
.
2.將按鈕拉線到工程內(nèi),分別為
startCapture
,stopCapture
,rotateCamera
3.采集畫面
// 創(chuàng)建一個錄制會話對象
fileprivate lazy var session : AVCaptureSession = AVCaptureSession()
// 創(chuàng)建一個預(yù)覽圖層
fileprivate lazy var preViewLayer : AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.session)
// 創(chuàng)建全局隊列
fileprivate lazy var queue = DispatchQueue.global()
fileprivate lazy var audioQueue = DispatchQueue.global()
// 創(chuàng)建視頻輸入源
fileprivate var videoInput : AVCaptureDeviceInput?
// 創(chuàng)建視頻輸出源
fileprivate var videoOutPut : AVCaptureVideoDataOutput?
// 創(chuàng)建音頻輸入源
fileprivate var audioInput : AVCaptureDeviceInput?
// 創(chuàng)建音頻輸出源
fileprivate var audioOutPut : AVCaptureAudioDataOutput?
開始采集畫面
fileprivate func setUpVideo(){
// 會話輸入源(獲取攝像頭)
// 獲取設(shè)備
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
}
// 設(shè)置視頻輸入源 全局變量
self.videoInput = input
// 判斷視頻會話對象是否能添加輸入源
if self.session.canAddInput(input){
self.session.addInput(input)
}
// 會話輸出源
let outPut : AVCaptureVideoDataOutput = AVCaptureVideoDataOutput()
// 設(shè)置輸出源的代理
outPut.setSampleBufferDelegate(self, queue: self.queue)
// 判斷視頻錄制會話對象是否能添加輸出源
if self.session.canAddOutput(outPut){
self.session.addOutput(outPut)
}
self.videoOutPut = outPut
旋轉(zhuǎn)鏡頭
// 添加鏡頭旋轉(zhuǎn)的動畫
@IBAction func rotateCamera(_ sender: AnyObject) {
// 添加旋轉(zhuǎn)攝像頭的動畫
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}
// 設(shè)置相反的位置的鏡頭
position = position == .front ? .back : .front
// 根據(jù)現(xiàn)在攝像頭的位置創(chuàng)建新的device
let devices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo) as? [AVCaptureDevice]
guard let device = devices?.filter({$0.position == position}).first else {return}
// 創(chuàng)建新的輸入源
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(){
// 創(chuàng)建音頻輸入源(話筒)
// 獲取設(shè)備
guard let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeAudio) else {return}
// 創(chuàng)建輸入源
guard let input = try? AVCaptureDeviceInput(device: device) else {return}
self.audioInput = input
// 判斷是否能添加輸入源
if session.canAddInput(input) {
session.addInput(input)
}
// 創(chuàng)建輸出源
let outPut = AVCaptureAudioDataOutput()
// 設(shè)置代理
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