中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

鑫三科技網(wǎng)站設(shè)計(jì)百度關(guān)鍵詞推廣費(fèi)用

鑫三科技網(wǎng)站設(shè)計(jì),百度關(guān)鍵詞推廣費(fèi)用,相冊(cè)管理網(wǎng)站模板,網(wǎng)站建設(shè)咨詢(xún)推薦導(dǎo)讀 本系列文章將從客戶(hù)端、服務(wù)器以及音視頻編碼優(yōu)化三個(gè)層面,介紹如何基于WebRTC構(gòu)建視頻連麥系統(tǒng)。希望通過(guò)這一系列的講解,幫助開(kāi)發(fā)者更全面地了解 WebRTC 的核心技術(shù)與實(shí)踐應(yīng)用。 背景 在文章《B站在實(shí)時(shí)音視頻技術(shù)領(lǐng)域的探索與實(shí)踐》中&#xff…

導(dǎo)讀?

本系列文章將從客戶(hù)端、服務(wù)器以及音視頻編碼優(yōu)化三個(gè)層面,介紹如何基于WebRTC構(gòu)建視頻連麥系統(tǒng)。希望通過(guò)這一系列的講解,幫助開(kāi)發(fā)者更全面地了解 WebRTC 的核心技術(shù)與實(shí)踐應(yīng)用。

背景

在文章《B站在實(shí)時(shí)音視頻技術(shù)領(lǐng)域的探索與實(shí)踐》中,提到了直播行業(yè)從傳統(tǒng)娛樂(lè)直播發(fā)展到教育、電商等新形式,用戶(hù)對(duì)實(shí)時(shí)互動(dòng)直播的需求增加。B站基于WebRTC的開(kāi)發(fā)了一套視頻連麥系統(tǒng):這套系統(tǒng)優(yōu)先選擇UDP協(xié)議以保證低延遲,必要時(shí)降級(jí)為T(mén)CP;且使用前向糾錯(cuò)和后向糾錯(cuò)結(jié)合解決丟包問(wèn)題;并根據(jù)網(wǎng)絡(luò)狀況動(dòng)態(tài)調(diào)整音視頻碼率和發(fā)送速率,確保實(shí)時(shí)性和畫(huà)質(zhì)。

但是這套視頻連麥系統(tǒng)是提取了WebRTC的部分模塊組合而成的,對(duì)于上游代碼倉(cāng)庫(kù)的后續(xù)升級(jí)有較高維護(hù)成本,且與使用高層級(jí)抽象接口的Web瀏覽器端無(wú)法很好兼容互通。所以在使用了一段時(shí)間后,我們決定對(duì)其進(jìn)行重構(gòu),改為使用WebRTC的標(biāo)準(zhǔn)應(yīng)用編程接口(API)進(jìn)行開(kāi)發(fā)。

本文為上篇,將會(huì)著重介紹終端上如何使用WebRTC的標(biāo)準(zhǔn)應(yīng)用編程接口來(lái)接入視頻連麥業(yè)務(wù)。

信令和直接連接

WebRTC的握手主要通過(guò)“信令交換”來(lái)完成?!靶帕睢笔且粋€(gè)相對(duì)抽象的術(shù)語(yǔ),在實(shí)際操作中,可以用一個(gè)簡(jiǎn)化的例子來(lái)解釋。我現(xiàn)在有兩個(gè)主播需要進(jìn)行視頻連麥,一方主播已經(jīng)準(zhǔn)備好了攝像頭畫(huà)面、壓縮攝像頭畫(huà)面的編碼器、麥克風(fēng)音頻、壓縮麥克風(fēng)音頻的編碼器,以及用于數(shù)據(jù)傳輸?shù)膮f(xié)議和網(wǎng)絡(luò)地址。進(jìn)行視頻連麥的另一方主播,需要相應(yīng)地準(zhǔn)備好可以接收數(shù)據(jù)的網(wǎng)絡(luò)地址、可以解析傳輸協(xié)議的解析器、以及用于解碼這些音視頻數(shù)據(jù)的解碼器。

