直播一:画面采集和声音采集

直播一:画面采集和声音采集_第1张图片
伟大的雷锋同志

画面采集

导入AVFoundation
1.在Main.storyboard上拖入3个按钮,一个是开始录制,一个是暂停录制,一个是旋转镜头.

直播一:画面采集和声音采集_第2张图片
main.storyBoard上的三个按钮

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

你可能感兴趣的:(直播一:画面采集和声音采集)