美文网首页
音频视频采集Swift

音频视频采集Swift

作者: br_MorningStar | 来源:发表于2017-11-28 23:51 被阅读179次

视频采集
音频采集
AVCaptureVideoPreviewLayer
本地存储
切换摄像头

1.创建捕获会话AVCaptureSession

    fileprivate lazy var session : AVCaptureSession = AVCaptureSession()
//其他属性
    fileprivate var videoOutpu : AVCaptureVideoDataOutput?
    fileprivate var videoInout : AVCaptureDeviceInput?
    fileprivate var previewLayer : AVCaptureVideoPreviewLayer?
    fileprivate var movieOutput : AVCaptureMovieFileOutput?

2.初始化视频输入和输出
①获取设备device
②获取设备上的输入流Input,并保存
③获取输出流output
④输出流设置代理
⑤Session会话中添加输入流和输出流

fileprivate func setupVideoInputOutout(){
        //添加视频的输入
        
        /*
         let device = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera, for: AVMediaType.video, position: .front)
    */
        
        let devices = AVCaptureDevice.devices()
        guard let device =  devices.filter({ $0.position == .back }).first else { return }
        guard let input = try? AVCaptureDeviceInput(device: device) else { return }
        self.videoInout = input
        
        //添加视频的输出
        let output = AVCaptureVideoDataOutput()
        let queue = DispatchQueue.global()
        output.setSampleBufferDelegate(self, queue: queue)
        self.videoOutpu = output
        
        //添加输入&输出
        addInputAndOutpuSession(input, output)
    }

3.初始化音频输入和输出流
①获取设备
②获取输入流
③获取输出流,并设置代理
④在会话中添加Session

fileprivate func setupAudioInputOutout(){
        
        //创建输入
        guard let device = AVCaptureDevice.default(for: .audio) else { return }
        guard let input = try?  AVCaptureDeviceInput(device: device) else { return }
        
        //创建输出
        let output = AVCaptureAudioDataOutput()
        let queue = DispatchQueue.global()
        output.setSampleBufferDelegate(self, queue: queue)
        
        //添加输入&输出
        addInputAndOutpuSession(input, output)
    }

添加输入输出流

//添加 输入 输出
    private func addInputAndOutpuSession(_ input : AVCaptureInput, _ output : AVCaptureOutput){
        //添加输入 & 输出
        session.beginConfiguration()
        if session.canAddInput(input){
            session.addInput(input)
        }
        if session.canAddOutput(output){
            session.addOutput(output)
        }
        session.commitConfiguration()
    }

④添加预览

fileprivate func setupPreviewLayer (){
        //1 创建预览图层
        previewLayer = AVCaptureVideoPreviewLayer(session: session)
        
        //2设置 preview属性
        previewLayer?.frame = view.bounds
        //3将图层添加到控制器的View的Layer 中
        view.layer.insertSublayer(previewLayer!, at: 0)
        
        
    }

⑤代理方法

// MARK: - AVCaptureVideoDataOutputSampleBufferDelegate -- AVCaptureAudioDataOutputSampleBufferDelegate 同一个方法
extension ViewController : AVCaptureVideoDataOutputSampleBufferDelegate , AVCaptureAudioDataOutputSampleBufferDelegate{
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        if videoOutpu?.connection(with: .video) == connection {
            print("采集到一针画面\(Thread.current)")
            
        }else {
            print("音频数据")
        }
    }
}

⑥切换摄像头
获取之前的VideoInput,创建新的Input,切换AVCaptureDevice.Position ,切换Input

@IBAction func changeCamera(_ sender: UIButton) {
        //取出之前镜头的方向
        guard let videoInput = videoInout else { return }
        let postion : AVCaptureDevice.Position = videoInput.device.position == .front ? .back : .front
        
        let devices = AVCaptureDevice.devices()
        guard let device =  devices.filter({ $0.position == postion }).first else { return }
        guard let newInput = try? AVCaptureDeviceInput(device: device) else { return }
        
        //移除之前的Input 添加新的Input
        session.beginConfiguration()
        session.removeInput(videoInput)
        if session.canAddInput(newInput){
            session.addInput(newInput)
        }
        session.commitConfiguration()
        
        //保存最新的Input
        self.videoInout = newInput
    }

⑦写入本地
获取AVCaptureMovieFileOutput,并保存

写入是主线程!不知道有没有方法可以解决卡顿

 //写入文件
    fileprivate func setupMoveFileOutput(){
        
        if (self.movieOutput != nil) {
            session.removeOutput(movieOutput!)
        }
        
        
        
        //1创建写入文件的输出
        let fileOutput = AVCaptureMovieFileOutput()
        self.movieOutput = fileOutput
        
        //必须设置
        let connection = fileOutput.connection(with: AVMediaType.video)
        connection?.automaticallyAdjustsVideoMirroring = true
        if session.canAddOutput(fileOutput) {
            session.addOutput(fileOutput)
        }
        
        //2直接开始写入文件
        let filePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/abc.mp4"
        let fileURL = URL(fileURLWithPath: filePath)
        fileOutput.startRecording(to: fileURL, recordingDelegate: self)
        
    }

代理是在主线程调度的

extension ViewController : AVCaptureFileOutputRecordingDelegate{
    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
        print("开始写入文件\(Thread.current)")
    }
    
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        print("完成写入文件\(Thread.current)")
    }
    
    
}

开和暂停

 @IBAction func startCaptuer(_ sender: UIButton) {
        
        session.startRunning()
        
//        setupPreviewLayer()
        previewLayer?.isHidden = false
        
        //录制写入文件
        self.setupMoveFileOutput()
    }
    
    @IBAction func stopCaptuer(_ sender: UIButton) {
        //先停止输入
        movieOutput?.stopRecording()
        
        session.stopRunning()
        
        previewLayer?.isHidden = true
    }

https://github.com/BRburen/shipincaiji.git

相关文章

网友评论

      本文标题:音频视频采集Swift

      本文链接:https://www.haomeiwen.com/subject/jbyybxtx.html