因此,發(fā)送端的主播需要告訴接收端的主播自己即將開(kāi)啟的視頻和音頻分別使用了哪種編碼格式,并通過(guò)哪個(gè)IP地址和端口進(jìn)行數(shù)據(jù)發(fā)送。同時(shí),接收端的主播也需要告知發(fā)送端的主播自己可以接收音頻和視頻,并通過(guò)什么IP地址和端口接收數(shù)據(jù)。雙方在交換了這些信息后,發(fā)送端的主播就可以將數(shù)據(jù)發(fā)送到接收端的主播的IP地址。通過(guò)這一過(guò)程,雙方可以互相接收對(duì)方的聲音和畫(huà)面,從而實(shí)現(xiàn)視頻連麥。

上述流程雖然理想,但實(shí)際操作中可能面臨一些挑戰(zhàn)。例如,接收端的主播無(wú)法解析發(fā)送端的數(shù)據(jù)或解碼其音視頻,這種情況該如何處理?為了盡量減少這種問(wèn)題的發(fā)生,實(shí)際使用中,發(fā)送端通常會(huì)一次性列出多種不同格式的編碼。接收端則從中選擇其能識(shí)別的格式并通知發(fā)送端。發(fā)送端隨后僅使用雙方兼容的編碼格式進(jìn)行傳輸。同樣,對(duì)于傳輸協(xié)議,假如發(fā)送端能傳輸前向糾錯(cuò)的數(shù)據(jù)包以改善高延遲網(wǎng)絡(luò)下的通信質(zhì)量,但接收端無(wú)法識(shí)別這些數(shù)據(jù)包,那么傳輸這些數(shù)據(jù)包反而會(huì)占用網(wǎng)絡(luò)資源。

在WebRTC中,“信令”是一種用于記錄和傳輸會(huì)話描述協(xié)議(Session Description Protocol, SDP)的機(jī)制。SDP最終表現(xiàn)為一個(gè)包含編碼格式、傳輸協(xié)議、IP地址、端口及一些附加信息的長(zhǎng)字符串。

當(dāng)需要建立WebRTC通信連接時(shí),兩個(gè)用戶(hù)會(huì)互相傳遞這樣一個(gè)字符串。一個(gè)用戶(hù)將該字符串發(fā)送給另一個(gè)用戶(hù),接收方隨后也會(huì)返回一個(gè)類(lèi)似的字符串。通過(guò)這個(gè)過(guò)程,雙方就能互相了解使用什么格式和協(xié)議,通過(guò)哪個(gè)IP地址和端口進(jìn)行數(shù)據(jù)傳輸,從而實(shí)現(xiàn)通信連接。

在此過(guò)程中,想要變更傳輸細(xì)節(jié)的一方會(huì)發(fā)送一個(gè)稱(chēng)為Offer的SDP字符串,另一方在解析Offer后修改本地狀態(tài),隨后生成Answer并傳回。這種來(lái)回交換信令的過(guò)程被稱(chēng)為協(xié)商(negotiate)。理解這一過(guò)程時(shí),可以將其類(lèi)比為一次雙方狀態(tài)同步的遠(yuǎn)程過(guò)程調(diào)用,這或許會(huì)更容易理解。

以實(shí)際例子為例,用戶(hù)A的SDP字符串中詳細(xì)列出了以下信息:音視頻的收發(fā)地址為10.0.0.2,端口為17723;傳輸協(xié)議使用SRTP,視頻的編碼和解碼均使用H.264,SSRC為114514(由于音視頻共用一個(gè)端口進(jìn)行收發(fā),因此需要一個(gè)“編號(hào)”來(lái)區(qū)分發(fā)出的數(shù)據(jù)包是音頻還是視頻,這個(gè)編號(hào)就是SSRC),音頻的編碼和解碼均使用OPUS。用戶(hù)B收到該SDP字符串后,會(huì)解析其中的內(nèi)容,從而知道往10.0.0.2的17723端口發(fā)送何種數(shù)據(jù),確保用戶(hù)A能正常處理。然后,用戶(hù)B也會(huì)回傳一個(gè)類(lèi)似的SDP字符串,包含上述信息。用戶(hù)A同樣會(huì)解析該字符串,確保后續(xù)發(fā)送的音視頻數(shù)據(jù)能夠被用戶(hù)B接收并正常處理。

