iOS 音視頻學習 - 視頻錄製階段

前言

伴隨着大火的短視頻應用,正好本身也有點時間,就稍微學習了一下視頻相關的內容。html

這種多媒體技術並無想象的那麼簡單,這算是一個技術方向了。我把這些視頻相關的技術分爲了兩部分,暫且叫作應用層面和底層技術層面(本身取得名字並不許確)。ios

應用層面能夠理解爲調用一些系統的api或者使用一些三方的框架,完成項目中的需求。從一個視頻類app的流程來講,可能就要包括視頻的錄製,視頻的處理(多段合成一段,添加背景音樂等),視頻的播放等,固然了還包括一些濾鏡效果,美顏效果,甚至是一些特效。git

底層技術呢,就包括視頻如何編碼解碼,相機濾鏡美顏特效的一些實現。github

坦白的說,從這兩個方面來講,我都很菜,這段時間的學習就算是這方面一個進階的過程吧。首先先從應用的角度來入手,畢竟有項目驅動的話,首先咱得先把某些效果給實現了,而後再考慮他們底層一些的技術。api

視頻入門

視頻實質:
純粹的視頻(不包括音頻)實質上就是一組幀圖片,通過視頻編碼成爲視頻(video)文件再把音頻(audio)文件有些還有字幕文件組裝在一塊兒成爲咱們看到的視頻(movie)文件。1秒內出現的圖片數就是幀率,圖片間隔越小畫面就越流暢,因此幀率越高效果就越好,須要的存儲空間也就越多。

視頻格式:
MP四、MOV、AVI、RMVB這些播放格式其實都是封裝格式,除了RMVB比較特殊外,其餘格式內封裝的視頻編碼格式都是H264,H264以高壓縮率聞名於世,壓縮效率比MEPG-2提高一倍多,可是世上沒有一箭雙鵰的事,H264的解碼難度提升了3倍多。xcode

這兩個概念就足覺得我本身掃盲了。咱們以前接觸到的視頻文件,其實咱們不能單一把它當作一個文件,其實他是一種封裝。它包括了純粹的視頻,也就是一連串的圖片,包括音頻,還可能包括了字幕。session

視頻錄製

我上網看了不少的文章,總結起來實現視頻的錄製有三種方法能夠用。app

  1. UIImagePickerController
  2. AVCaptureSession + AVCaptureMovieFileOutput
  3. AVCaptureSession + AVAssetWriter

下面咱們來分別說一下這三種方式的。框架

第一種:UIImagePickerController是使用起來最簡單的,固然可定製化也是最低的,只能設置一些簡單的參數來實現基本的視頻錄製的效果。若是你想自定義錄製界面的UI,那你就只能拋棄這個簡單的方法了。異步

第2、三兩種方式要使用AVFoundation框架。
在AVFoundation框架中,關於視頻錄製的是要的類是AVCaptureSession,他負責調配輸入和輸出,算是總的管理。單獨管理輸入的是AVCaptureDeviceInput這個類。

AVFoundation中類不少,一個類會有各類屬性,用起來比較麻煩。咱們第一次使用就先着重瞭解這個總體流程和主要的那幾個類。

第二種方法中使用了AVCaptureMovieFileOutput來做爲輸出,這是一個須要不多配置就能夠直接輸出視頻的類,什麼意思呢,也就是使用第二種AVCaptureSession + AVCaptureMovieFileOutput的方式錄製視頻,在你結束錄製以後,AVCaptureMovieFileOutput會幫你直接生成一個視頻文件到你指定的路徑下,好處就是便捷,直接輸出了視頻文件。

第三種方法我我的以爲是最麻煩的,由於它處理的最原始的數據,並且視頻數據和音頻數據是分開處理,同時這也提升了這種方法的可定製性。

這種方法是經過AVCaptureVideoDataOutput和AVCaptureAudioDataOutput 分別拿到原始的視頻和音頻的數據,再進行處理。咱們拿到這些原始的數據流能夠來爲設置不少參數,也能夠添加背景音樂水印等。而後經過AVAssetWriter把這些數據流處理合成視頻文件。

固然了,第二和三兩種方法中,咱們還須要AVCaptureVideoPreviewLayer來實時預覽攝像頭的畫面。(也就是說咱們攝像頭捕獲的畫面,是經過這個類來管理展現的)

代碼示例和DEMO

這部分具體的操做邏輯就是上面描述的這個樣子,主要的東西都在代碼上。每一個功能類的初始化,各類屬性配置,使用AVAssetWriter時數據時如何寫入的,這都是一個個麻煩的點。還好我從網上發現了一份特別棒的代碼,而後照着大神的代碼敲了一遍,而後針對我想實現的功能作了一點點修改,我把改後的代碼放到百度網盤了。

這是個人DEMO,你們能夠下載來看

下面是第二種方法裏面的一段代碼,從中能夠看出整個流程來

