AVFoundation 框架介紹

  • 2019 年 11 月 5 日
  • 筆記

01 前言

大家好,從今天開始我們正式進入 iOS 專題。

本文是 iOS/Android 音影片開發專題 第九篇,該專題中項目程式碼將在 Github 進行託管,你可在微信公眾號(GeekDev)後台回復 資料 獲取項目地址。

本期內容:

  • AVFoundation 概述
  • AVFoundation 中的常用類
  • AVFoundation 採集設備
  • 結束語

02 AVFoundation 概述

AVFoundation 是 iOS 中多媒體框架之一,基於 Object-C/Swift 介面,可以用來播放,編輯,重新編碼音影片文件。我們可以通過 AVCaptureSession 輸入設備實時捕捉處理影像資訊。下面是 iOS 系統中的 AVFoundation 媒體架構:

通常,我們使用高級介面就可以滿足我們的大部分需求。

  • 如果你簡單的播放一個影片,可以使用 AVKit 框架
  • 在 iOS 系統中如果你不關心格式的情況下錄製影片,可以使用 UIKit 框架

另外,你可能還聽說過 VideoToolbox , AudioToolbox ,CoreMedia , CoreVideo, 這些框架是 iOS 為開發提供的 C 語言介面,AVFoundation 底層技術就是使用的這些 C 語言框架。

像 VideoToolbox 我們做直播類項目時,通常會使用 VideoToolbox 對影片流進行 h264 編碼。使用 VideoToolbox 我們可以更加精細的控制編碼數。AVFoundation 一般用於對媒體文件(Asset)進行編輯,在短影片場景下用的較多。

03 AVFoundation 常用類

  • AVAsset 是一個抽象類,定義了一個資產文件的抽象介面
    • AVURLAsset 通過 URL 創建,URL 可以是本地資源,也可以是網路資源
    • AVComposition 可以將多個基於本地文件的媒體數據以自定義的時間安排組合在一起, 用以呈現或處理多個源的媒體數據
  • AVAssetReader 用以讀取 AVAsset 的媒體數據,可以直接將未解碼的媒體數據解碼為可用數據
  • AVAssetReaderOutput 有多個子類,例如 AVAssetReaderTrackOutput 或 AVAssetReaderVideoCompositionOtput。 你可以使用 addOutput: 將一個或多個 AVAssetReaderOutput 添加到 AVAssetReader 對象中來讀取資產的媒體數據
  • AVAssetTrack 媒體資產軌道對象
  • AVAssetImageGenerator 提供獲取影片資產縮圖的功能。如果你需要獲取多張縮略圖建議 使用 generateCGImageesAsynchronouslyForTimes:completionHandler:
  • AVAssetExportSession 可以將 AVAsset 媒體文件內容由指定的預設格式進行輸出
  • AVAssetWriter 可以將媒體數據 CMSampleBuffer 寫入指定的文件中。相比 AVAssetExportSession AVAssetReader + AVAssetWriter 可以有更細粒度的配置,比如我們可以將 CMSampleBuffer 經過特效處理後寫入文件
  • CMSampleBuffer 是 Core Foundation 對象,是音頻, 影片的壓縮或未壓縮數據樣本。 AVAssetReaderOutput 輸出的媒體數據就是該對象
  • CMTime 一個表示時間的結構體。以分數的形式表示時間,value 表示分子,timescale 表示分母。一般我們使用 timescale 表示每秒鐘幀率,value 表示當前第幾幀。 例如,timescale 為 30fps ,value 為 60 時,當前時間為 60/30 = 2s . CMTime 定義在 Core Media 框架中,我們可以通過 CMTimeMake(int64_t value,int32_t timescale) 快速創建一個 CMTime 。你可以通過 CMTimeMakeWithSeconds(Float64 seconds,int32_t preferredTimescale) ,將 seconds 轉為 CMTime. preferredTimescale 建議我們使用的有 NSEC_PER_SEC(一秒鐘納秒數), NSEC_PER_MSEC(一毫秒納秒數), USEC_PER_SEC(一秒鐘微妙數), NESC_PER_USEC(一微妙納秒數)。
    • 1秒 = 1000000000 納秒 (10億)
    • 1毫秒 = 1000000 納秒 (100萬)
    • 1秒 = 1000000 微妙 (100萬)
    • 1微妙 = 1000 納秒(1000)
  • CMTimeRange 標識一個時間範圍的結構體,同樣定義在 Core Media 框架中。 start 表示開始時間,duration 表示持續時間,類型都是 CMTime。 CMTimeRange 的創建方式與 CMTime 類似都提供了一個 C 語言函數。 通過 CMTimeRangeMake(CMTime start, CMTime duration) 可以快速創建一個時間範圍。 另外,Core Media 也為我們提供了很多實用的工具方法
    • CMTimeRangeEqual (CMTimeRange range1,CMTimeRnage range2) 比較 range1 與 range2 時間範圍是否相同
    • CMTimeRangeContainsTime(CMTimeRange range,CMTime time) 判斷 time 是否在 range 範圍內
    • CMTimeRangeGetEnd(CMTimeRange range) 獲取 range 的結束時間 (start + duration)
    • CMTimeRangeGetUnion(CMTimeRange range,CMTimeRange otherRange) 計算 range 與 otherRange 的並集
    • CMTimeRangeGetIintersection(CMTimeRange range,CMTimeRange otherRange) 計算 range 與 otherRange 的交集

