摘要:前言伴隨著大火的短視頻應(yīng)用,正好自己也有點時間,就稍微學(xué)習(xí)了一下視頻相關(guān)的內(nèi)容。視頻錄制我上網(wǎng)看了很多的文章,總結(jié)起來實現(xiàn)視頻的錄制有三種方法可以用。還有在寫入文件時,視頻和音頻是分開處理的。
伴隨著大火的短視頻應(yīng)用,正好自己也有點時間,就稍微學(xué)習(xí)了一下視頻相關(guān)的內(nèi)容。
這種多媒體技術(shù)并沒有想象的那么簡單,這算是一個技術(shù)方向了。我把這些視頻相關(guān)的技術(shù)分為了兩部分,暫且叫做應(yīng)用層面和底層技術(shù)層面(自己取得名字并不準(zhǔn)確)。
應(yīng)用層面可以理解為調(diào)用一些系統(tǒng)的api或者使用一些三方的框架,完成項目中的需求。從一個視頻類app的流程來說,可能就要包括視頻的錄制,視頻的處理(多段合成一段,添加背景音樂等),視頻的播放等,當(dāng)然了還包括一些濾鏡效果,美顏效果,甚至是一些特效。
底層技術(shù)呢,就包括視頻如何編碼解碼,相機濾鏡美顏特效的一些實現(xiàn)。
坦白的說,從這兩個方面來說,我都很菜,這段時間的學(xué)習(xí)就算是這方面一個進(jìn)階的過程吧。首先先從應(yīng)用的角度來入手,畢竟有項目驅(qū)動的話,首先咱得先把某些效果給實現(xiàn)了,然后再考慮他們底層一些的技術(shù)。
視頻實質(zhì):
純粹的視頻(不包括音頻)實質(zhì)上就是一組幀圖片,經(jīng)過視頻編碼成為視頻(video)文件再把音頻(audio)文件有些還有字幕文件組裝在一起成為我們看到的視頻(movie)文件。1秒內(nèi)出現(xiàn)的圖片數(shù)就是幀率,圖片間隔越小畫面就越流暢,所以幀率越高效果就越好,需要的存儲空間也就越多。視頻格式:
MP4、MOV、AVI、RMVB這些播放格式其實都是封裝格式,除了RMVB比較特殊外,其他格式內(nèi)封裝的視頻編碼格式都是H264,H264以高壓縮率聞名于世,壓縮效率比MEPG-2提升一倍多,但是世上沒有兩全其美的事,H264的解碼難度提高了3倍多。
這兩個概念就足以為我自己掃盲了。我們之前接觸到的視頻文件,其實我們不能單一把它當(dāng)做一個文件,其實他是一種封裝。它包括了純粹的視頻,也就是一連串的圖片,包括音頻,還可能包括了字幕。
我上網(wǎng)看了很多的文章,總結(jié)起來實現(xiàn)視頻的錄制有三種方法可以用。
UIImagePickerController
AVCaptureSession + AVCaptureMovieFileOutput
AVCaptureSession + AVAssetWriter
下面我們來分別說一下這三種方式的。
第一種:UIImagePickerController是使用起來最簡單的,當(dāng)然可定制化也是最低的,只能設(shè)置一些簡單的參數(shù)來實現(xiàn)基本的視頻錄制的效果。如果你想自定義錄制界面的UI,那你就只能拋棄這個簡單的方法了。
第二、三兩種方式要使用AVFoundation框架。
在AVFoundation框架中,關(guān)于視頻錄制的是要的類是AVCaptureSession,他負(fù)責(zé)調(diào)配輸入和輸出,算是總的管理。多帶帶管理輸入的是AVCaptureDeviceInput這個類。
AVFoundation中類很多,一個類會有各種屬性,用起來比較麻煩。我們第一次使用就先著重了解這個整體流程和主要的那幾個類。
第二種方法中使用了AVCaptureMovieFileOutput來作為輸出,這是一個需要很少配置就可以直接輸出視頻的類,什么意思呢,也就是使用第二種AVCaptureSession + AVCaptureMovieFileOutput的方式錄制視頻,在你結(jié)束錄制之后,AVCaptureMovieFileOutput會幫你直接生成一個視頻文件到你指定的路徑下,好處就是便捷,直接輸出了視頻文件。
第三種方法我個人覺得是最麻煩的,因為它處理的最原始的數(shù)據(jù),而且視頻數(shù)據(jù)和音頻數(shù)據(jù)是分開處理,同時這也提高了這種方法的可定制性。
這種方法是通過AVCaptureVideoDataOutput和AVCaptureAudioDataOutput 分別拿到原始的視頻和音頻的數(shù)據(jù),再進(jìn)行處理。我們拿到這些原始的數(shù)據(jù)流可以來為設(shè)置很多參數(shù),也可以添加背景音樂水印等。然后通過AVAssetWriter把這些數(shù)據(jù)流處理合成視頻文件。
當(dāng)然了,第二和三兩種方法中,我們還需要AVCaptureVideoPreviewLayer來實時預(yù)覽攝像頭的畫面。(也就是說我們攝像頭捕獲的畫面,是通過這個類來管理展示的)
這部分具體的操作邏輯就是上面描述的這個樣子,主要的東西都在代碼上。每個功能類的初始化,各種屬性配置,使用AVAssetWriter時數(shù)據(jù)時如何寫入的,這都是一個個麻煩的點。還好我從網(wǎng)上發(fā)現(xiàn)了一份特別棒的代碼,然后照著大神的代碼敲了一遍,然后針對我想實現(xiàn)的功能做了一點點修改,我把改后的代碼放到百度網(wǎng)盤了。
這是我的DEMO,大家可以下載來看
下面是第二種方法里面的一段代碼,從中可以看出整個流程來
#pragma mark - 主要過程 - (void)setUpWithType:(VideoViewType)type { /// -1. 提前異步創(chuàng)建存儲路徑 dispatch_async(dispatch_get_main_queue(), ^{ [self videoFold]; }); ///0. 初始化捕捉會話,數(shù)據(jù)的采集都在會話中處理 [self setUpInit]; ///1. 設(shè)置視頻的輸入 [self setUpVideo]; ///2. 設(shè)置音頻的輸入 [self setUpAudio]; ///3.添加寫入文件的fileoutput [self setUpFileOut]; ///4. 視頻的預(yù)覽層 [self setUpPreviewLayerWithType:type]; ///5. 開始采集畫面 [self.session startRunning]; }
這個地方要聲明一下,那個第-1步提前異步創(chuàng)建存儲路徑是我加上的,之前代碼里面沒有,為什么要加這一步呢?
再點擊了開始錄制按鈕之后呢,會出現(xiàn)短暫的卡頓然后才開始錄制,我分析了一下可能是在第3步的時候有創(chuàng)建路徑的操作,大家都知道,都文件的操作是比較耗時的,所以我才在最開始就先異步把路徑提前創(chuàng)建好了,然后正真開始錄制的時候就會免去這一步耗時的操作,體驗好一些,當(dāng)然這是我的想法。
我們從項目開始講起吧 ~ ?
這是項目結(jié)構(gòu),我提前聲明一下,那個RecordVideo文件中我是照著大神的FileOut文件中的代碼敲得(也就是視頻錄制的第二種方法),里面有一些小改動。然后針對第三種方法的代碼修改我都是直接在AVAssetWriter這個文件中直接改的。
下面是重點
原來這份代碼只是從三個方面實現(xiàn)了視頻錄制的功能,三種方法實現(xiàn)的效果都是一樣的,就是簡單的視頻錄制。
但是在實際的項目中,我們有時候會遇到這么一個需求,那就是在錄制的過程中暫停,然后恢復(fù)錄制。
我從網(wǎng)上看了一下,找到了兩種實現(xiàn)方法。一種是通過暫停時候的時間偏移量計算來實現(xiàn),第二種是多段視頻拼接。第一種我暫時還沒能深入的了解,所以我通過修改AVAssetWriter這個文件中的代碼,來實現(xiàn)一下多段視頻拼接的思路。
我的修改是這樣的:
點擊開始錄制是開始錄制第一段視頻,點擊停止的時候就停止錄制并生成第一段視頻 (之前是點擊了停止生成視頻直接跳到下一級頁面播放了)
再一次點擊開始錄制的時候,開始錄制第二段,點擊停止時停止錄制并生成第二段。
以此類推
在view上我添加了一個錄制完成的button,點擊這個button就開始把之前的多段視頻合成一段。(點擊button之后注意看xcode的打印臺)
合成完成之后。直接跳轉(zhuǎn)到下一個頁面預(yù)覽我們生成的視頻文件。
視頻合成的代碼可以去FMWVideoView這個類中的下面方法中看,我給了很多注釋。
//////////////// 視頻合成//////////// - (void)showFiles{}
上面方法的代碼也有很多不足的地方,比如說如果給整個視頻錄制規(guī)定一個最大時間長度,上面實現(xiàn)的分段錄制并沒有收到這個最大時間的限制,這都是要進(jìn)一步完善的地方,重點在于這個分段錄制合成的思路。
使用AVAssetWriter完成視頻錄制
在用AVAssetWriter實現(xiàn)錄制的時候,視頻數(shù)據(jù)和音頻數(shù)據(jù)分別是使用AVCaptureVideoDataOutput和AVCaptureAudioDataOutput來進(jìn)行輸出,他與之前的AVCaptureMovieFileOutput輸出不同的是,AVCaptureMovieFileOutput會直接輸出來視頻文件,但是AVCaptureVideoDataOutput和AVCaptureAudioDataOutput輸出的是原始的數(shù)據(jù),再結(jié)合AVAssetWriter的把原始數(shù)據(jù)寫成文件的能力來實現(xiàn)整個錄制過程。
AVAssetWriter實現(xiàn)錄制視頻相對來說麻煩一點,具體麻煩在把采集到的數(shù)據(jù)寫成文件的這個過程。其實具體的實現(xiàn)流程并沒有什么難懂,關(guān)鍵是這寫類的用法問題。還有在寫入文件時,視頻和音頻是分開處理的。具體的用法,代碼寫的很清楚,大家可以看一下。
關(guān)于視頻更改背景音樂的思考
上面說到兩個視頻合成一個視頻的例子,其實更改背景音樂用到的就是這種方法。
舉個例子說,就像我們說過的,我們要把A和B兩個視頻合成一個新的視頻,我們會創(chuàng)建一個視頻軌道一個音頻軌道,然后把A和B的視頻部分提取出來加到視頻軌道中,音頻部分提取出來加到音頻軌道中,然后用這兩個軌道合成一個文件。我們在更改背景音樂的時候,就是要處理這個音頻軌道,在這個音頻軌道中,我們不再是添加之前文件的音頻部分,而且把我們需要的那個背景音樂添加到音頻軌道中,用添加了背景音樂的音頻軌道和視頻軌道合成視頻文件。
當(dāng)然了,這里面還涉及一些是否保留原音,或者或者跟范圍有關(guān)的一些問題,大家可以自己再研究一下。
濾鏡效果。
特別感謝大神的代碼,不勝感激,附上大神的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...
音視頻相關(guān)的東西太多太多,我們一邊學(xué)習(xí),一邊領(lǐng)悟吧。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/11082.html
閱讀 1536·2023-04-25 18:56
閱讀 1483·2021-09-29 09:34
閱讀 1708·2021-09-22 15:51
閱讀 3482·2021-09-14 18:03
閱讀 1159·2021-07-23 17:54
閱讀 2017·2019-08-29 18:38
閱讀 2899·2019-08-29 12:38
閱讀 609·2019-08-26 13:41