【云駐共創(chuàng)】RTSP 流媒體協(xié)議錄制產(chǎn)品的實(shí)踐案例綜述
前言

在安防和監(jiān)控領(lǐng)域,RTSP 媒體協(xié)議流有很廣泛的使用。今天我向大家介紹一款自己從零做起來的云端錄制產(chǎn)品,這款云產(chǎn)品最初先是針對 RTSP 媒體流,后期對其他媒體流協(xié)議也進(jìn)行了一定能力上的擴(kuò)展。本文重點(diǎn)介紹對 RTSP 流媒體協(xié)議的錄制方案及其相應(yīng)的覆蓋策略。據(jù)我所知,聲網(wǎng)的實(shí)時(shí)錄制功能支持三種模式,分別是云端錄制、本地服務(wù)端錄制和頁面錄制,今天我們介紹的錄制方案和聲網(wǎng)的云端錄制類似。
正文
既然是產(chǎn)品實(shí)踐案例綜述,本文涉及的內(nèi)容會比較廣,將從錄制視頻格式的調(diào)研、錄制方案的選擇、異常狀況的處理、覆蓋策略的執(zhí)行四個(gè)大方面進(jìn)行介紹。
1. 錄制視頻格式調(diào)研
如果想要實(shí)現(xiàn) RTSP 媒體流的錄制功能,就需要考慮錄制目標(biāo)文件的格式,也就是把媒體流錄制成哪種格式的視頻文件。起初我們預(yù)設(shè)了三種方案,經(jīng)過一系列調(diào)研后,最終選擇了 m3u8。接下來,我們簡單介紹一下這個(gè)選擇過程。
1.1 為什么不用 mp4 格式
mp4 是點(diǎn)播視頻中最為常見的視頻格式,綜合分析下來并不符合我們的使用場景。一般情況下,一個(gè)電影視頻的最大時(shí)長也就兩到三個(gè)小時(shí)左右,保存成一個(gè) mp4 文件就夠用了,但是在安防和監(jiān)控場景下,一個(gè)攝像頭對應(yīng)的錄制視頻文件的長度可能是十幾個(gè)小時(shí),甚至是十幾天。所以,對比下來,mp4 格式更適用于電影網(wǎng)站。
這就引出了 mp4 格式的一個(gè)缺點(diǎn),如果錄制存儲為一個(gè) mp4 格式,那文件體積可能會非常大。那么,存儲的時(shí)候就會面臨一系列問題,比如磁盤空間不足、大文件分片等狀況的處理,特別是錄制過程中數(shù)據(jù)流異常中斷可能會導(dǎo)致已經(jīng)錄制的 mp4 文件不可用,這是其一。
我們知道 mp4 文件是由許多 Box 和 FullBox 組成的,可以參考上圖的 Box 樹形圖,其中,F(xiàn)ullBox 是 Box 的擴(kuò)展,每個(gè) Box 又包含 Header 和 Data 兩部分,moov Box 記錄了整個(gè) mp4 文件的音視頻媒體信息。而 moov Box 一般是在 mp4 文件寫完時(shí)才在文件尾部添加。因此,又引出了另外一個(gè)缺點(diǎn),如果 mp4 文件特別大,那么在播放的時(shí)候,播放器需要加載全部的視頻文件到內(nèi)存中,如果視頻文件特別大,這幾乎是不現(xiàn)實(shí)的。因此,我們在錄制結(jié)束保存 mp4 的時(shí)候,需要把 moov Box 調(diào)整到文件頭部來避免這個(gè)問題。
1.2 為什么不用 mpd 格式
mpd 格式類似于 m3u8 格式,但是它采用的是 XML 的組織形式。我們不選擇它的原因也有兩個(gè),其一,mpd 格式在現(xiàn)有產(chǎn)品線上沒有類似使用場景,我們使用更多的是 m3u8,換句話說就是技術(shù)儲備不足。
其二,播放器方案的通用性上存在問題,如果使用 mpd 格式,那么我們的播放器方案需要調(diào)整,能夠支持 mpd 格式媒體的播放,這樣一來會給播放器帶來一定的工作量和隱含的問題。
最后,給出一個(gè) mpd 的文件示例,讓大家對其有一個(gè)更加直觀的了解。
通過上述文件,我們可以知道這個(gè) mpd 文件包含了一路音頻流,同時(shí)支持三種不同分辨率和碼率的視頻流。不同的媒體類型是用 AdaptationSet 標(biāo)簽表示的,內(nèi)部還可以使用 Representation 標(biāo)簽標(biāo)記不同分辨率和碼率的媒體流。
1.3 為什么最終選擇 m3u8 格式
選擇 m3u8 的話,優(yōu)勢就會更加明顯,除了規(guī)避上述方案的問題外,還有一些自身的優(yōu)勢,具體表現(xiàn)如下:
1)本身就是 ts 分片存儲形式,不需要再單獨(dú)考慮大文件的切片問題。
2)現(xiàn)有播放器方案支持 m3u8 格式,不需要再單獨(dú)進(jìn)行適配。
3)具有一定的技術(shù)儲備,開發(fā)上手快,開發(fā)周期可控。
4)相應(yīng)的覆蓋策略執(zhí)行起來會更加方便。
最后,給出一個(gè) m3u8 的文件示例,讓大家對其有一個(gè)更加直觀的了解。
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:17 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:11.933333, index_0000.ts #EXTINF:3.866667, index_0001.ts #EXTINF:7.333333, index_0002.ts #EXTINF:16.666667, index_0003.ts #EXTINF:4.133333, index_0004.ts #EXT-X-ENDLIST
通過上述文件,我們可以知道這個(gè) m3u8 文件包含了 5 個(gè) ts 分片,以及它們各自的時(shí)長信息。文件以 #EXTM3U 標(biāo)簽開始,并以 #EXT-X-ENDLIST 標(biāo)簽結(jié)束。這里有一點(diǎn)需要注意,如果是直播使用的 m3u8 文件,它是沒有 #EXT-X-ENDLIST 標(biāo)簽的。
2. 錄制方案選擇
既然已經(jīng)確定了目標(biāo)文件的格式,那么我們就要考慮怎么實(shí)現(xiàn)了。目前有兩個(gè)方案可以考慮,一個(gè)是 Golang 純原生方案,另一個(gè)是利用 ffmpeg 實(shí)現(xiàn),接下來分別介紹。
2.1 Go 原生
利用純原生的 Golang 實(shí)現(xiàn),其實(shí),Golang 處理音視頻數(shù)據(jù)還是有一定優(yōu)勢的,通過解封裝 RTSP 媒體流,得到音頻數(shù)據(jù)和視頻數(shù)據(jù),然后創(chuàng)建對應(yīng)的解碼器,得到對應(yīng)的原始音頻 PCM 數(shù)據(jù)和原始視頻 YUV 數(shù)據(jù),再分別編碼成 AAC 的音頻和 H264 的視頻,最后保存成 m3u8 格式的錄制文件。整個(gè)過程可以參考下圖:
這種方案,編碼的工作量會稍微大一些,同時(shí)有很多音視頻數(shù)據(jù)處理的細(xì)節(jié)問題,負(fù)載度和難易程度上不如 ffmpeg 方案。
2.2 ffmpeg
利用 ffmpeg 工具庫,通過啟用 ffmpeg 進(jìn)程來完成對應(yīng)的 RTSP 流數(shù)據(jù)接收和 m3u8 文件錄制保存工作,這樣會更加簡單,我們只需要管理好進(jìn)程的創(chuàng)建、釋放和異常處理工作。
3. 異常處理
錄制過程中會遇到各種各樣的問題,接下會分別介紹。有一點(diǎn)是相同的,所有的異常狀況都會通知到錄制調(diào)度服務(wù),由調(diào)度服務(wù)進(jìn)行統(tǒng)一分析和管理,同時(shí)支持熱備機(jī)制,我們通過 Nacos 的服務(wù)發(fā)現(xiàn)機(jī)制監(jiān)測錄制調(diào)度服務(wù)的運(yùn)行狀態(tài),具體關(guān)系可以參考下圖:
3.1 CPU、磁盤
CPU 負(fù)載過高和磁盤空間不足是最為常見的兩種錄制時(shí)的異常狀況,大致的處理邏輯也是較為相似的。
CPU 過高的處理邏輯,可以參考下圖:
當(dāng)前機(jī)器接收到任務(wù)后,進(jìn)行自檢操作,發(fā)現(xiàn) CPU 負(fù)載過高會停止當(dāng)前錄制任務(wù)的執(zhí)行,同時(shí)上報(bào)調(diào)度服務(wù),重新分配別的機(jī)器執(zhí)行該錄制任務(wù)。
當(dāng)前機(jī)器正在執(zhí)行錄制任務(wù),突然發(fā)現(xiàn) CPU 負(fù)載超過閾值,會持續(xù)觀察一段時(shí)間,假定觀察周期為 10 秒,如果 CPU 負(fù)載連續(xù) 10 秒鐘超高,那么會停止當(dāng)前錄制任務(wù),同時(shí)上報(bào)調(diào)度服務(wù),請求別的機(jī)器繼續(xù)執(zhí)行該錄制任務(wù),最后將兩臺機(jī)器上的錄制文件進(jìn)行邏輯關(guān)聯(lián)保存到數(shù)據(jù)庫中。如果 CPU 負(fù)載在 10 秒內(nèi)恢復(fù)到正常值,我們將繼續(xù)執(zhí)行當(dāng)前錄制任務(wù)。
磁盤空間不足的處理邏輯和 CPU 負(fù)載過高有類似的處理邏輯,具體可以參考下圖:
通過流程圖,我們也可以知道磁盤空間不足的處理邏輯和 CPU 負(fù)載過高時(shí)類似,上圖已經(jīng)展示的非常明確了,這里就不過多贅述了。
3.2 異常處理
一些其他的異常處理情況,比如崩潰,整體流程可以參考下圖:
異常發(fā)生時(shí),如果是一般異常,我們只需要將狀態(tài)通知調(diào)度服務(wù)即可,調(diào)度服務(wù)記錄相關(guān)日志,綜合分析整個(gè)錄制服務(wù)的狀態(tài)。如果 60%的錄制機(jī)器觸發(fā)了相同的異常,調(diào)度服務(wù)就要采取相應(yīng)的策略。如果是崩潰等重大異常,就需要重啟機(jī)器或者調(diào)度新的機(jī)器繼續(xù)執(zhí)行錄制任務(wù)。
3.3 錄制超時(shí)
如果發(fā)生了錄制超時(shí),比如我們想錄制 24 個(gè)小時(shí)的視頻,現(xiàn)在時(shí)長已經(jīng)錄夠了,接下來應(yīng)該怎么做呢?一般有兩種處理方法,第一種是直接停止當(dāng)前錄制,上報(bào)通知調(diào)度服務(wù)即可,這種處理方式比較簡單粗暴,但是在安防和監(jiān)控領(lǐng)域是不合適的。第二種是執(zhí)行特定規(guī)則的覆蓋策略,實(shí)現(xiàn)循環(huán)覆蓋,始終保留最近 24 小時(shí)之內(nèi)的視頻畫面內(nèi)容。
對比上述兩種處理方式,當(dāng)發(fā)生錄制超時(shí)時(shí),第二種方式是最符合安防和監(jiān)控領(lǐng)域的通用做法。那么覆蓋策略又是怎么實(shí)現(xiàn)的呢,這就引出了下面的內(nèi)容——覆蓋策略。
4. 覆蓋策略
覆蓋策略在原理上理解起來很簡單,但是具體執(zhí)行時(shí),就不那么簡單了。首先,我們也先通過一個(gè)流程圖對覆蓋策略的處理邏輯有一個(gè)整體上的認(rèn)識。
4.1 一級定時(shí)器
當(dāng)錄制任務(wù)啟動時(shí),我們同時(shí)啟動一個(gè)定時(shí)器(一級定時(shí)器),定時(shí)器的時(shí)長就是錄制任務(wù)的目標(biāo)時(shí)長,這個(gè)非常好理解。但是,這個(gè)定時(shí)器只生效一次或者一次都不生效。只有一級定時(shí)器生效后,才會啟動二級定時(shí)器。如果一級定時(shí)器沒有啟動,那么二級定時(shí)器也不會啟動。
我們可以這樣理解,只有一級定時(shí)器觸發(fā),錄制服務(wù)才會執(zhí)行對應(yīng)的覆蓋策略。當(dāng)覆蓋策略啟動后,一級定時(shí)器銷毀,二級定時(shí)器生效。
4.2 二級定時(shí)器
當(dāng)文件時(shí)長達(dá)到了預(yù)設(shè)的最大時(shí)長時(shí),我們將啟動二級定時(shí)器。其實(shí),二級定時(shí)器控制的是覆蓋策略的刪除頻率,每次時(shí)間到了,就刪除早些時(shí)候到錄制文件分片。
4.3 執(zhí)行覆蓋
具體覆蓋的執(zhí)行邏輯是,根據(jù) ts 分片的時(shí)長和二級定時(shí)器的時(shí)間周期,計(jì)算需要刪除的 ts 分片個(gè)數(shù),同時(shí)更新 m3u8 中的索引列表,然后循環(huán)執(zhí)行該策略,最終實(shí)現(xiàn)動態(tài)循環(huán)的錄制覆蓋策略。
覆蓋策略的執(zhí)行過程如上圖所示,相信通過上文的解釋,大家理解起來還是非常容易的。需要特別說明的是,由于二級定時(shí)器執(zhí)行周期 t 的限制,錄制文件的實(shí)際時(shí)長在最大錄制時(shí)長 T 和(T+t)之間。
結(jié)尾
好了,現(xiàn)在關(guān)于 RTSP 媒體流的錄制方案和覆蓋策略就介紹完了,相信大家對云端錄制產(chǎn)品方案也有了一定認(rèn)識,有自己想法和感興趣的小伙伴,歡迎評論留言。關(guān)注我,分享更多音視頻和流媒體服務(wù)器內(nèi)容。
本文整理自【內(nèi)容共創(chuàng)系列】1024,懂你所需,予你溫暖,致敬新時(shí)代可愛的程序員們,活動鏈接:https://bbs.huaweicloud.com/blogs/302011
5G媒體 TCP/IP 視頻
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。