#pragma mark - 主要過程
- (void)setUpWithType:(VideoViewType)type {
    /// -1. 提早異步建立存儲路徑 
    dispatch_async(dispatch_get_main_queue(), ^{
        [self videoFold];
    });
    
    ///0. 初始化捕捉會話,數據的採集都在會話中處理
    [self setUpInit];
    
    ///1. 設置視頻的輸入
    [self setUpVideo];
    
    ///2. 設置音頻的輸入
    [self setUpAudio];
    
    ///3.添加寫入文件的fileoutput
    [self setUpFileOut];
    
    ///4. 視頻的預覽層
    [self setUpPreviewLayerWithType:type];
    
    ///5. 開始採集畫面
    [self.session startRunning];
    
    
}

這個地方要聲明一下,那個第-1步提早異步建立存儲路徑是我加上的,以前代碼裏面沒有,爲何要加這一步呢?

再點擊了開始錄製按鈕以後呢,會出現短暫的卡頓而後纔開始錄製,我分析了一下多是在第3步的時候有建立路徑的操做,你們都知道,都文件的操做是比較耗時的,因此我纔在最開始就先異步把路徑提早建立好了,而後正真開始錄製的時候就會免去這一步耗時的操做,體驗好一些,固然這是個人想法。

視頻錄製的細節功能

咱們從項目開始講起吧 ~ 

項目結構

這是項目結構,我提早聲明一下,那個RecordVideo文件中我是照着大神的FileOut文件中的代碼敲得(也就是視頻錄製的第二種方法),裏面有一些小改動。而後針對第三種方法的代碼修改我都是直接在AVAssetWriter這個文件中直接改的。

下面是重點

原來這份代碼只是從三個方面實現了視頻錄製的功能,三種方法實現的效果都是同樣的,就是簡單的視頻錄製。

可是在實際的項目中,咱們有時候會遇到這麼一個需求,那就是在錄製的過程當中暫停,而後恢復錄製。

我從網上看了一下,找到了兩種實現方法。一種是經過暫停時候的時間偏移量計算來實現,第二種是多段視頻拼接。第一種我暫時還沒能深刻的瞭解,因此我經過修改AVAssetWriter這個文件中的代碼,來實現一下多段視頻拼接的思路。

個人修改是這樣的:

  1. 點擊開始錄製是開始錄製第一段視頻,點擊中止的時候就中止錄製並生成第一段視頻 (以前是點擊了中止生成視頻直接跳到下一級頁面播放了)
  2. 再一次點擊開始錄製的時候,開始錄製第二段,點擊中止時中止錄製並生成第二段。
  3. 以此類推
  4. 在view上我添加了一個錄製完成的button,點擊這個button就開始把以前的多段視頻合成一段。(點擊button以後注意看xcode的打印臺)
  5. 合成完成以後。直接跳轉到下一個頁面預覽咱們生成的視頻文件。

示例頁面

視頻合成的代碼能夠去FMWVideoView這個類中的下面方法中看,我給了不少註釋。

//////////////// 視頻合成////////////
- (void)showFiles{}

上面方法的代碼也有不少不足的地方,好比說若是給整個視頻錄製規定一個最大時間長度,上面實現的分段錄製並無收到這個最大時間的限制,這都是要進一步完善的地方,重點在於這個分段錄製合成的思路。

兩點補充

  1. 使用AVAssetWriter完成視頻錄製

    在用AVAssetWriter實現錄製的時候,視頻數據和音頻數據分別是使用AVCaptureVideoDataOutput和AVCaptureAudioDataOutput來進行輸出,他與以前的AVCaptureMovieFileOutput輸出不一樣的是,AVCaptureMovieFileOutput會直接輸出來視頻文件,可是AVCaptureVideoDataOutput和AVCaptureAudioDataOutput輸出的是原始的數據,再結合AVAssetWriter的把原始數據寫成文件的能力來實現整個錄製過程。

    AVAssetWriter實現錄製視頻相對來講麻煩一點,具體麻煩在把採集到的數據寫成文件的這個過程。其實具體的實現流程並無什麼難懂,關鍵是這寫類的用法問題。還有在寫入文件時,視頻和音頻是分開處理的。具體的用法,代碼寫的很清楚,你們能夠看一下。

  2. 關於視頻更改背景音樂的思考

    上面說到兩個視頻合成一個視頻的例子,其實更改背景音樂用到的就是這種方法。

    舉個例子說,就像咱們說過的,咱們要把A和B兩個視頻合成一個新的視頻,咱們會建立一個視頻軌道一個音頻軌道,而後把A和B的視頻部分提取出來加到視頻軌道中,音頻部分提取出來加到音頻軌道中,而後用這兩個軌道合成一個文件。咱們在更改背景音樂的時候,就是要處理這個音頻軌道,在這個音頻軌道中,咱們再也不是添加以前文件的音頻部分,並且把咱們須要的那個背景音樂添加到音頻軌道中,用添加了背景音樂的音頻軌道和視頻軌道合成視頻文件。

    固然了,這裏面還涉及一些是否保留原音,或者或者跟範圍有關的一些問題,你們能夠本身再研究一下。

接下來學習

濾鏡效果。

特別感謝

特別感謝大神的代碼,不勝感激,附上大神的github主頁。
https://github.com/suifengqjn

參考文章

https://www.cnblogs.com/zy198...

http://gcblog.github.io/2017/...

http://ios.jobbole.com/85069/

https://www.jianshu.com/p/174...

音視頻相關的東西太多太多,咱們一邊學習,一邊領悟吧。

相關文章
相關標籤/搜索