当前位置: 首页 > article >正文

深入解析 iOS 视频录制(一):录制管理核心MWRecordingController 类的设计与实现

深入解析 iOS 视频录制(一):录制管理核心MWRecordingController 类的设计与实现

深入解析iOS视频录制(二):自定义UI的实现

引言

在 iOS 应用开发中,视频录制功能越来越常见,尤其是在直播、短视频和社交应用中,用户经常需要录制高质量的视频内容。为了实现这个功能,我们不仅需要处理视频的输入和输出,还要控制摄像头的切换、录制的开始与结束,以及会话的管理等。而这些都需要通过一套清晰且高效的代码架构来实现。

在本系列博客中,我们将深入探讨如何实现 iOS 中的自定义视频录制功能。第一篇将重点介绍 MWRecordingController 类,它是整个视频录制管理的核心组件。我们将从它的设计原理、功能实现以及如何高效地管理录制会话入手,逐步揭开它在视频录制过程中的关键作用。

通过本篇博客的学习,您将能够更好地理解 iOS 视频录制的底层实现,并能在自己的项目中灵活地应用这些技术。

MWRecordingController 类的设计与实现

在自定义的视频录制功能中,MWRecordingController 类扮演着至关重要的角色。它是视频录制管理的核心,负责协调视频会话的启动与控制,确保录制过程的顺畅与高效。

MWRecordingController 类的作用与职责

具体来说,MWRecordingController 的主要职责包括:

  1. 管理录制会话的生命周期:MWRecordingController 类负责创建、启动和停止会话,确保视频录制从初始化到结束的整个过程可控。它为会话提供配置,控制录制的开始与停止,确保每一次录制都符合预期。
  2. 设置视频输入与输出:MWRecordingController还负责配置视频的输入源和输出目标。
  3. 切换摄像头:MWRecordingController 提供摄像头切换的功能,使用户能够在录制过程中自由选择前置或后置摄像头,增强录制体验。它确保每次切换都能快速且无缝地完成,以满足实时录制的需求。
  4. 录制控制:作为核心组件,MWRecordingController 控制着录制的开始与停止,确保视频文件的正确保存与后续处理。它负责处理录制过程中的状态变化,并通过回调通知外部应用,确保录制功能的顺利执行。
  5. 错误接结果的回调:MWRecordingController还负责将录制时产生的错误,及录制结果传递出去。

总结来说,MWRecordingController 类通过高效的会话管理、视频输入输出设置、摄像头控制及录制控制,承担了视频录制过程中的核心任务,是实现自定义视频录制功能的关键所在。

关键功能解析

接下来,我们将深入分析 MWRecordingController 类中的关键功能,从启动会话到停止录制的整个过程。通过这些功能的代码实现,我们能够更清楚地理解每个环节是如何协同工作,以确保视频录制的顺利进行。

1. 配置会话

在视频录制过程中,所有操作都依赖于 AVCaptureSession 实例。AVCaptureSession是 iOS 中用来协调视频和音频数据流的核心对象,它负责将输入设备(如摄像头、麦克风等)的数据与输出(如文件、屏幕显示等)进行连接。因此,第一步就是创建一个 AVCaptureSession 实例,并对其进行必要的配置。

    /// 视频录制会话
    private(set) var session: AVCaptureSession?
    /// 开始设置会话
    func setupSession() {
        session = AVCaptureSession()
        guard let session = session else {
            let error = NSError(domain: "com.mw.video", code: 0, userInfo: [NSLocalizedDescriptionKey: "创建会话失败"])
            delegate?.recordingController(self, didFailWithError: error)
            return
        }
        session.beginConfiguration()
        session.sessionPreset = .hd1280x720
        // 设置视频输入
        setupVideoInput()
        // 设置音频输入
        setupAudioInput()
        // 设置视频输出
        setupVideoOutput()
        session.commitConfiguration()
    }
  1. 创建一个AVCaptureSession的实例。
  2. 如果创建失败则直接回调出错误信息。
  3. 开启录制会话的配置。
  4. 设置录制的视频分辨率大小。
  5. 配置录制会话的视频输入。
  6. 配置录制会话的音频输入。
  7. 配置录制会话的视频输出。
  8. 提交录制会话配置。