以偽代碼表示,由一臺(tái)服務(wù)器在兩個(gè)用戶(hù)之間中轉(zhuǎn)數(shù)據(jù),流程大致如下:

用戶(hù)A {pc = 創(chuàng)建RTCPeerConnection對(duì)象給pc添加視頻收發(fā)器(Transceiver)用于發(fā)送或接收給pc添加音頻收發(fā)器(Transceiver)用于發(fā)送或接收offer = await pc.CreateOffer() // offer里包含了IP地址、端口和收發(fā)器能使用的協(xié)議、編碼等信息await pc.SetLocalDescription(offer)等待IP地址、端口等信息(即:Candidate)獲取完成offer = pc.GetLocalDescription()通過(guò)服務(wù)器中轉(zhuǎn)將offer發(fā)送給B
}
用戶(hù)B {offer = 收到Offerpc = 創(chuàng)建RTCPeerConnection對(duì)象監(jiān)聽(tīng)pc的創(chuàng)建新收發(fā)器的事件await pc.SetRemoteDescription(offer)answer = await pc.CreateAnswer()await pc.SetLocalDescription(answer)等待IP地址、端口等信息獲取完成answer = pc.GetLocalDescrption()通過(guò)服務(wù)器中轉(zhuǎn)將answer發(fā)送給Apc.等待連接成功的事件
}
用戶(hù)A {answer := // 收到answerpc.SetRemoteDescription(answer)pc.等待連接成功的事件
}

在收到連接成功的事件之后,就可以通過(guò)收發(fā)器的接口和回調(diào)發(fā)送和接收音視頻數(shù)據(jù)了。

因?yàn)閃ebRTC是一種比較成熟的技術(shù),相關(guān)的示例資料在網(wǎng)上也好找,能解釋這個(gè)字符串里哪些代表什么意思,但篇幅特別長(zhǎng),這里就不贅述了。

選擇性轉(zhuǎn)發(fā)服務(wù)器

在業(yè)務(wù)玩法逐漸變得復(fù)雜之后,這種用戶(hù)之間的連接形式就應(yīng)付不過(guò)來(lái)了。經(jīng)??粗辈サ男』锇槎贾?#xff0c;網(wǎng)絡(luò)直播的視頻連麥會(huì)出現(xiàn)人傳人的現(xiàn)象:一開(kāi)始是兩個(gè)人,然后變成三個(gè),四個(gè)...九個(gè),越來(lái)越多。如果連麥?zhǔn)怯脩?hù)之間直接連的,假設(shè)主播甲乙丙丁在視頻連麥,主播甲就要把自己的音視頻數(shù)據(jù)發(fā)給乙丙丁發(fā)三遍啊三遍,而且乙丙丁也逃不掉也得這么發(fā)?,F(xiàn)在中國(guó)的家用寬帶大部分是上傳遠(yuǎn)小于下載的,結(jié)果就是人一多就可能又卡又糊了。

鑒于是同樣的數(shù)據(jù)發(fā)這么多遍,如果有一臺(tái)服務(wù)器能幫我把這個(gè)數(shù)據(jù)發(fā)給需要接收的人,那么我自己就只要發(fā)一遍給服務(wù)器就夠了。所以B站就設(shè)計(jì)了這樣的服務(wù)器來(lái)幫用戶(hù)轉(zhuǎn)發(fā)數(shù)據(jù),這樣主播就只要發(fā)一份給服務(wù)器,服務(wù)器發(fā)給另外三個(gè)人,這樣正好適配了前面說(shuō)中國(guó)的家用寬帶大部分是下載遠(yuǎn)大于上傳的特點(diǎn)。

