深入解析 iOS 視頻錄制(三):完整錄制流程的實現與整合

深入解析 iOS 視頻錄制(一):錄制管理核心MWRecordingController 類的設計與實現

深入解析iOS視頻錄制(二):自定義UI的實現???????

深入解析 iOS 視頻錄制(三):完整錄制流程的實現與整合

引言

在之前的兩篇博客中,我們詳細探討了如何實現 iOS 視頻錄制功能的核心部分。第一篇博客《深入解析 iOS 視頻錄制(一):錄制管理核心MWRecordingController 類的設計與實現》介紹了如何設計并實現一個錄制管理類MWRecordingController,該類負責管理視頻錄制的核心功能,包括啟動會話、設置輸入輸出、切換攝像頭以及控制錄制的開始與停止。第二篇《深入解析 iOS 視頻錄制(二):自定義 UI 的實現》中,我們詳細探討了如何通過自定義 UI 提供更流暢的用戶體驗,包括錄制按鈕、預覽視圖、控制視圖等組件的實現與布局。

本篇博客將以這些基礎為依托,重點講解如何在一個 ViewController?中實現完整的視頻錄制流程。我們將把前兩篇博客中的內容整合,展示如何在單一視圖控制器中實現從視頻預覽到錄制控制、從開始錄制到保存視頻文件的全過程。通過這篇博客,你將了解如何將這些不同模塊融合成一個完整、可交互的視頻錄制應用。

希望通過這篇博客,你能深入理解如何實現一個簡單而強大的視頻錄制功能,并為未來的應用開發打下堅實的基礎。

準備工作

在開始實現視頻錄制功能之前,我們需要做好一些必要的準備工作。確保項目配置正確,依賴庫安裝完畢,以及設備權限已正確設置,才能順利進行開發和測試。

項目設置與依賴

首先,確保你的 Xcode 項目已經設置好并配置了正確的依賴項。在本項目中,我們主要依賴 AVFoundation 框架來實現視頻錄制功能。

import AVFoundation

配置 Info.plist 權限請求

iOS 中,應用訪問設備的硬件(如攝像頭和麥克風)時需要請求響應的權限。為了確保應用能順利進行示例錄制,我們需要在 Info.plist 文件中添加以下權限描述:

<key>NSCameraUsageDescription</key>
<string>需要訪問攝像頭來進行視頻錄制</string>
<key>NSMicrophoneUsageDescription</key>
<string>需要訪問麥克風來錄制音頻</string>

這些描述會在應用首次請求權限時,向用戶展示權限請求彈窗。確保根據你應用的功能,調整描述內容,提供清晰且易懂的理由,以提升用戶體驗。

設備要求與測試

為了保證視頻錄制功能能夠順利運行,請確保測試設備支持攝像頭和麥克風,在模擬器中一般無法使用真實攝像頭進行錄制,因此必須使用真實設備進行開發和調試。

錄制完整流程代碼實現

在這一部分,我們將會結合代碼一步一步實現錄制視頻的完整流程。

錄制管理與UI組件集成

MWRecordingViewController是本次實現的核心視圖控制,它將 MWRecordingController 作為錄制的核心控制器,并通過自定義的視圖組件(如MWRecordingPreview、MWRecordingControlView、MWRecordingNavgationView)構建了一個完成的視頻錄制界面。

MWRecordingController