2. 配置视频输入

配置视频输入是录制过程中至关重要的一步。视频输入源通常是设备的摄像头,iOS 提供了前置和后置摄像头可供选择。在这一过程中,我们需要确保选择正确的摄像头,并将其转换为 AVCaptureDeviceInput 以便能够将其添加到 AVCaptureSession 中。

    /// 摄像头
    private var camera: AVCaptureDevice?
    /// 视频输入
    private var videoInput: AVCaptureDeviceInput?
    /// 添加视频输入
    private func setupVideoInput(position:AVCaptureDevice.Position = .back) {
        // 默认获取后置
        guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: position) else {
            let error = NSError(domain: "com.mw.video", code: 0, userInfo: [NSLocalizedDescriptionKey: "获取摄像头失败"])
            delegate?.recordingController(self, didFailWithError: error)
            return
        }
        camera = device
        do {
            let input = try AVCaptureDeviceInput(device: device)
            videoInput = input
            if session?.canAddInput(input) == true {
                session?.addInput(input)
            }
        } catch {
            delegate?.recordingController(self, didFailWithError: error)
        }
    }
  1. 获取设备的视频输入源摄像头,默认为后置摄像头。
  2. 将AVCaptureDevice包装一层AVCaptureDeviceInput,并添加到AVCaptureSession中。
  3. 如果发生错误直接回调回对应的NSError。

3. 配置音频输入

视频录制时如果需要音频,那么我们就需要将音频输入也像视频一样配置上,步骤同上。

    /// 添加音频输入
    private func setupAudioInput() {
        guard let device = AVCaptureDevice.default(for: .audio) else {
            let error = NSError(domain: "com.mw.video", code: 0, userInfo: [NSLocalizedDescriptionKey: "获取麦克风失败"])
            delegate?.recordingController(self, didFailWithError: error)
            return
        }
        do {
            let input = try AVCaptureDeviceInput(device: device)
            if session?.canAddInput(input) == true {
                session?.addInput(input)
            }
        } catch {
            delegate?.recordingController(self, didFailWithError: error)
        }
    }
  1. 获取麦克风设备。
  2. 将AVCaptureDevice包装一层AVCaptureDeviceInput,并添加到AVCaptureSession中。
  3. 如果发生错误直接回调回对应的NSError。

4. 配置音视频输出

视频输出是录制过程中不可或缺的一部分,它决定了如何保存或处理录制的视频数据。在 iOS 中,我们通常使用AVCaptureMovieFileOutput 来输出录制的视频文件。它能够将视频流保存到指定的位置,通常是一个文件路径,之后可以进行播放或其他处理。

    /// 视频录制输出
    private var videoOutput: AVCaptureMovieFileOutput?
    /// 添加视频输出
    private func setupVideoOutput() {
        let output = AVCaptureMovieFileOutput()
        if session?.canAddOutput(output) == true {
            session?.addOutput(output)
            videoOutput = output
        } else {
            let error = NSError(domain: "com.mw.video", code: 0, userInfo: [NSLocalizedDescriptionKey: "添加视频输出失败"])
            delegate?.recordingController(self, didFailWithError: error)
        }
    }
  1. 使用AVCaptureMovieFileOutput会为我们直接生成录制好的音频数据,我们只需要设置数据存储路径。
  2. 创建音视频输出。
  3. 添加音视频输出。
  4. 如果发生错误直接回调回NSError。

5. 开启和停止会话

在进行视频和音频的采集之前,首先要做的就是启动会话,开启采集。

    /// 开始会话
    func startSession() {
        videoQueue.async {[weak self] in
            guard let self = self else { return }
            if self.session?.isRunning == false {
                self.session?.startRunning()
            }
        }
    }

当不需要使用时,手动调用结束会话。

    /// 停止会话
    func stopSession() {
        videoQueue.async {[weak self] in
            guard let self = self else { return }
            if self.session?.isRunning == true {
                self.session?.stopRunning()
            }
        }
    }