服務(wù)器也運(yùn)行一套WebRTC的模塊,這樣客戶(hù)端連人和連服務(wù)器就沒(méi)什么區(qū)別,也是通過(guò)交換SDP。所以服務(wù)器照常收offer、給客戶(hù)端回answer,客戶(hù)端就能和服務(wù)器連上,不需要區(qū)分對(duì)面是普通人還是服務(wù)器。服務(wù)器用這種方式和所有在同一個(gè)“房間”里連麥的人建立了連接;這個(gè)“房間”內(nèi)的用戶(hù)只和服務(wù)器連接,服務(wù)器在這些人之間有選擇性地轉(zhuǎn)發(fā)數(shù)據(jù)(例如,用戶(hù)A只請(qǐng)求B和C的數(shù)據(jù),那么A的數(shù)據(jù)不會(huì)被發(fā)回來(lái),D的數(shù)據(jù)也不會(huì)發(fā)回給A),通過(guò)這種方式就可以實(shí)現(xiàn)多人連麥了。

關(guān)于選擇性轉(zhuǎn)發(fā)服務(wù)器的細(xì)節(jié),將會(huì)在單獨(dú)的一篇詳細(xì)剖析。

信令狀態(tài)

在由用戶(hù)之間直接連接變成只與服務(wù)器連接之后,會(huì)出現(xiàn)單個(gè)RTCPeerConnection實(shí)例中,使用多個(gè)媒體收發(fā)器來(lái)接收來(lái)自不同視頻連麥對(duì)手的數(shù)據(jù)的需求??紤]到不同的視頻連麥對(duì)手使用的編碼器可能有不同(舉個(gè)例子,電腦性能好的用戶(hù)可以使用AV1編碼來(lái)發(fā)送視頻數(shù)據(jù),而電腦性能一般的用戶(hù)只能使用H.264來(lái)發(fā)送視頻數(shù)據(jù)),并且在一個(gè)視頻連麥的“房間”內(nèi),參與的主播又是可以隨時(shí)進(jìn)出房間,所以不同媒體收發(fā)器需要協(xié)商不同的編解碼設(shè)置,且媒體收發(fā)器要?jiǎng)討B(tài)增加和刪除。在上一節(jié)的偽代碼中演示了如何在兩個(gè)用戶(hù)間創(chuàng)建連接,偽代碼中完成了所有媒體收發(fā)器的創(chuàng)建然后才開(kāi)始使用SDP進(jìn)行協(xié)商,并沒(méi)有涉及連接建立之后再添加或者刪除收發(fā)器的操作。

這邊我們引入一個(gè)新的概念:信令狀態(tài)。在上面的例子中,對(duì)LocalDescription、RemoteDescription進(jìn)行Set操作之后,信令狀態(tài)就會(huì)改變。信令狀態(tài)只能遵循一定的順序變化。一個(gè)最簡(jiǎn)單的典型流程是:

圖片

在這個(gè)信令交換的流程里面,需要重點(diǎn)觀察stable, have-local-offer, have-remote-offer三個(gè)狀態(tài),這個(gè)狀態(tài)的變化,通過(guò)RTCPeerConnection上的signalingstatechange事件可以監(jiān)聽(tīng)變化;通過(guò)signalingState屬性可以獲取狀態(tài);遵循以上流程的話,webrtc就不會(huì)老報(bào)錯(cuò)。同時(shí)negotiationneeded事件指明了是不是需要進(jìn)行信令交換,需要的時(shí)候事件會(huì)觸發(fā)……這么說(shuō)感覺(jué)很難懂,套個(gè)例子好理解點(diǎn)。

