放平臺(tái)音視頻接入與直播流管理實(shí)戰(zhàn)指南)
做螢石開(kāi)放平臺(tái)的音視頻接入我印象最深的一句話是設(shè)備接入這件事看起來(lái)是“填幾個(gè)參數(shù)、調(diào)一個(gè)接口”但真正決定項(xiàng)目后續(xù)順不順的其實(shí)是接入之前把整個(gè)鏈路想清楚了。螢石開(kāi)放平臺(tái)的直播流管理核心就是把攝像頭這類(lèi)設(shè)備通過(guò)平臺(tái)接入到云端然后拿到一路又一路的直播流地址再集成到自己的后臺(tái)、小程序或者App里。它解決的是“我有硬件設(shè)備怎么把它變成實(shí)時(shí)可看的音視頻資源”這個(gè)問(wèn)題。這篇東西適合正在做音視頻開(kāi)發(fā)、集成商項(xiàng)目、或是個(gè)人想快速搭一套可視化監(jiān)控系統(tǒng)的朋友參考我盡量把設(shè)備接入和直播流管理的實(shí)操細(xì)節(jié)都講透。1. 在碰代碼之前先把設(shè)備接入這件事想清楚1.1 設(shè)備接入的本質(zhì)是一條完整鏈路很多人拿到螢石開(kāi)放平臺(tái)的文檔第一反應(yīng)是去找“接口列表”然后就開(kāi)始調(diào)。這個(gè)順序雖然不能說(shuō)錯(cuò)但如果一開(kāi)始不明白整條鏈路的走向后面排查問(wèn)題會(huì)很被動(dòng)。設(shè)備接入的本質(zhì)其實(shí)是把一條數(shù)據(jù)通路打通終端設(shè)備攝像頭/DVR/NVR通過(guò)螢石云完成注冊(cè)設(shè)備上線后由平臺(tái)側(cè)統(tǒng)一管理設(shè)備信息、通道信息、視頻流開(kāi)放平臺(tái)再把設(shè)備能力以 HTTP OpenAPI 的形式暴露給開(kāi)發(fā)者開(kāi)發(fā)者拿著這些接口去獲取設(shè)備列表、拿直播地址最后在自家播放器里把畫(huà)面播出來(lái)。我習(xí)慣把這個(gè)過(guò)程拆成三段來(lái)看第一段是“設(shè)備上云”也就是設(shè)備端的注冊(cè)和在線第二段是“平臺(tái)取流”也就是通過(guò)開(kāi)放平臺(tái)調(diào)用接口拿到可播放的地址第三段是“播放落地”也就是在網(wǎng)頁(yè)、客戶(hù)端、小程序里把流拉起來(lái)。三段中間任何一環(huán)斷了都會(huì)表現(xiàn)為“畫(huà)面出不來(lái)”。這里有一個(gè)容易混淆的點(diǎn)螢石開(kāi)放平臺(tái)本身不直接生產(chǎn)視頻流它是“設(shè)備側(cè)能力的管理者和轉(zhuǎn)發(fā)者”。你要拿到的直播地址其實(shí)是平臺(tái)根據(jù)設(shè)備通道實(shí)時(shí)生成的帶有鑒權(quán)信息并且有過(guò)期時(shí)間。所以你會(huì)發(fā)現(xiàn)同樣的一個(gè)設(shè)備每次調(diào)用取流接口拿到的 URL 可能都不一樣這不是平臺(tái)不穩(wěn)定而是它的防盜鏈機(jī)制在起作用。1.2 前置準(zhǔn)備賬號(hào)、應(yīng)用、密鑰三件套設(shè)備接入和直播流管理繞不開(kāi)三樣?xùn)|西開(kāi)發(fā)者賬號(hào)、應(yīng)用、密鑰。這三者相當(dāng)于你的“系統(tǒng)身份證”。在螢石開(kāi)放平臺(tái)控制臺(tái)注冊(cè)開(kāi)發(fā)者賬號(hào)之后需要?jiǎng)?chuàng)建一個(gè)應(yīng)用應(yīng)用創(chuàng)建成功后會(huì)生成一對(duì)關(guān)鍵的密鑰AppKey 和 AppSecret。AppKey 相當(dāng)于你的應(yīng)用在平臺(tái)上的身份標(biāo)識(shí)AppSecret 相當(dāng)于你的應(yīng)用密碼。后續(xù)調(diào)用絕大多數(shù)開(kāi)放平臺(tái)接口都需要先用這兩個(gè)值去換取訪問(wèn)憑證 accessToken。accessToken 是一次性拿到的臨時(shí)身份令牌它在有效期內(nèi)可以讓你調(diào)用設(shè)備列表、直播地址等接口而不用每次帶著 AppSecret。說(shuō)通俗點(diǎn)AppKey/AppSecret 就是“你的登錄賬號(hào)密碼”accessToken 就是“你登錄后發(fā)的會(huì)話票據(jù)”。這里要提醒一下AppSecret 的保管非常重要不要把它寫(xiě)死在博客、GitHub、小程序前端這些能被扒到的地方。很多項(xiàng)目后期出現(xiàn)接口被惡意調(diào)用都是因?yàn)槊荑€從前端源碼里泄露出去的。正確的做法是把密鑰放在服務(wù)端由服務(wù)端統(tǒng)一換 token前端只拿 token 跟你們的業(yè)務(wù)服務(wù)通信。另外應(yīng)用創(chuàng)建時(shí)通常需要選擇應(yīng)用類(lèi)型和權(quán)限范圍關(guān)于音視頻相關(guān)的權(quán)限要在控制臺(tái)里確認(rèn)已經(jīng)開(kāi)通。我遇到過(guò)不少人在這一步卡住應(yīng)用建好了接口卻提示無(wú)權(quán)限排查了半天才發(fā)現(xiàn)音視頻能力沒(méi)有勾選開(kāi)通。這也是為什么我把“前置準(zhǔn)備”單拎出來(lái)說(shuō)因?yàn)樗苯記Q定后面的流程是否走得通。1.3 設(shè)備接入的三種方式怎么選螢石設(shè)備接入開(kāi)放平臺(tái)從操作路徑上大致分三類(lèi)我根據(jù)自己的項(xiàng)目經(jīng)驗(yàn)整理了一個(gè)對(duì)比接入方式適用場(chǎng)景優(yōu)點(diǎn)需要注意的點(diǎn)App 掃碼/驗(yàn)證碼綁定個(gè)人開(kāi)發(fā)、快速驗(yàn)證操作簡(jiǎn)單設(shè)備信息自動(dòng)上云設(shè)備歸到賬號(hào)下要保證賬號(hào)體系一致開(kāi)放平臺(tái)控制臺(tái)手動(dòng)添加集成商項(xiàng)目、批量管理有設(shè)備管理和通道管理界面能快速核對(duì)需要拿到設(shè)備序列號(hào)和驗(yàn)證碼OpenAPI 接口對(duì)接獨(dú)立產(chǎn)品化、二次開(kāi)發(fā)可自動(dòng)化創(chuàng)建用戶(hù)、設(shè)備、流地址邏輯復(fù)雜度高調(diào)試鏈路長(zhǎng)如果你是個(gè)人做測(cè)試最省事的方式是先把設(shè)備用手機(jī)上的螢石云視頻 App 綁定到賬號(hào)再用同一個(gè)手機(jī)號(hào)注冊(cè)開(kāi)發(fā)者賬號(hào)然后調(diào)接口查回來(lái)的設(shè)備列表就是你這批設(shè)備。如果你是幫客戶(hù)做集成那客戶(hù)手里那批攝像頭很可能已經(jīng)在別人賬號(hào)下你需要讓客戶(hù)先在螢石云視頻 App 上把設(shè)備解綁再綁到你項(xiàng)目對(duì)應(yīng)的管理賬號(hào)里否則接口是拉不到這些設(shè)備的。還有一種情況是設(shè)備走局域網(wǎng)私有協(xié)議或其他非螢石協(xié)議的 IPC那這條路就暫時(shí)走不通。螢石開(kāi)放平臺(tái)的設(shè)備接入主要面向支持螢石協(xié)議、能夠上云的硬件設(shè)備。如果客戶(hù)用的是雜牌攝像頭又不支持螢石協(xié)議先別急著寫(xiě)代碼得先確認(rèn)硬件層面是否具備接入條件。2. 設(shè)備接入的完整實(shí)操流程從注冊(cè)到上線2.1 創(chuàng)建應(yīng)用并拿到密鑰我先說(shuō)下我通常的操作路徑。在螢石開(kāi)放平臺(tái)控制臺(tái)注冊(cè)并登錄后進(jìn)入“開(kāi)發(fā)者服務(wù)”里的“應(yīng)用管理”創(chuàng)建一個(gè)應(yīng)用。應(yīng)用名稱(chēng)、描述這些按實(shí)際填就行關(guān)鍵是創(chuàng)建成功后在應(yīng)用詳情頁(yè)里找到 AppKey 和 AppSecret。拿到密鑰之后第一件事不是去調(diào)設(shè)備接口而是先用它獲取一次 accessToken 驗(yàn)證一下鏈路是通的。接口形式一般是 POST 請(qǐng)求把 AppKey 和 AppSecret 作為參數(shù)提交返回的數(shù)據(jù)里會(huì)帶 accessToken 和過(guò)期時(shí)間。你可以用 Postman、Apifox或者直接在命令行里 curl 一把。我第一次用的命令大致長(zhǎng)這樣curl -X POST https://open.ys7.com/api/lapp/token/get \ -d appKey你的AppKey \ -d appSecret你的AppSecret返回正常的話你會(huì)拿到一串很長(zhǎng)的 accessToken。這個(gè)token的有效期每個(gè)開(kāi)發(fā)者應(yīng)用可能有差異但通常是以天為級(jí)別的。我建議你在項(xiàng)目里做一個(gè)統(tǒng)一的服務(wù)端 token 管理定時(shí)刷新避免在業(yè)務(wù)代碼里到處粘貼 token。這里有一個(gè)實(shí)踐上的細(xì)節(jié)accessToken 在快過(guò)期的時(shí)候再去刷新就行不要每次請(qǐng)求都重新?lián)Q取。開(kāi)放平臺(tái)接口一般有頻率限制頻繁換取 token 容易觸發(fā)限流反而讓業(yè)務(wù)收到異常錯(cuò)誤。我在一個(gè)項(xiàng)目里就犯過(guò)這個(gè)毛病寫(xiě)了個(gè)每次調(diào)用都先調(diào) token 接口的代碼結(jié)果一壓測(cè)直接被平臺(tái)限流教訓(xùn)很深刻。2.2 把設(shè)備添加到賬號(hào)序列號(hào)與驗(yàn)證碼拿到密鑰和 token 之后最關(guān)鍵的一步來(lái)了把設(shè)備加到你的賬號(hào)下。這一步很多人以為是調(diào)一個(gè)“設(shè)備添加”接口就完了其實(shí)根據(jù)設(shè)備當(dāng)前狀態(tài)不同操作路徑是不同的。如果設(shè)備是全新的你可以在“螢石云視頻”App 里通過(guò)掃碼或者手動(dòng)錄入 SN設(shè)備序列號(hào)、驗(yàn)證碼來(lái)添加。設(shè)備會(huì)出現(xiàn)在你賬號(hào)的設(shè)備列表里。然后開(kāi)發(fā)者控制臺(tái)對(duì)應(yīng)的同賬號(hào)下也能在設(shè)備列表里看到它。如果是控制臺(tái)方式添加一般是進(jìn)入設(shè)備管理頁(yè)面選擇添加設(shè)備輸入設(shè)備序列號(hào)和設(shè)備驗(yàn)證碼。設(shè)備序列號(hào)在哪里看通常貼在攝像頭機(jī)身底部或側(cè)面是一串由字母和數(shù)字組成的 SN比如像 “E12345678” 或 “C12345678” 這種格式。設(shè)備驗(yàn)證碼則是單獨(dú)的一串 6 位字符也在機(jī)身標(biāo)簽上和 SN 是兩樣?xùn)|西。很多人會(huì)把這倆搞混或者找不到驗(yàn)證碼就去試默認(rèn)密碼位結(jié)果是“驗(yàn)證碼錯(cuò)誤”或者“設(shè)備已被添加”。注意這里說(shuō)的是設(shè)備接入開(kāi)放平臺(tái)的“賬號(hào)歸屬權(quán)”。設(shè)備在同一時(shí)間里只能被一個(gè)主賬號(hào)管理。如果客戶(hù)手里那臺(tái)設(shè)備之前已經(jīng)綁定了別的賬號(hào)你必須先在原賬號(hào)下刪除或解綁設(shè)備才能在新的賬號(hào)下添加成功。我在調(diào)試一個(gè)項(xiàng)目時(shí)客戶(hù)發(fā)來(lái)一臺(tái)“二手?jǐn)z像頭”我始終添加失敗最后才確認(rèn)是前任綁定沒(méi)有解除。所以接手設(shè)備前先確認(rèn)這臺(tái)設(shè)備是不是“自由身”很重要。2.3 用 token 查詢(xún)?cè)O(shè)備列表與通道狀態(tài)設(shè)備添加成功之后項(xiàng)目代碼里通常要做的第一件業(yè)務(wù)操作就是“查詢(xún)?cè)O(shè)備列表”。開(kāi)放平臺(tái)提供了設(shè)備列表相關(guān)的接口傳入 accessToken可以拿到當(dāng)前賬號(hào)下的設(shè)備信息一般包括設(shè)備序列號(hào)、設(shè)備名稱(chēng)、設(shè)備狀態(tài)、通道列表這些字段。我一般會(huì)在代碼里把設(shè)備列表和通道狀態(tài)打印出來(lái)因?yàn)檫@是驗(yàn)證“設(shè)備接入是否真正生效”的最直接證據(jù)。設(shè)備狀態(tài)status通常用 1 和 0 來(lái)表示在線和離線通道列表里的通道號(hào)channelNo則是后面取流時(shí)必填的參數(shù)。通道的概念要稍微解釋一下。普通家用攝像頭通常有 1 個(gè)通道也就是一路畫(huà)面但對(duì)于 NVR 這類(lèi)設(shè)備一個(gè) NVR 下可能掛接多路 IPC每個(gè)通道對(duì)應(yīng)一路攝像頭。所以查詢(xún)出來(lái)的設(shè)備下會(huì)有一個(gè) channel 數(shù)組里面的 channelNo 從 1 開(kāi)始編號(hào)。取流的時(shí)候你不僅要告訴平臺(tái)“我要看哪臺(tái)設(shè)備”還要告訴它“我要看這臺(tái)設(shè)備的第幾路畫(huà)面”。在調(diào)試階段我會(huì)在庫(kù)里把 deviceSerial 和 channelNo 一起保存下來(lái)作為后面調(diào)用直播地址接口的基礎(chǔ)數(shù)據(jù)。這里有個(gè)小經(jīng)驗(yàn)設(shè)備序列號(hào)的大小寫(xiě)必須原樣保留很多人在手抄或復(fù)制中把大小寫(xiě)搞錯(cuò)了導(dǎo)致查詢(xún)不到設(shè)備。英文字母 O 和數(shù)字 0、字母 I 和數(shù)字 1 也是重災(zāi)區(qū)建議直接從設(shè)備列表接口返回的數(shù)據(jù)里復(fù)制粘貼而不是人肉抄錄。2.4 設(shè)備上線的判斷標(biāo)準(zhǔn)與排查思路設(shè)備加入賬號(hào)后不代表立刻就能取流。你還需要確認(rèn)設(shè)備狀態(tài)是“在線”。在控制臺(tái)的設(shè)備管理頁(yè)面里你會(huì)看到設(shè)備的在線狀態(tài)在線才說(shuō)明設(shè)備已經(jīng)成功連上云端具備取流條件。實(shí)際項(xiàng)目里我發(fā)現(xiàn)設(shè)備離線的原因大致有這么幾類(lèi)設(shè)備所在網(wǎng)絡(luò)無(wú)法訪問(wèn)外網(wǎng)、設(shè)備被斷電、Wi-Fi 信號(hào)弱導(dǎo)致頻繁重連、NTP 時(shí)間不對(duì)導(dǎo)致設(shè)備鑒權(quán)失敗。螢石云設(shè)備上云依賴(lài)公網(wǎng)連接如果項(xiàng)目部署在比較封閉的內(nèi)網(wǎng)環(huán)境、設(shè)備只連著局域網(wǎng)那它是無(wú)法跟云端建立長(zhǎng)連接的直播流當(dāng)然出不來(lái)。判斷設(shè)備是否在線不要只看控制臺(tái)頁(yè)面最好在代碼里循環(huán)檢測(cè)設(shè)備列表接口返回的 status 字段。我在對(duì)接某項(xiàng)目的時(shí)候曾經(jīng)遇到頁(yè)面顯示在線但接口返回“設(shè)備不在線”的情況。后來(lái)發(fā)現(xiàn)是因?yàn)轫?yè)面有緩存延遲真實(shí)的狀態(tài)以接口返回為準(zhǔn)。所以業(yè)務(wù)邏輯里要盡量以接口數(shù)據(jù)做實(shí)時(shí)狀態(tài)判斷不要依賴(lài)人工去看頁(yè)面。3. 直播流管理從取流地址到播放器落地3.1 直播地址是怎么生成的設(shè)備在線之后直播流管理就進(jìn)入關(guān)鍵環(huán)節(jié)從平臺(tái)獲取一路可以播放的直播地址。螢石開(kāi)放平臺(tái)直播流管理的核心接口大致是這樣傳入 accessToken、設(shè)備序列號(hào) deviceSerial、通道號(hào) channelNo以及想要的協(xié)議類(lèi)型 protocol平臺(tái)返回一條帶鑒權(quán)的 URL 和過(guò)期時(shí)間。我把直播地址的生成過(guò)程理解為“平臺(tái)按需簽發(fā)的門(mén)票”。你告訴平臺(tái)想看哪臺(tái)設(shè)備的哪個(gè)通道、想用什么協(xié)議看、想看多久平臺(tái)就給你生成一張對(duì)應(yīng)“門(mén)票”URL。這張門(mén)票帶有時(shí)效和簽名信息播放器拿這個(gè) URL 去拉流平臺(tái)校驗(yàn)通過(guò)后就把視頻流放出來(lái)。這里有一個(gè)容易混淆的地方直播地址接口返回的是“地址”并不是“視頻流本身”。相當(dāng)于平臺(tái)給你指了一個(gè)“哪里能拿到流”的方向真正拉流是播放器基于這個(gè)地址去做的。所以調(diào)試時(shí)不要只盯著接口返回是否成功還要用播放器實(shí)際拉流驗(yàn)證返回的 URL 是否可播。關(guān)于協(xié)議類(lèi)型我通常見(jiàn)到的有 RTMP、HLS、RTSP、HTTPS-FLV 這幾種。選擇哪種取決于你要在什么端播放不能一概而論。下面我會(huì)展開(kāi)講一下協(xié)議選型。3.2 RTMP/HLS/RTSP/HTTPS-FLV 怎么選這是我被問(wèn)得最多的問(wèn)題之一。很多剛接觸螢石開(kāi)放平臺(tái)的人看到返回的地址后綴不一樣就會(huì)擔(dān)心是不是選錯(cuò)了協(xié)議。其實(shí)這幾個(gè)協(xié)議沒(méi)有絕對(duì)的優(yōu)劣關(guān)鍵是匹配你的播放端和業(yè)務(wù)場(chǎng)景。協(xié)議延遲水平播放端適配典型場(chǎng)景HLS中等秒級(jí)網(wǎng)頁(yè)、移動(dòng)端兼容性好通用監(jiān)控回放、低交互需求RTMP低1-2秒PC播放器、部分服務(wù)端轉(zhuǎn)推友好傳統(tǒng)直播平臺(tái)轉(zhuǎn)推RTSP極低毫秒級(jí)專(zhuān)業(yè)播放器/VLC局域網(wǎng)或?qū)I(yè)客戶(hù)端HTTPS-FLV低1-3秒網(wǎng)頁(yè)、移動(dòng)端支持較好Web端低延遲播放我自己的習(xí)慣是如果做 Web 端監(jiān)控頁(yè)面優(yōu)先考慮 HTTPS-FLV 或 HLS如果用 VLC 這類(lèi)本地播放器調(diào)試RTSP 和 RTMP 都很直觀如果要做微信小程序端播放則要看小程序 live-player 組件的協(xié)議支持情況通常 HLS 兼容性較好部分場(chǎng)景可用 RTMP。這里插一句不要迷信“延遲越低越好”因?yàn)榈脱舆t協(xié)議往往對(duì)網(wǎng)絡(luò)和播放器要求更高出現(xiàn)花屏、卡頓的概率也會(huì)增加。我見(jiàn)過(guò)一個(gè)客戶(hù)執(zhí)意要 RTSP 方案來(lái)做手機(jī)端觀看結(jié)果在 4G 網(wǎng)絡(luò)下頻繁斷流最后還是換成了 HLS。選協(xié)議前先明確需求你的用戶(hù)是用什么終端看、對(duì)延遲的容忍度是多少、網(wǎng)絡(luò)環(huán)境是否可控這幾個(gè)問(wèn)題定了再選協(xié)議。3.3 把直播流地址接到播放器里拿到直播地址之后下一步就是播放器驗(yàn)證。我調(diào)試監(jiān)控流最常用的工具是 VLC 和 ffplay因?yàn)樗鼈儾恍枰獙?xiě)代碼打開(kāi)地址就能播。比如你拿到了一個(gè) RTSP 地址直接在 VLC 里打開(kāi)網(wǎng)絡(luò)串流輸入地址回車(chē)幾分鐘內(nèi)就能確認(rèn)這個(gè)流是否正常。如果你是在自己的應(yīng)用里集成那就要用播放器 SDK 或前端播放庫(kù)。螢石官方有自家的播放器組件同時(shí)你也可以根據(jù)協(xié)議選用通用方案。比如 HLS 在 Web 端可以用 hls.jsFLV 流可以用 flv.js小程序端則用 live-player 組件。這些方案之間沒(méi)有絕對(duì)的好與壞更多是看你的播放端技術(shù)棧。我建議項(xiàng)目一開(kāi)始就把播放器做成一個(gè)獨(dú)立的模塊配置文件里能切換協(xié)議和地址。因?yàn)樵诤罄m(xù)聯(lián)調(diào)中你很有可能會(huì)因?yàn)榫W(wǎng)絡(luò)原因從 RTMP 切到 FLV或者從 HLS 切到 WebRTC 方案播放器可配置會(huì)省掉很多不必要的重構(gòu)。接播放器的時(shí)候還有一個(gè)地方要留意直播 URL 里通常帶鑒權(quán)參數(shù)這些參數(shù)在拼接進(jìn)播放器之前一定要做必要的 URL 編碼處理否則播放器解析地址的時(shí)候會(huì)截?cái)嗷蛘呗﹨⒈憩F(xiàn)為“視頻加載不出來(lái)但接口返回明明是成功的”。3.4 直播地址的有效期與防盜鏈處理直播流管理最容易忽略的就是地址有效期。螢石開(kāi)放平臺(tái)生成的直播地址并不是永久有效的這個(gè)設(shè)計(jì)本意是防止地址被惡意盜用但如果你沒(méi)有做地址的定時(shí)刷新管理就會(huì)出現(xiàn)“用戶(hù)看著看著畫(huà)面突然黑掉”的問(wèn)題。我在實(shí)際項(xiàng)目里見(jiàn)過(guò)不少這樣的情況開(kāi)發(fā)者把直播地址存在數(shù)據(jù)庫(kù)里第二天再拿出去播結(jié)果全斷了。這是因?yàn)榈刂愤^(guò)期了。解決方案一般是兩種思路一是每次播放時(shí)都即時(shí)調(diào)用接口獲取新地址不落庫(kù)二是做地址緩存刷新機(jī)制在地址過(guò)期前重新獲取并替換??紤]到直播地址接口調(diào)用也有頻率限制我傾向于采用“按需獲取 短時(shí)緩存”的策略。當(dāng)用戶(hù)進(jìn)入某個(gè)監(jiān)控頁(yè)面時(shí)后端才去拿直播地址返回給前端緩存時(shí)間控制在地址有效期內(nèi)。這樣既不會(huì)頻繁調(diào)用接口也能保證用戶(hù)每次看到的地址都是新鮮可用的。另外要強(qiáng)調(diào)一點(diǎn)拿到直播地址接口返回后不要把 expires 時(shí)間字段丟了。前端可以在播放前檢查地址是否快要過(guò)期快過(guò)期時(shí)就重新向后端要地址避免播放中斷。這個(gè)體驗(yàn)細(xì)節(jié)在做過(guò)幾個(gè)項(xiàng)目之后你會(huì)意識(shí)到它有多重要。4. 我踩過(guò)的坑常見(jiàn)問(wèn)題與排查經(jīng)驗(yàn)4.1 序列號(hào)、驗(yàn)證碼相關(guān)的坑怎么避開(kāi)序列號(hào)和驗(yàn)證碼問(wèn)題是我在設(shè)備接入階段遇到最多的一類(lèi)坑。先說(shuō)序列號(hào)。SN 是設(shè)備的唯一標(biāo)識(shí)很多設(shè)備因?yàn)殚L(zhǎng)期放在戶(hù)外機(jī)身標(biāo)簽褪色或者磨損抄錄時(shí)很容易看錯(cuò)字符。更麻煩的是有些項(xiàng)目的設(shè)備列表是從 Excel 表格里導(dǎo)出來(lái)的表格里的 SN 前導(dǎo)空格、字母大小寫(xiě)、全半角括號(hào)都會(huì)導(dǎo)致接口查不到設(shè)備。我在做一個(gè)連鎖門(mén)店項(xiàng)目時(shí)就曾經(jīng)因?yàn)?SN 里的字母 I 被誤寫(xiě)成數(shù)字 1導(dǎo)致門(mén)店設(shè)備一直在設(shè)備列表里查不到。折騰了一個(gè)晚上最后逐字符比對(duì)才找出問(wèn)題。我的建議是所有設(shè)備信息盡量通過(guò)接口拉取后直接落庫(kù)不要人工維護(hù) SN 表格。如果需要人工錄入前端要做格式校驗(yàn)比如限制只能輸入字母數(shù)字、統(tǒng)一轉(zhuǎn)為大寫(xiě)、去掉前后空格。驗(yàn)證碼的問(wèn)題則更隱蔽。驗(yàn)證碼是設(shè)備在云信令節(jié)點(diǎn)認(rèn)證時(shí)用的不是所有設(shè)備都一直印在機(jī)身上。有些設(shè)備出廠后驗(yàn)證碼可能被管理員在 App 里修改過(guò)所以你拿著機(jī)身標(biāo)簽上的驗(yàn)證碼去添加反而提示錯(cuò)誤。這時(shí)候需要先通過(guò)已有渠道確認(rèn)驗(yàn)證碼是否被重置過(guò)。如果確認(rèn)不了只能通過(guò)設(shè)備重置恢復(fù)出廠重新獲取驗(yàn)證碼。4.2 設(shè)備離線、通道號(hào)不對(duì)導(dǎo)致取流失敗取流失敗的排查我一般先看設(shè)備在不在線。很多次同事跟我說(shuō)“取流失敗”我第一反應(yīng)不是去看直播地址接口而是先查設(shè)備列表接口看 status 是不是 1。如果設(shè)備離線直播地址接口大概率會(huì)提示設(shè)備不在線這時(shí)候花時(shí)間去分析 URL 是沒(méi)有意義的。設(shè)備在線但取流還是失敗就要看通道號(hào)。NVR 設(shè)備在添加不同 IPC 通道后通道號(hào)可能是按添加順序分配的也可能在配置界面手動(dòng)調(diào)整過(guò)。如果不核對(duì)通道號(hào)和實(shí)際畫(huà)面的對(duì)應(yīng)關(guān)系就會(huì)出現(xiàn)“視頻流能拉到但畫(huà)面不是預(yù)期那個(gè)攝像頭”的情況。我的經(jīng)驗(yàn)是初始化階段就把設(shè)備列表接口返回的通道數(shù)組完整打印出來(lái)跟現(xiàn)場(chǎng)畫(huà)面逐一核對(duì)再錄入數(shù)據(jù)庫(kù)中不要等上線之后再來(lái)回排查。還有一種情況是設(shè)備在線、通道號(hào)也對(duì)但直播地址接口返回的 URL 在播放器里播不出來(lái)。這時(shí)候我會(huì)先試 VLC 手動(dòng)播一下。如果 VLC 也播不出來(lái)就換個(gè)協(xié)議類(lèi)型再取一次地址試試。有些設(shè)備或網(wǎng)絡(luò)環(huán)境下某個(gè)協(xié)議的流會(huì)被防火墻或運(yùn)營(yíng)商給攔掉換一個(gè)協(xié)議往往就通了。4.3 播放黑屏、卡頓、花屏怎么排查黑屏和卡頓的問(wèn)題發(fā)生在“播放”這一段的概率遠(yuǎn)大于“取流”這一段。我先說(shuō)黑屏如果直播地址接口返回成功URL 放入播放器后畫(huà)面一直黑屏很大概率是播放器和協(xié)議不匹配。比如你拿了 HLS 地址但是播放器對(duì) HLS 的支持有問(wèn)題或者拿了 RTSP 地址播放器所在網(wǎng)絡(luò)對(duì) RTSP 端口不通??D和花屏則要先分清是設(shè)備上傳帶寬不足還是播放端下行帶寬不足。很多家用攝像頭在公網(wǎng)上傳本身就受限當(dāng)碼率較高而網(wǎng)絡(luò)上行不穩(wěn)定時(shí)平臺(tái)輸出的流就會(huì)出現(xiàn)花屏。排查辦法是把直播地址拿到一個(gè)網(wǎng)絡(luò)更好的環(huán)境里播如果流暢那就是上行或中間鏈路的問(wèn)題如果還是卡頓就要考慮降低碼率或換協(xié)議。還有一個(gè)小細(xì)節(jié)螢石開(kāi)放平臺(tái)直播流默認(rèn)的編碼參數(shù)是設(shè)備側(cè)的有些老設(shè)備默認(rèn)編碼是 H.264有些新設(shè)備支持 H.265。如果你在網(wǎng)頁(yè)端用瀏覽器播放 H.265 格式的流可能會(huì)遇到兼容性問(wèn)題因?yàn)椴簧贋g覽器對(duì) H.265 的支持并不好。這時(shí)候要么在平臺(tái)或設(shè)備側(cè)切編碼格式要么改用原生播放器方案。4.4 排查問(wèn)題的幾個(gè)好習(xí)慣踩坑踩多了我慢慢養(yǎng)成一套自己的排查習(xí)慣。第一所有接口請(qǐng)求和響應(yīng)日志必須留詳細(xì)尤其是 accessToken、deviceSerial、channelNo、協(xié)議類(lèi)型、請(qǐng)求時(shí)間、返回碼。很多問(wèn)題其實(shí)在日志里一眼就能看出來(lái)比如 token 過(guò)期了、設(shè)備號(hào)打錯(cuò)了、參數(shù)格式不對(duì)。沒(méi)有日志排查就像盲人摸象。第二先分清是“平臺(tái)的問(wèn)題”還是“自己的問(wèn)題”。拿到一個(gè)報(bào)錯(cuò)先看返回碼在官方文檔里的含義再對(duì)照自己的請(qǐng)求參數(shù)。很多時(shí)候不是你代碼寫(xiě)得不對(duì)而是文檔里要求的字段你沒(méi)傳全或者格式不對(duì)。開(kāi)放平臺(tái)對(duì)這些字段是非常敏感的多一個(gè)空格、少一個(gè)字符都可能報(bào)參數(shù)錯(cuò)誤。第三做技術(shù)驗(yàn)證時(shí)要敢于用最笨的工具。不要一上來(lái)就在自己的播放器代碼里加斷點(diǎn)先用 VLC 手動(dòng)拉流驗(yàn)證地址是否有效有效就說(shuō)明平臺(tái)這一側(cè)是通的問(wèn)題在播放器代碼無(wú)效就說(shuō)明取流環(huán)節(jié)有異常往上排查。這個(gè)次序能幫你快速收斂問(wèn)題范圍。大家不要覺(jué)得這些是“基本功”就掉以輕心。我在實(shí)際項(xiàng)目中見(jiàn)過(guò)不少莫名其妙的故障最后定位下來(lái)的原因其實(shí)都特別基礎(chǔ)比如設(shè)備掉線、密鑰輪換后沒(méi)有及時(shí)更新、地址過(guò)期后前端還在死磕舊地址。這些問(wèn)題的共同特點(diǎn)就是在接入階段沒(méi)把鏈路搞清楚在管理階段沒(méi)把生命周期管起來(lái)。最后再分享一個(gè)我自己的習(xí)慣每次對(duì)接螢石開(kāi)放平臺(tái)的音視頻項(xiàng)目我都會(huì)在項(xiàng)目初期做一個(gè)小工具頁(yè)面專(zhuān)門(mén)用來(lái)展示賬號(hào)下的設(shè)備列表、通道狀態(tài)、在線狀態(tài)并且能一鍵獲取某臺(tái)設(shè)備當(dāng)前最新的直播地址。這個(gè)小工具看起來(lái)不起眼但它幫我省下了大量“幫客戶(hù)驗(yàn)證設(shè)備到底能不能看”的時(shí)間。設(shè)備接入和直播流管理說(shuō)到底是鏈路、數(shù)據(jù)和管理的問(wèn)題把這三樣理清了項(xiàng)目的穩(wěn)定性基本就有了底。