錄制控制器(MWRecordingController):負責啟動會話、開始和停止錄制、切換攝像頭。

    /// 錄制控制器private let recordingController = MWRecordingController()
  public override func viewDidLoad() {super.viewDidLoad()setupRecording()addPreviewView()addNavgationView()addControlView()}private func setupRecording() {recordingController.recordingSource = self.recordingSource// 設置recordingController.setupSession()// 開始會話recordingController.startSession()recordingController.delegate = self}

MWRecordingPreview

預覽視圖(MWRecordingPreview):負責展示視頻錄制過程中的實時畫面。

    /// 預覽視圖private let previewView = MWRecordingPreview()

MWRecordingControlView

控制器視圖(MWRecordingControlView):提供開始/暫停錄制、重新錄制、完成錄制等按鈕。

    /// 底部控制視圖private let controlView = MWRecordingControlView()
    // 控制視圖private func addControlView() {self.view.addSubview(controlView)controlView.snp.makeConstraints { make inmake.leading.trailing.equalToSuperview()make.height.equalTo(103.0)make.bottom.equalToSuperview().offset(-MW_BOTTOM_SAFE_HEIGHT - 14.0)}// 開始/暫停 錄制controlView.recordButtonClickBlock = { [weak self] inguard let self = self else { return }....}// 重新錄制controlView.reRecordButtonClickBlock = { [weak self] inguard let self = self else { return }.....}// 完成controlView.finishButtonClickBlock = { [weak self] inguard let self = self else { return }...}}

MWRecordingNavgationView

導航欄(MWRecordingNavgationView):提供切換攝像頭和返回的按鈕。

  /// 導航欄private let navgationView = MWRecordingNavgationView()
   // 導航private func addNavgationView() {self.view.addSubview(navgationView)navgationView.snp.makeConstraints { make inmake.top.equalToSuperview().offset(MW_TOP_SAFE_HEIGHT)make.leading.trailing.equalToSuperview()make.height.equalTo(56.0)}// 返回navgationView.backButtonClickBlock = { [weak self] inguard let self = self else { return }self.exit()}// 切換攝像頭navgationView.switchCameraButtonClickBlock = { [weak self] inguard let self = self else { return }self.recordingController.switchCamera()}}

實現錄制的核心邏輯

在這一部分將會重點講解如何在MWRecordingViewController中實現視頻錄制的核心功能,就是UI組件與用操作的交互,以及UI組件與錄制核心類MWRecordingController的交互。

在創建MWRecordingController時,我們已經設置并啟動了會話,那么第一步我們來實現控制視圖的開始/暫停錄制的功能,在MWRecordingControlView中我們創建了多個閉包。

錄制/暫停

其中recordButtonClickBlock負責回調中間錄制/暫停按鈕的事件。

        // 開始/暫停 錄制controlView.recordButtonClickBlock = { [weak self] inguard let self = self else { return }if self.recordingState == .normal {// 正常狀態 開始錄制self.recordingState = .recordingself.recordingController.startRecording()} else if self.recordingState == .recording {// 錄制狀態 暫停self.recordingState = .finishself.recordingController.stopRecording()} else if self.recordingState == .finish {// 完成狀態 重新錄制self.recordingState = .recordingself.recordingController.startRecording()}if self.recordingState == .recording {self.currentDuration = 0self.startTimer()} else {self.stopTimer()}// 隱藏/顯示 切換按鈕self.navgationView.isHiddenSwitchCameraButton = self.recordingState != .normalself.controlView.setRecordingState(state: self.recordingState)}

該按鈕的點擊事件會根據當前的狀態來執行不同的操作。

  1. normal:當狀態為normal,調用MWRecordingController的開始錄制startRecording()方法,并修改狀態為recording。
  2. recording:當狀態為recording,調用MWRecordingController的結束錄制stopRecording()方法,并修改狀態為finish。
  3. finish:當狀態為finish時,直接重新錄制,調用開始錄制方法。
  4. 切換狀態后,如果狀態為recording,重新開啟定時器,定時讀取錄制時長,否則停止定時器。
  5. 根據切換后的狀態,更新MWRecordingControlView以及MWRecordingNavgationView視圖的狀態。

重新錄制

點擊重新錄制按鈕,直接切換狀態為錄制狀態,并執行開始錄制,啟動定時器開始讀取錄制時長。

        // 重新錄制controlView.reRecordButtonClickBlock = { [weak self] inguard let self = self else { return }self.stopPlay()self.recordingState = .recordingself.controlView.setRecordingState(state: self.recordingState)self.recordingController.startRecording()self.startTimer()}

完成事件

點擊完成事件,首先判斷錄制時長是否符合要求,然后將錄制視頻的URL傳遞回調用的視圖控制器,并隱藏當前錄制的視圖控制器。

        // 完成controlView.finishButtonClickBlock = { [weak self] inguard let self = self else { return }// 判斷時長if self.currentDuration < self.minDuration {MWToast.showToast("Video at least \(self.minDuration) seconds")return}self.recordingCompletionHandler?(self.coverImage,self.videoURL)self.exit()}

錄制的代理

在MWRecordingController中我們定義了兩個代理方法,用于回調錄制的錯誤信息以及錄制完成的視頻地址。

    //MARK: MWRecordingControllerDelegate/// 錄制報錯func recordingController(_ controller: MWRecordingController, didFailWithError error: any Error) {let image = UIImage(named: "login_toast_left_icon")MWToast.showTopToast(error.localizedDescription, icon: image)}/// 錄制完成func recordingController(_ controller: MWRecordingController, didFinishRecordingTo outputFileURL: URL) {videoURL = outputFileURLlet image = generateCoverImage()coverImage = imageif currentDuration < minDuration {MWToast.showToast("Video at least \(minDuration) seconds")return}}
  1. 錯誤信息直接顯示Toast。
  2. 錄制完成后,根據視頻地址讀取視頻封面。

計時器

開啟和關閉計時器,在定時事件中更新錄制時長,如果達到錄制的最大時長自動結束錄制。

    /// 開啟定時器private func startTimer() {if timer != nil {return}MWLogHelper.debug("開啟定時器", context: "MWRecordingViewController")timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true)}/// 結束定時器private func stopTimer() {MWLogHelper.debug("結束定時器", context: "MWRecordingViewController")timer?.invalidate()timer = nil}/// 定時器事件@objc private func timerAction() {// 讀取錄制時長let duration = recordingController.durationcurrentDuration = CMTimeGetSeconds(duration)if currentDuration >= maxDuration {// 結束錄制recordingController.stopRecording()recordingState = .finishcontrolView.setRecordingState(state: recordingState)stopTimer()} else {controlView.updateTime(time: currentDuration)}}

結語

在本篇博客中,我們詳細介紹了如何在 ViewController?中實現完整的 iOS 視頻錄制功能。通過整合之前討論的錄制管理核心 MWRecordingController?和自定義的 UI 組件,我們構建了一個可交互的視頻錄制界面,涵蓋了錄制的各個方面:從視頻預覽、錄制控制到視頻保存與封面生成,提供了一個完整且流暢的用戶體驗。

通過這次實現,大家可以了解到如何使用 AVFoundation?框架來處理視頻錄制,同時也掌握了如何結合自定義 UI 和交互設計,提升應用的易用性與功能性。

在未來,視頻錄制功能的擴展性非常強,可以根據需求加入更多的特性,如視頻特效、實時濾鏡、錄制過程中的實時預覽調整等。隨著技術的不斷發展,如何優化視頻錄制的性能、降低資源消耗、提高錄制質量等,仍然是值得我們不斷探索的方向。

希望本系列博客能夠幫助你更好地理解 iOS 視頻錄制的實現方式,也期待你能將這些知識應用到自己的項目中,打造出更豐富、更有趣的用戶體驗!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/71404.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/71404.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/71404.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于豆瓣2025電影數據可視化分析系統的設計與實現

??本項目旨在通過對豆瓣電影數據進行綜合分析與可視化展示&#xff0c;構建一個基于Python的大數據可視化系統。通過數據爬取收集、清洗、分析豆瓣電影數據&#xff0c;我們提供了一個全面的電影信息平臺&#xff0c;為用戶提供深入了解電影產業趨勢、影片評價與演員表現的工…

tcp協議連接,和傳輸數據

1、連接 這個是通用的 2、傳送數據 當連接建立后&#xff0c;客戶端和服務器都可以主動發送數據&#xff0c;分別如下 1》客戶端先發送數據 這里是單向的&#xff0c;服務器沒有對客戶端的數據內容進行應答&#xff0c;只是單純的對報文應答ack 2》服務器先發送數據

2024年國賽高教杯數學建模C題農作物的種植策略解題全過程文檔及程序

2024年國賽高教杯數學建模 C題 農作物的種植策略 原題再現 根據鄉村的實際情況&#xff0c;充分利用有限的耕地資源&#xff0c;因地制宜&#xff0c;發展有機種植產業&#xff0c;對鄉村經濟的可持續發展具有重要的現實意義。選擇適宜的農作物&#xff0c;優化種植策略&…

鴻蒙開發:V2版本裝飾器之@Monitor裝飾器

前言 本文代碼案例基于Api13。 隨著官方的迭代&#xff0c;在新的Api中&#xff0c;對于新的應用開發&#xff0c;官方已經建議直接使用V2所屬的裝飾器進行開發了&#xff0c;所以&#xff0c;能上手V2的盡量上手V2吧&#xff0c;畢竟&#xff0c;V2是V1的增強版本&#xff0c;…

國產編輯器EverEdit - 獨門暗器:自動監視剪貼板內容

1 監視剪貼板 1.1 應用場景 如果需要對剪貼板的所有歷史進行記錄&#xff0c;并進行分析和回顧&#xff0c;則可以使用監視剪貼板功能&#xff0c;不僅在EverEdit中的復制會記錄&#xff0c;在其他應用的復制也會記錄。 1.2 使用方法 新建一個空文檔(重要&#xff1a;防止擾亂…

pdf轉換成word在線 簡單好用 支持批量轉換 效率高 100%還原

pdf轉換成word在線 簡單好用 支持批量轉換 效率高 100%還原 在數字化辦公的浪潮中&#xff0c;文檔格式轉換常常讓人頭疼不已&#xff0c;尤其是 PDF 轉 Word 的需求極為常見。PDF 格式雖然方便閱讀和傳輸&#xff0c;但難以編輯&#xff0c;而 Word 格式卻能靈活地進行內容修…

深入探索C語言中的字符串處理函數:strstr與strtok

在C語言的字符串處理領域&#xff0c; strstr 和 strtok 是兩個非常重要的函數&#xff0c;它們各自承擔著獨特的功能&#xff0c;為開發者處理字符串提供了強大的支持。 一、strstr函數&#xff1a;字符串查找的利器 strstr 函數用于在一個字符串中查找另一個字符串的首次出現…

AIGC(生成式AI)試用 21 -- Python調用deepseek API

1. 安裝openai pip3 install openai########################## Collecting openaiUsing cached openai-1.61.1-py3-none-any.whl.metadata (27 kB) Collecting anyio<5,>3.5.0 (from openai)Using cached anyio-4.8.0-py3-none-any.whl.metadata (4.6 kB) Collecting d…

關于使用雪花算法生成唯一ID,返回給前端ID不一致的問題

問題 在某個項目中,使用雪花算法生成的唯一ID,從數據庫查詢到數據后返回給前端,但是前端接受到的數據ID和數據庫原先生成的不一致 但是前端展示的數據: 原因 原因是后端使用Long類型來存儲雪花算法生成的ID,但是這個數值已經超過前端數值類型的范圍,導致前端在存儲這個數值…

Windows 啟動 SSH 服務

Windows 啟動 SSH 服務 一、OpenSSH Server 安裝 以 Win10 系統為例 打開設置 -> 系統 -> 可選功能 在 添加的功能 查看是否安裝了 OpenSSH 服務 或者 OpenSSH Server 如果沒有安裝&#xff0c;找到 系統->添加可選功能 -> 查看功能->搜索 OpenSSH 服務 ->…

C#功能測試

List 內部元素為引用 src[0]為"11" List<Source> src new List<Source>(); src.Add(new Source() { Name "1", Age 1, Description "1" }); src.Add(new Source() { Name "2", Age 2, Description "2"…

大數據SQL調優專題——Flink執行原理

引入 上一篇我們了解了Spark&#xff0c;相比起MapReduce來說&#xff0c;它確實已經快了超級多了&#xff0c;但是人類的欲望是沒有止境的&#xff0c;這也是推動人類進步的動力。 Flink就是為了滿足實時響應的場景需求誕生的。 其實在Flink之前&#xff0c;實時處理其實已…

計算機視覺:神經網絡實戰之手勢識別(附代碼)

第一章&#xff1a;計算機視覺中圖像的基礎認知 第二章&#xff1a;計算機視覺&#xff1a;卷積神經網絡(CNN)基本概念(一) 第三章&#xff1a;計算機視覺&#xff1a;卷積神經網絡(CNN)基本概念(二) 第四章&#xff1a;搭建一個經典的LeNet5神經網絡(附代碼) 第五章&#xff1…

win11安裝wsl報錯:無法解析服務器的名稱或地址(啟用wsl2)

1. 啟用wsl報錯如下 # 查看可安裝的 wsl --install wsl --list --online此原因是因為沒有開啟DNS的原因&#xff0c;所以需要我們手動開啟DNS。 2. 按照如下配置即可 Google的DNS&#xff08;8.8.8.8和8.8.4.4) 全國通用DNS地址 (114.114.114.114) 3. 運行以下命令來重啟 WSL…

開源模型應用落地-DeepSeek-R1-Distill-Qwen-7B-LoRA微調-LLaMA-Factory-單機單卡-V100(一)

一、前言 如今&#xff0c;大語言模型領域熱鬧非凡&#xff0c;各種模型不斷涌現。DeepSeek-R1-Distill-Qwen-7B 模型憑借其出色的效果和性能&#xff0c;吸引了眾多開發者的目光。而 LLaMa-Factory 作為強大的微調工具&#xff0c;能讓模型更好地滿足個性化需求。 在本篇中&am…

k8s-對接NFS存儲

一、前提條件 1、NFS_Server 部署好了。 2、網絡可達。 二、 使用方式 1、CSI **項目地址 https://github.com/kubernetes-csi/csi-driver-nfs#readme Install NFS CSI driver v4.10.0 version on a kubernetes cluster If you have already installed Helm, you can a…

【動態路由】系統Web URL資源整合系列(后端技術實現)【nodejs實現】

需求說明 軟件功能需求&#xff1a;反向代理功能&#xff08;描述&#xff1a;apollo、eureka控、apisix、sentinel、普米、kibana、timetask、grafana、hbase、skywalking-ui、pinpoint、cmak界面、kafka-map、nacos、gateway、elasticsearch、 oa-portal 業務應用等多個web資…

Git 修改或刪除某次提交信息

Git 修改或刪除某次提交信息 情況一&#xff1a;未推送到遠程倉庫修改提交信息刪除提交信息&#xff08;替換為空信息&#xff09;修改歷史提交信息刪除歷史提交信息 情況二&#xff1a;已推送到遠程倉庫修改最新提交信息并推送到遠程倉庫修改歷史提交信息并推送到遠程倉庫 情況…

DeepSeek崛起:如何在云端快速部署你的專屬AI助手

在2025年春節的科技盛宴上&#xff0c;DeepSeek因其在AI領域的卓越表現成為焦點&#xff0c;其開源的推理模型DeepSeek-R1擅長處理多種復雜任務&#xff0c;支持多語言處理&#xff0c;并通過搜索引擎獲取實時信息。DeepSeek因其先進的自然語言處理技術、廣泛的知識庫和高性價比…

DeepSeek部署到本地(解決ollama模型下載失敗問題)

一、下載ollama軟件安裝 1、下載ollama軟件 Ollama 下載完成后可以直接進行安裝&#xff08;外網&#xff0c;速度可能會有點慢&#xff09; 2、修改安裝目錄 進去下載的目錄&#xff0c;使用cmd打開終端輸入OllamaSetup.exe /DIRE:\MySoftware\Ollama 輸入完成后會自動打開…