如果將狀態(tài)機(jī)和事件引入上述用戶(hù)直接建連的例子中。用戶(hù)A創(chuàng)建了RTCPeerConnection對(duì)象,然后在對(duì)象上添加音頻和視頻收發(fā)器。注意,此時(shí)negotiationneeded事件會(huì)觸發(fā),意味著如果想要連接對(duì)手知道你創(chuàng)建了收發(fā)器,需要和它進(jìn)行一次SDP交換。于是,A這里調(diào)用createOffer方法,生成己方的Offer SDP,并使用setLocalDescription更新本地的會(huì)話描述;此時(shí),RTCPeerConnection的信令狀態(tài)會(huì)變?yōu)閔ave-local-offer。然后,A的Offer SDP通過(guò)網(wǎng)絡(luò)傳輸?shù)竭B接對(duì)手B那邊,B也創(chuàng)建RTCPeerConnection,然后將A的Offer通過(guò)setRemoteDescription設(shè)置進(jìn)去,此時(shí)B的RTCPeerConnection信令狀態(tài)會(huì)變?yōu)閔ave-remote-offer。B調(diào)用createAnswer生成己方的Answer SDP,并使用setLocalDescription更新本地的會(huì)話描述,此時(shí)B的信令狀態(tài)變成stable。B的Answer SDP發(fā)送到A那邊,A使用setRemoteDescription更新遠(yuǎn)程描述(即,連接對(duì)手的描述),A的狀態(tài)也變?yōu)閟table。這樣一次添加收發(fā)器的流程就完成了,并且兩方收發(fā)器的狀態(tài)同步。

于是我們現(xiàn)在了解了引入negotiationneeded事件和signalingState屬性之后,動(dòng)態(tài)修改媒體收發(fā)器的事情就變得簡(jiǎn)單了。在連接已經(jīng)建立之后,如果一方添加、刪除或者修改媒體收發(fā)器,negotiationneeded事件會(huì)再次觸發(fā),此時(shí)再進(jìn)行一次上述SDP交換流程,連麥雙方的狀態(tài)就能重新同步。

數(shù)據(jù)通道

從上面的流程中可以看出,WebRTC和網(wǎng)絡(luò)直播中常用的RTMP、HTTP協(xié)議有很大的不同。使用RTMP推流的時(shí)候,是建立一個(gè)TCP連接,完成RTMP協(xié)議握手,然后指定數(shù)據(jù)傳輸?shù)摹懊襟w流名稱(chēng)”等信息,最后實(shí)時(shí)發(fā)送音視頻數(shù)據(jù)流;而通過(guò)HTTP傳輸直播流的方式,是建立一個(gè)TCP連接,然后通過(guò)HTTP動(dòng)詞“GET”指定需要拉取的媒體流名稱(chēng),然后服務(wù)器返回一個(gè)HTTP狀態(tài)碼,并持續(xù)發(fā)送音視頻數(shù)據(jù)流。如果類(lèi)比上述兩種方式,那么WebRTC對(duì)于開(kāi)發(fā)人員來(lái)說(shuō)將是這樣的:雙方通過(guò)IP地址和端口等信息建立WebRTC連接,A添加媒體收發(fā)器后B馬上收到事件回調(diào),B這邊回調(diào)函數(shù)執(zhí)行完之后A收到操作完成的信息。但實(shí)際上A和B建立連接之后,只能收發(fā)媒體流;這些媒體收發(fā)器的控制信息,通過(guò)額外的SDP交換來(lái)完成,只要雙方?jīng)]有經(jīng)過(guò)這種手動(dòng)交換SDP的過(guò)程,那么一方修改了媒體收發(fā)器的狀態(tài),WebRTC內(nèi)部不會(huì)給你進(jìn)行遠(yuǎn)程過(guò)程調(diào)用(Remote Procedure Call)啥的,你不手動(dòng)做SDP交換另一方就不會(huì)知道。

