iOS-音视屏采集

2018-07-27  本文已影响0人  三月望龙

概述

采集流程

1、初始化输入输出源

    private func setupVideo() {
        // 获取视屏input所需的设备,本例取的是前置摄像头
        let devices = AVCaptureDevice.devices(for: AVMediaType.video)
        guard let device = devices.filter({ $0.position == .front}).first else {return}
        
        // input
        guard let input = try? AVCaptureDeviceInput(device: device) else { return }
        self.videoInput = input
        
        // output
        let output = AVCaptureVideoDataOutput()
        output.setSampleBufferDelegate(self, queue: DispatchQueue.global())
        self.videoOutput = output
        
        // add session
        session.beginConfiguration()
        if session.canAddInput(input) {
            session.addInput(input)
        }
        if session.canAddOutput(output) {
            session.addOutput(output)
        }
        session.commitConfiguration()
    }
   private func setupAudio() {
        // input
        guard let device = AVCaptureDevice.default(for: AVMediaType.audio) else { return }
        guard let input = try? AVCaptureDeviceInput(device: device) else { return }
    
        // output
        let output = AVCaptureAudioDataOutput()
        output.setSampleBufferDelegate(self, queue: DispatchQueue.global())
        
        // add session
        session.beginConfiguration()
        if session.canAddInput(input) {
            session.addInput(input)
        }
        if session.canAddOutput(output) {
            session.addOutput(output)
        }
        session.commitConfiguration()
    }

实时显示采集的画面,可以添加此预览图层
不添加该图层也可以正常采集

    private func setupPreviewLayer() {
        let preview = AVCaptureVideoPreviewLayer(session: session)
        preview.frame = view.bounds
        view.layer.insertSublayer(preview, at: 0)
        self.previewLayer = preview
    }

音频回调遵循AVCaptureAudioDataOutputSampleBufferDelegate
视屏回调遵循AVCaptureVideoDataOutputSampleBufferDelegate
注意: 音频回调方法和视屏回调方法是同一个方法

extension ViewController:  AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
       // 丢弃采集 
    }
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        // sampleBuffer 采集到的每一帧结果
        // 通过connection判断采集到的数据是视屏或音频信息
        if self.videoOutput?.connection(with: AVMediaType.video) == connection {
            print("采集到视屏")
        }else {
            print("采集到音频")
        }
    }
}

2、设置采集结果的保存

如果需要保存采集到的音视屏,可以添加此实例

    private func setupOutputFile () {
        if movieOutputFile != nil {
            session.removeOutput(movieOutputFile!)
        }
        
        let fileOutput = AVCaptureMovieFileOutput()
        let connection = fileOutput.connection(with: AVMediaType.video)
        connection?.automaticallyAdjustsVideoMirroring = true
        if session.canAddOutput(fileOutput) {
            session.addOutput(fileOutput)
        }
        self.movieOutputFile = fileOutput 
    }

使用计算属性

    private var urlPath: URL? {
        let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first! + "/video.mp4"
        
        return URL(fileURLWithPath: path)
    }
extension ViewController: AVCaptureFileOutputRecordingDelegate {
    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
        print("开始写入")
    }
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        print("结束写入")
    }
}

3、开始采集以及结束采集

    @IBAction func startCapture(_ sender: Any) {
         // 每次开始采集前, 设置预览图层
        setupPreviewLayer()
        
        // 开始录制,保存采集结果
        if let url = urlPath {
            self.movieOutputFile?.startRecording(to: url, recordingDelegate: self)
        }
        
        // 开始采集
        session.startRunning()
    }
    @IBAction func stopCapture(_ sender: Any) {
         // 结束录制
        self.movieOutputFile?.stopRecording()
        
        // 结束采集
        session.stopRunning()
        
        // 移出预览图层
        previewLayer?.removeFromSuperlayer()
    }

4、旋转采集摄像头

    @IBAction func rotateCamera(_ sender: Any) {
        guard let videoInput = videoInput else { return }
        // 前置 -> 后置, 后置 -> 前置
        let position: AVCaptureDevice.Position = videoInput.device.position == .front ? .back : .front
        
        // 输入源重新添加设备
        let devices = AVCaptureDevice.devices(for: AVMediaType.video)
        guard let device = devices.filter({$0.position == position }).first else { return }
        guard let input = try? AVCaptureDeviceInput(device: device) else { return }
        
        // session重新添加输入源
        session.beginConfiguration()
        session.removeInput(videoInput)
        if session.canAddInput(input) {
            session.addInput(input)
        }
        session.commitConfiguration()
        
        // 保存最新输入源
        self.videoInput = input
    }
上一篇下一篇

猜你喜欢

热点阅读