04 AVFoundation 採集設備

在 03 AVFoundation 常用類 章節中,我們並沒有提到 iOS 中的相機採集,因為相機採集足夠複雜,

我們將相機採集獨立成章,足夠我們使用一篇文章單獨講解。這裡我們姑且拋磚引玉,

在以後的文章中我們將開放一款 相機 APP。

AVFoundation Capture 子系統為 iOS 的影片,照片和音頻捕獲服務提供了通用的高級體系架構。

如果你要執行以下操作,你應該使用該系統API:

  • 構建自定義的相機用戶介面,將拍照或影片錄製集成到應用中
  • 為用戶提供對照片和影片捕獲更直接的控制,例如焦點,曝光等增強選項。
  • 與系統相機 UI 產生不同的結果,例如 RAW 格式的照片,深度圖或需要自定義影片元數據
  • 從採集設備 (Capture device) 實時獲取影片像素或音頻數據。

Capture 系統體系結構主要部分是會話,輸入和輸出,Capture 會話將一個或多個輸入連接到一個或多個

輸出。輸入是媒體的來源,包括捕獲設備相機和麥克風。輸出是從輸入中獲取媒體數據,例如寫入磁碟文件併產生一個電影文件。

  • AVCaptureSession 採集會話,用於管理並協調輸入設備(AVCaptureDeviceInput)和輸出設備 (AVCatureoutput)。要開啟實時捕獲,需要實例化 AVCaptureSession 對象並添加合適的輸入和輸出。

下面是如何配置捕獲設備用以錄製音頻。

/ Create the capture session.AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];  // Lookup the default audio device.AVCaptureDevice *audioDevice =    [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];  // Wrap the audio device in a capture device input.NSError *error = nil;AVCaptureDeviceInput *audioInput =    [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];  if (audioInput) {    // If the input can be added, add it to the session.    if ([captureSession canAddInput:audioInput]) {        [captureSession addInput:audioInput];    }} else {    // Configuration failed. Handle error.}
  • AVCaptureInput 為 AVCaptureSession 提供輸入數據,是所有輸入設備的超類。 需要將 AVCaptureInput 與 AVCaptureSession 相關聯,在 AVCaptureSession 上調用addInput:
    • AVCaptureDeviceInput 捕獲輸入對象,用於從 AVCaptureDevice 捕獲設備中獲取數據 並提供給 AVCaptureSession 。創建 AVCaptureInput 時需要指定 AVCaptureDevice, AVCaptureDevice 決定了捕獲的數據類型
    • AVCaptureScreenInput 提供錄屏捕獲輸入
    • AVCaptureMetadataInput 元數據輸入 (沒用過)
  • AVCaptureOutput 捕獲輸出
    • AVCaptureAudioDataOutput 記錄音頻輸出,提供對音頻樣本緩衝區的訪問
    • AVCaptureAudioPreviewOutput 音頻輸出,與音頻輸出設備相關聯,可用於播放

由 AVCaptureSession 捕獲的音頻數據

  • AVCaptureDepthDataOutput 輸出相機畫面的場景深度資訊,只有雙攝影機或以上才支援深度資訊
  • AVCapturePhotoOutput 相機照片輸出,可以從相機中捕獲一張照片。在 iOS10.0 之前使用 AVCaptureStillImageOutput
  • AVCaptureVideoDataOutput 記錄影片並提供影片幀輸出
  • AVCaptureFileOutput 捕獲文件輸出超類
  • AVCaptureMovieFileOutput 將音頻和影片數據輸出到文件中
  • AVCaptureAudioFileOutput 記錄音頻數據輸出到文件中
  • AVCaptureMetadataOutput 元數據捕獲輸出 該 Output 比較牛逼,可以用來掃描條形碼,人臉,二維碼,UPC-E 商品條形碼等資訊。