為了方便進(jìn)行這種SDP交換流程,WebRTC在媒體收發(fā)器之外還提供了“數(shù)據(jù)收發(fā)器”——數(shù)據(jù)通道(Data channel)。數(shù)據(jù)通道可以傳輸非音視頻音視頻數(shù)據(jù),內(nèi)部不會(huì)像媒體收發(fā)器那樣進(jìn)行音視頻的編碼和解碼,而是原原本本把調(diào)用發(fā)送函數(shù)時(shí)候傳入的數(shù)據(jù)發(fā)給另一端。這樣,在第一次進(jìn)行SDP交換建立連接的時(shí)候,可以只創(chuàng)建一個(gè)數(shù)據(jù)通道完成建連,后續(xù)再添加、刪除、修改媒體收發(fā)器的時(shí)候,就通過(guò)數(shù)據(jù)通道來(lái)傳輸SDP字符串,不再需要準(zhǔn)備額外的渠道來(lái)收發(fā)SDP完成協(xié)商。

業(yè)務(wù)動(dòng)作

對(duì)于實(shí)際在線上使用的視頻連麥來(lái)說(shuō),需要一些遠(yuǎn)程過(guò)程調(diào)用來(lái)完成業(yè)務(wù)動(dòng)作,這些遠(yuǎn)程過(guò)程調(diào)用的請(qǐng)求也會(huì)使用數(shù)據(jù)通道進(jìn)行傳輸。以最基礎(chǔ)的必要?jiǎng)幼鳛槔?#xff0c;視頻連麥?zhǔn)切枰獏^(qū)分連麥房間的,主播ABCD在進(jìn)行連麥的同時(shí),主播EFGH也可以進(jìn)行視頻連麥,而且ABCD和EFGH不會(huì)互相看見(jiàn)對(duì)方。所以需要有一個(gè)遠(yuǎn)程過(guò)程調(diào)用來(lái)告訴服務(wù)器,當(dāng)前的視頻連麥會(huì)話是屬于哪一個(gè)房間的。在音視頻傳輸方面,也分為“我要發(fā)送音視頻”和“我要接收某某人的音視頻”這樣的操作。所以需要自己設(shè)計(jì)一套協(xié)議,表明這個(gè)數(shù)據(jù)是請(qǐng)求還是響應(yīng)或者是事件通知之類(lèi),具體是哪個(gè)遠(yuǎn)程過(guò)程調(diào)用方法,攜帶什么參數(shù)。然后把數(shù)據(jù)結(jié)構(gòu)以protobuf、messagepack、json等形式序列化之后通過(guò)數(shù)據(jù)通道發(fā)送。

總結(jié)

下面開(kāi)始視頻連麥的技術(shù)總結(jié)。

B站自研的第二代視頻連麥系統(tǒng)使用標(biāo)準(zhǔn)WebRTC接口,初始狀態(tài)下使用專(zhuān)門(mén)的接口獲取服務(wù)器的信息,基于服務(wù)器信息創(chuàng)建只有一個(gè)數(shù)據(jù)通道的SDP完成信令協(xié)商,與服務(wù)器建立連接;

視頻連麥過(guò)程中只與服務(wù)器建立連接、不與連麥對(duì)手直接建立連接,通過(guò)服務(wù)器在不同參與者之間轉(zhuǎn)發(fā)音視頻數(shù)據(jù);

通過(guò)數(shù)據(jù)通道來(lái)回傳輸遠(yuǎn)程過(guò)程調(diào)用的請(qǐng)求和響應(yīng),包括加入房間、發(fā)布和接收音視頻流的請(qǐng)求、執(zhí)行房間管理操作等;涉及到音視頻變更的,請(qǐng)求和響應(yīng)需要攜帶SDP字符串。

通過(guò)這種方式,視頻連麥能力可以使用同樣的邏輯流程運(yùn)行于web端、android端、iOS端、Windows端,不會(huì)像第一代那樣受限于web端無(wú)法調(diào)用內(nèi)部模塊而無(wú)法在網(wǎng)頁(yè)上運(yùn)行。

預(yù)告

