醉凝眸 2020-04-04 10.48.52 - 01.gif
序一:我看了看Xcode代碼,又看了看右上角時間牧牢,emmm看锉,想了下就不詳細敘述了姿锭,走一遍大概邏輯以作提醒!
序二:單人音視頻功能實現(xiàn)依賴于GoogleWebRTC和SocketRocket框架伯铣;
序三:多人音視頻功能分mesh模式呻此、SFU模式、MCU模式腔寡,本項目采用的是基于SFU模式的Kurento焚鲜,框架為KurentoToolbox,相關區(qū)別請看鏈接:
傳送門
序四:懶得麻煩········懶······
序五:因為只講邏輯放前,不講具體實現(xiàn)代碼忿磅,所以主要記錄一些踩過的坑
一、踩過的坑
1.因為iOS的代碼項目在goole上面是后進的人發(fā)offer凭语、先進的人發(fā)oanswer葱她,而常規(guī)的單人音視頻是先進的人打個后進的人,也就是需要先進的人發(fā)offer叽粹、后進的人發(fā)answer览效;實現(xiàn)邏輯:將peer和newPeer信令的邏輯對調,A進來收到peer信令啥事也不干虫几,然后當b進來后锤灿,A收到newPeer信令后,創(chuàng)建本地流辆脸、生成peerconnection并添加本地流但校,發(fā)送offer;B進來收到peer信令創(chuàng)建本地流啡氢、生成peerconnection并添加本地流状囱;
2.和安卓端互通問題:iPhone和iPhone可以后,和安卓端聯(lián)調時候倘是,在發(fā)送offer和answer時候回報錯FingerPrint啥啥啥的亭枷,打印查詢sdp后發(fā)現(xiàn)原因是安卓端底層代碼此協(xié)議默認關閉(安卓端是有個if-else,默認走得是另外一個協(xié)議)導致sdp中fingerPrint不通過搀崭,解決方案移動端統(tǒng)一增加屬性值DtlsSrtpKeyAgreement為yes叨粘;
3.斷網重連問題之重連實現(xiàn):整體斷網重連由于webSocket代碼心跳不能百分百拉回peerconnection(也就是說RTCIceConnectionState經過斷網重連后不能從RTCIceConnectionStateFailed狀態(tài)切換到RTCIceConnectionStateConnected狀態(tài)),所以采用的重走流程方案瘤睹,即收到didFailWithError代理回調時候升敲,判定條件(如果rtcIsFail且非主動掛斷且ReachabilityStatus>0),條件成立轰传,重新初始化socket驴党,鏈接服務器,didOpen后發(fā)送reconnect信令給服務器获茬,然后重走peer及后續(xù)信令港庄,重新拉回peerconnection鏈接(因為本地流倔既、peerconnection、iceServer和RTCPeerConnectionFactory都是全局變量攘轩,而且都做了判空處理叉存,所以整個流程其實就是相當于重新初始化了下socket服務器码俩,然后信令走了一遍具體信令里面的操作其實相當于沒走)度帮;
4.斷網重連問題之和安卓端的適配:因為谷歌項目中peerconnection是局部變量,在重連時候重走流程時候稿存,iPhone和iPhone手機是完全沒問題的笨篷;但是和安卓就有點蛋疼了,因為安卓創(chuàng)建本地流瓣履、生成peerconnection耽誤時間率翅,所以安卓邏輯是在進入頁面時進行這些操作,為了適配安卓手機袖迎,iOS端把peerconnection也初始化全局冕臭,這樣子整個移動端相當于peerconnection都是全局變量,重連時候不需要再重新創(chuàng)建peerconnection燕锥,直接恢復已有的peerconnection辜贵!
5.斷網重連問題之斷網提示:手動創(chuàng)建定時器,新建心跳heart信令發(fā)送給rtc服務器归形,哪方網絡不好時候托慨,rtc服務器會返回給對面_poor_connection信令用來顯示對應的網絡提示;
6.大坑之音視頻鏈接音頻ok視頻卻黑屏問題:經測試暇榴,在iPhone7以下機型厚棵,音視頻ok;7以上機型蔼紧,音頻ok視頻黑屏問題婆硬,嘗試過修改sdp內容的編解碼、網路帶寬和碼率等奸例;最終解決方案定位統(tǒng)一視頻分辨率彬犯!
7.多網絡音視頻互通:rtc服務器同學在stun打洞服務器的基礎上新增turn服務器,移動端創(chuàng)建iceServer時候兩個都加上!
8.視頻橫屏問題:didChangeVideoSize代理回調中哩至,判斷寬大于高時候調換一下躏嚎,然后橫豎比按照videoView.bounds.size.height/videoFrame.size.height值對比;
9.單人音視頻前后置攝像頭切換導致的本地和遠程視頻流鏡像問題:保持前置攝像頭鏡像(即本地視頻預覽)ok,修改后置攝像頭(即遠程視頻預覽)菩貌;創(chuàng)建remoteVideoView設置transform的scale為(-1,1),和安卓端適配時卢佣,在點擊切換攝像頭時候發(fā)送change_camera信令,收到change_camera信令時候箭阶,判定如果攝像頭是back就設置遠程預覽頁為Identity虚茶,如果否就設置遠程預覽頁scale為(-1,1)戈鲁;
10.群聊音視頻的鏡像問題:因為群聊音視頻顯示在接聽頁面上的流都是放在遠程預覽頁remoteVideoView上顯示的,所以跟單人音視頻一樣嘹叫,將遠程預覽頁的transform的scale設置為(-1,1)即可婆殿!
11.emmmmm··················,忘了罩扇,想起來了有緣在寫婆芦,下班了,溜了溜了喂饥!
二消约、代碼實現(xiàn)
1.CocoaPods導入GoogleWebRTC和SocketRocket
2.WebRTCHelper單列類引用
3.主頁面遠程視頻預覽頁和本地視頻預覽頁創(chuàng)建(RTCEAGLVideoView和RTCCameraPreviewView)
4.鏈接webrtc服務器,代碼部分:
[[WebRTCHelper shareInstance] connectServer:@"rtc服務器地址" port:@"rtc服務器端口" room:@"你的房間"];
5.鏈接服務器员帮,初始化websocket或粮,鏈接成功,會回調webSocketDidOpen代理方法捞高;鏈接失敗氯材,會回調didFailWithError代理方法,并自動調用didCloseWithCode代理硝岗;
6.鏈接成功后氢哮,后續(xù)會進行七大常規(guī)信令交涉(join、peer辈讶、newPeer命浴、iceCandidate、offer贱除、answer生闲、leave七個信令),接收此七大常規(guī)信令的方法為didReceiveMessage代理方法
7.鏈接成功后月幌,發(fā)送join信令(表示該用戶加入房間)碍讯,代碼:
8.用戶A join房間成功后,會收到rtc服務器返回的peer信令扯躺,此信令代表用戶自己進入成功捉兴,每一個用戶加入房間都會收到peer信令用來表示自己加入成功;
9.加入房間后录语,如果此時有新用戶B進入房間(新用戶B加入流程也是5倍啥、6、7澎埠、8步)虽缕,之前加入房間的用戶A會收到newPeer信令,然后進行創(chuàng)建本地音視頻流蒲稳、生成peerconnection氮趋、peerconnection添加本地音視頻流伍派、創(chuàng)建并發(fā)送offer,大致代碼:
10.新用戶B會收到rtc服務器轉發(fā)的用戶A的offer信令剩胁,接到offer信令后生成answer信令并發(fā)送诉植,大致代碼:
11.用戶A會收到rtc服務器轉發(fā)的新用戶B的answer信令
12.在A、B兩用戶交涉過程中昵观,會通過打洞iceServer的方式晾腔,進行點與點的信令交涉,也就是iceCandidate信令:
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者