6. 开启录制结束录制

一切准备就绪之后,我们就可以使用视频的输出调用开始录制方法,同时设置视频的输出地址,以及代理。

    /// 开始录制
    func startRecording() {
        if isRecording {
            return
        }
        videoQueue.async {[weak self] in
            guard let self = self else { return }
            let videoConnection = self.videoOutput?.connection(with: .video)
            self.videoOutput?.startRecording(to: self.outputFileURL(), recordingDelegate: self)
        }
    }
    /// 结束录制
    func stopRecording() {
        if isRecording == false {
            return
        }
        videoQueue.async {[weak self] in
            guard let self = self else { return }
            self.videoOutput?.stopRecording()
        }
    }

7. 完成回调

录制完成之后,我们在AVCaptureFileOutputRecordingDelegate的协议方法中,可以直接获取到录制的视频地址URL,或者录制报错的错误信息。

    //MARK: - 结束录制
    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: (any Error)?) {
        
        if let error = error {
            delegate?.recordingController(self, didFailWithError: error)
        } else {
            delegate?.recordingController(self, didFinishRecordingTo: outputFileURL)
        }
    }

8. 切换摄像头

在进行切换前,首先设置会话状态为开始配置,然后移除当前的输入设备,获取新的输入设备并添加,提交新的配置。

    /// 切换摄像头
    func switchCamera() {
        guard let session = session else {
            return
        }
        session.beginConfiguration()
        // 移除输入
        if let videoInput = videoInput {
            session.removeInput(videoInput)
        }
        // 切换摄像头
        if camera?.position == .back {
            setupVideoInput(position: .front)
        } else {
            setupVideoInput(position: .back)
        }
        session.commitConfiguration()
    }
  1. 开启会话配置。
  2. 移除原来的视频输出。
  3. 设置新的视频输入。
  4. 移交配置。

9. 定义代理

为了将结果和错误信息回调到调用的对象中,我们定义了一个 MWRecordingControllerDelegate 的代理,主要包含了录制发生错误的回调,以及录制完成的回调。

protocol MWRecordingControllerDelegate: AnyObject {
    /// 录制发生错误
    func recordingController(_ controller: MWRecordingController, didFailWithError error: Error)
    /// 录制完成
    func recordingController(_ controller: MWRecordingController, didFinishRecordingTo outputFileURL: URL)
   
}

结语

通过本篇博客,我们深入解析了 MWRecordingController 类在 iOS 视频录制中的核心作用,详细介绍了如何配置会话、设置视频输入输出,以及录制控制的实现。这些技术为实现高效的视频录制功能奠定了基础。希望通过本篇的分享,能够帮助大家更好地理解视频录制的底层实现,为自己项目中的视频录制功能提供参考与帮助。在接下来的博客中,我们将继续探索其他优化与扩展的技术,敬请期待!


http://www.kler.cn/a/550303.html

相关文章:

  • Java基于 SpringBoot+Vue的微信小程序跑腿平台V2.0(附源码,文档)
  • Fisco-Bcos单群组区块链部署
  • 浏览器跨标签页通信
  • 【火星】火星 数字地面模型(DEM)数字正射影像(DOM)下载
  • POI 和 EasyExcel
  • Hadoop基本介绍
  • 【信息学奥赛一本通 C++题解】1285:最大上升子序列和
  • 数据结构(查找)
  • 浅析 vue里的全局指令文件 directives
  • 第1章大型互联网公司的基础架构——1.3 HTTP-DNS
  • 大模型知识蒸馏:解析原理、谈DeepSeek及服务器适配思路
  • 宝藏软件系列 篇一:My APK(Android)
  • Copilot:Excel中的Python高级分析来了
  • 青少年编程与数学 02-009 Django 5 Web 编程 19课题、RESTful API开发
  • C语言基础16:二维数组、字符数组
  • Mac本地部署deepseek
  • uv 简易安装与更换国内镜像源
  • 网页制作02-html,css,javascript初认识のhtml的文字与段落标记
  • Groovy语言的学习路线
  • Leetcode 227-基本计算器 II