iOS利用AVFoundation实现视频音频的输入&输出,切换摄像头并保存

原创 2018年04月17日 09:45:17

iOS中AVFoundation是一个专门的音频,视频处理库,很强大的一个库,配合GPUImage能够实现很多音视频和图片的处理,如:美颜效果等等

采集步骤

采集步骤文字描述

  • 导入框架
    • 相关API主要在AVFoundation框架中,因此需要先导入框架
  • 创建捕捉会话(AVCaptureSession)
    • 该会话用于连接之后的输入源&输出源
    • 输入源:摄像头&话筒
    • 输出源:拿到对应的音频&视频数据的出口
    • 会话:用于将输入源&输出源连接起来
  • 设置视频输入源&输出源
    • 输入源(AVCaptureDeviceInput):从摄像头输入
    • 输出源(AVCaptureVideoDataOutput):可以设置代理,在代理方法中拿到数据
    • 将输入&输出添加到会话中
  • 设置音频输入源&输出源
    • 输入源(AVCaptureDeviceInput):从话筒输入
    • 输出源(AVCaptureAudioDataOutput):可以设置代理,在代理方法中拿到数据
    • 将输入&输出添加到会话中
  • 添加预览图层(可选)
    • 如果希望用户看到采集的画面,可以添加预览图层
    • 该预览图层不是必须的,及时没有添加也可以正常采集数据
  • 开始采集即可
    • 调用会话(AVCaptureSession)的startRunning方法即可开始采集
现在记录下它的使用,为了方便看,下面把整个控制器的代码贴出来(使用Swift4):
import UIKit
import AVFoundation

class ViewController: UIViewController {
    
    fileprivate lazy var session: AVCaptureSession = AVCaptureSession()
    fileprivate var videoOutput: AVCaptureVideoDataOutput?
    fileprivate var videoInput: AVCaptureDeviceInput?
    fileprivate var previewLayer: AVCaptureVideoPreviewLayer?
    fileprivate var movieOutput: AVCaptureMovieFileOutput?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 初始化视频的输入&输出
        setupVideoInputOutput()
        
        // 初始化音频的输入&输出
        setupAudioInputOutput()
    }
    
    // 开始采集音视频
    @IBAction func startCapturing(_ sender: UIButton) {
        
        // 初始化一个预览图层
        setupPreviewLayer()
        session.startRunning()
        
        // 录制视频, 并且写入文件
        setupMovieFileOutput()
    }
    
    // 停止录制
    @IBAction func stopCapturing(_ sender: UIButton) {
        session.stopRunning()
        movieOutput?.stopRecording()
        previewLayer?.removeFromSuperlayer()
    }
    
    
    // 切换摄像头
    @IBAction func switchCamera(_ sender: UIButton) {
        
        // 取出之前镜头的方向
        guard let videoInput = self.videoInput else { return }
        let position: AVCaptureDevice.Position = videoInput.device.position == AVCaptureDevice.Position.front ? .back : .front
        let devices = AVCaptureDevice.devices()
        guard let device = devices.filter({ $0.position == position}).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.videoInput = newInput
    }
}

// MARK:- 初始化方法
extension ViewController {
    // 初始化视频的输入输出
    fileprivate func setupVideoInputOutput() {
        // 添加视频的输入
        let devices = AVCaptureDevice.devices()
        guard let device = devices.filter({ $0.position == .front }).first else { return }
        guard let input = try? AVCaptureDeviceInput(device: device) else { return }
        videoInput = input
        
        // 添加视频的输出
        let output = AVCaptureVideoDataOutput()
        let queue = DispatchQueue.global()
        output.setSampleBufferDelegate(self, queue: queue)
        videoOutput = output
        
        // 添加输入输出
        session.beginConfiguration()
        if session.canAddInput(input) {
            session.addInput(input)
        }
        
        if session.canAddOutput(output) {
            session.addOutput(output)
        }
        
        session.commitConfiguration()
    }
    
    // 初始化音频的输入输出
    fileprivate func setupAudioInputOutput() {
        // 添加音频的输入
        guard let device = AVCaptureDevice.default(for: AVMediaType.audio) else { return }
        guard let input = try? AVCaptureDeviceInput(device: device) else { return }
        
        // 创建输出
        let output = AVCaptureAudioDataOutput()
        let queue = DispatchQueue.global()
        output.setSampleBufferDelegate(self, queue: queue)
        
        //添加输入&输出
        session.beginConfiguration()
        if session.canAddOutput(output) {
            session.addOutput(output)
        }
        
        if session.canAddInput(input) {
            session.addInput(input)
        }
        session.commitConfiguration()
    }
    