基于webrtc在客戶(hù)端完成了包括連接建立和視頻連麥業(yè)務(wù)需要的音視頻發(fā)布、訂閱等操作后,后續(xù)將介紹選擇性轉(zhuǎn)發(fā)服務(wù)器如何接受這種形式的連接,響應(yīng)發(fā)布訂閱請(qǐng)求,并完成包括數(shù)據(jù)轉(zhuǎn)發(fā)、錄像留存、業(yè)務(wù)方遠(yuǎn)程過(guò)程調(diào)用接口等后端功能。

-End-

作者丨雷鳴、大熊哥

http://www.risenshineclean.com/news/51144.html

相關(guān)文章:

  • 網(wǎng)頁(yè)模板免費(fèi)下載html深圳網(wǎng)站關(guān)鍵詞優(yōu)化公司
  • 軟件工程做項(xiàng)目網(wǎng)站工程建設(shè)數(shù)字化管理平臺(tái)
  • 西寧seo網(wǎng)站優(yōu)化用戶(hù)體驗(yàn)
  • php做網(wǎng)站為什么比java快企業(yè)策劃咨詢(xún)公司
  • 成都廣告制作廠家深圳優(yōu)化seo
  • 做網(wǎng)站打廣告圖片素材app推廣方法
  • 程序界面設(shè)計(jì)seo查詢(xún)百科
  • 網(wǎng)站建設(shè)平臺(tái)源碼提供seo優(yōu)化seo外包
  • 做網(wǎng)站顏色如何搭配一個(gè)產(chǎn)品的網(wǎng)絡(luò)營(yíng)銷(xiāo)方案
  • 網(wǎng)站建設(shè)銷(xiāo)售銷(xiāo)售流程花關(guān)鍵詞排名系統(tǒng)
  • 手機(jī)版微網(wǎng)站百度關(guān)鍵詞排名十大排名
  • 應(yīng)用商店網(wǎng)站源碼媒體代發(fā)網(wǎng)站
  • 網(wǎng)站域名備案注銷(xiāo)灰色關(guān)鍵詞排名方法
  • 同城做鴨網(wǎng)站百度手機(jī)版
  • 如何找回網(wǎng)站備案密碼微軟優(yōu)化大師
  • php網(wǎng)站怎么做集群正規(guī)教育培訓(xùn)機(jī)構(gòu)
  • python做網(wǎng)站怎么樣網(wǎng)站建設(shè)全網(wǎng)營(yíng)銷(xiāo)
  • 網(wǎng)站建設(shè)費(fèi)應(yīng)怎樣做會(huì)計(jì)分錄上海網(wǎng)站搜索引擎優(yōu)化
  • 做外貿(mào)應(yīng)該去什么網(wǎng)站騰訊新聞發(fā)布平臺(tái)
  • 做網(wǎng)站該去哪找客戶(hù)免費(fèi)發(fā)布廣告信息的網(wǎng)站
  • 專(zhuān)門(mén)找建筑案例的網(wǎng)站如何查看網(wǎng)站權(quán)重
  • 設(shè)計(jì)一個(gè)電子商務(wù)網(wǎng)站建設(shè)方案小程序制作
  • 用帝國(guó)軟件做網(wǎng)站的心得成品網(wǎng)站seo
  • 建設(shè)工程評(píng)標(biāo)專(zhuān)家在哪個(gè)網(wǎng)站登錄百度指數(shù)怎么用
  • 下做圖軟件在哪個(gè)網(wǎng)站下載網(wǎng)站域名注冊(cè)查詢(xún)
  • 河南建設(shè)網(wǎng)站官網(wǎng)山東疫情最新消息
  • 桂陽(yáng)網(wǎng)站建設(shè)津seo快速排名
  • 大氣全屏通用企業(yè)網(wǎng)站整站源碼沈陽(yáng)seo優(yōu)化新勢(shì)力
  • 企業(yè)年金如何領(lǐng)取沈陽(yáng)網(wǎng)站關(guān)鍵詞優(yōu)化公司
  • 手機(jī)網(wǎng)站帶后臺(tái)源代碼免費(fèi)網(wǎng)站統(tǒng)計(jì)代碼