    // 初始化预览层
    fileprivate func setupPreviewLayer() {
        // 创建预览图层
        let previewLayer = AVCaptureVideoPreviewLayer(session: session)
        
        // 设置previewLayer属性
        previewLayer.frame = view.bounds
        
        // 图层添加到控制器的View的layer中
        view.layer.insertSublayer(previewLayer, at: 0)
        self.previewLayer = previewLayer
    }
    
    // 录制视频, 并且写入文件
    fileprivate func setupMovieFileOutput() {
        
        if let output = movieOutput {
            session.removeOutput(output)
        }
        
        // 创建写入文件的输出
        let fileOutput = AVCaptureMovieFileOutput()
        movieOutput = fileOutput
        
        let connection = fileOutput.connection(with: .video)
        connection?.automaticallyAdjustsVideoMirroring = true
        
        session.beginConfiguration()
        if session.canAddOutput(fileOutput) {
            session.addOutput(fileOutput)
        }
        session.commitConfiguration()
        
        // 直接开始写入文件
        let filePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! + "/video.mp4"
        let fileUrl = URL(fileURLWithPath: filePath)
        fileOutput.startRecording(to: fileUrl, recordingDelegate: self)
    }
}

// MARK:- <AVCaptureVideoDataOutputSampleBufferDelegate>
extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAudioDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        if videoOutput?.connection(with: AVMediaType.video) == connection {
            print("采集视频数据")
        } else {
            print("采集音频数据")
        }
    }
}

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("完成写入文件")
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24904667/article/details/79970154

通过AVFoundation框架获取摄像头数据

一、概述 从iOS4开始,AVFoundation框架增加了几个类,AVCaptureDevice、AVCaptureSession等,可以获取摄像头的数据,而不会弹出类似于Imag...
  • jingcheng345413
  • jingcheng345413
  • 2017-02-10 14:10:32
  • 1463

iOS AVFoundation实现相机功能

首先导入头文件 #import  导入头文件后创建几个相机必须实现的对象 /** * AVCaptureSession对象来执行输入设备和输出设备之间的数据传递 */...
  • qq_33140415
  • qq_33140415
  • 2016-05-04 09:53:28
  • 1234

iOS实现切换摄像头

前言(2018.3.1更新)hihi 我来更新了,这边博客下面有个小哥哥说用了不好用,今天又有一位程序员朋友加我微信问这个问题,抽了5分钟做了个Demo在github上摄像头翻转,供大家参考,省的大家...
  • u012265444
  • u012265444
  • 2016-06-20 22:43:19
  • 3238

ios开发之设备前后摄像头切换

#import   // Switching between front and back cameras   - (AVCaptureDevice *)cameraWithPosition...
  • wudidalishi
  • wudidalishi
  • 2012-09-28 09:15:41
  • 11938

iOS 开发AVFoundation系统原生二维码扫描实现

iOS 开发AVFoundation系统原生二维码扫描实现
  • u010328250
  • u010328250
  • 2015-05-12 14:36:12
  • 628

AVfoundation中焦距的设置(slider实现拉近拉远镜头)

首先设置一个slider UISlider focusSlider = [[UISlider alloc]initWithFrame:CGRectMake(60, _bottomView.fram...
  • u013089311
  • u013089311
  • 2014-01-02 15:51:19
  • 4054

iOS开发进阶 - 用AVFoundation自定义视频录制功能

系统自带的录制视频的功能显然无法项目的要求,自定义视频录制就非常重要了,那么下面来带大家制作属于自己的视频录制界面。主要使用AVFoundation和CoreMedia框架.....
  • wang631106979
  • wang631106979
  • 2016-05-25 14:13:18
  • 20685

iOS 原生AVFoundation 限制区域二维码扫描

1.导入AVFoundation/AVFoundation.h框架 2.在初始化时 定义imageView 作为自定义的现实区域 3.绘制遮盖层 可视区域之外的部分 半透明的遮盖  默认扫描二维码...
  • wangxiaoertedaye
  • wangxiaoertedaye
  • 2016-02-02 17:53:37
  • 1071

iOS 视频AVFoundation使用

iOS9弃用了MPMoviePlayerViewController 使用了AVPlayerViewViewController 框架 其中: 1.AVPlayer 播放音视频 2.AVPlay...
  • f9635214
  • f9635214
  • 2016-07-21 15:51:50
  • 1059

iOS 拍摄照片,使用视听媒体框架AVFoundation实现照片拍摄 —— HERO博客

用AVFoundation实现照片拍摄。
  • hero_wqb
  • hero_wqb
  • 2017-08-27 15:56:45
  • 342
收藏助手
不良信息举报
您举报文章:iOS利用AVFoundation实现视频音频的输入&amp;输出,切换摄像头并保存
举报原因:
原因补充:

(最多只允许输入30个字)