最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

視頻直播技術干貨:一文讀懂主流視頻直播系統(tǒng)的推拉流架構、傳輸協(xié)議等

2022-05-31 16:51 作者:nickkckckck  | 我要投稿

本文由蘑菇街前端開發(fā)工程師“三體”分享,原題“蘑菇街云端直播探索——啟航篇”,有修訂。

1、引言

隨著移動網(wǎng)絡網(wǎng)速的提升與資費的降低,視頻直播作為一個新的娛樂方式已經(jīng)被越來越多的用戶逐漸接受。特別是最近這幾年,視頻直播已經(jīng)不僅僅被運用在傳統(tǒng)的秀場、游戲類板塊,更是作為電商的一種新模式得到迅速成長。

本文將通過介紹實時視頻直播技術體系,包括常用的推拉流架構、傳輸協(xié)議等,讓你對現(xiàn)今主流的視頻直播技術有一個基本的認知。

學習交流:

- 移動端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動端IM》

- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK(備用地址點此)

(本文已同步發(fā)布于:http://www.52im.net/thread-3922-1-1.html)

2、蘑菇街的直播架構概覽

目前蘑菇街直播推拉流主流程依賴于某云直播的服務。

云直播提供的推流方式有兩種:

  • 1)一是通過集成SDK的方式進行推流(用于手機端開播);

  • 2)另一種是通過RTMP協(xié)議向遠端服務器進行推流(用于PC開播端或專業(yè)控臺設備開播)。

除去推拉流,該云平臺也提供了云通信(IM即時通訊能力)和直播錄制等云服務,組成了一套直播所需要的基礎服務。

3、推拉流架構1:廠商SDK推拉流

如上題所示,這一種推拉流架構方式需要依賴騰訊這類廠商提供的手機互動直播SDK,通過在主播端App和用戶端App都集成SDK,使得主播端和用戶端都擁有推拉流的功能。

這種推拉流架構的邏輯原理是這樣的:

  • 1)主播端和用戶端分別與云直播的互動直播后臺建立長連接;

  • 2)主播端通過UDT私有協(xié)議向互動直播后臺推送音視頻流;

  • 3)互動直播后臺接收到音視頻流后做轉發(fā),直接下發(fā)給與之建立連接的用戶端。

這種推拉流方式有幾點優(yōu)勢:

  • 1)只需要在客戶端中集成SDK:通過手機就可以開播,對于主播開播的要求比較低,適合直播業(yè)務快速鋪開;

  • 2)互動直播后臺僅做轉發(fā):沒有轉碼,上傳CDN等額外操作,整體延遲比較低;

  • 3)主播端和用戶端都可以作為音視頻上傳的發(fā)起方:適合連麥、視頻會話等場景。

4、推拉流架構2:旁路推流

之前介紹了通過手機SDK推拉流的直播方式,看起來在手機客戶端中觀看直播的場景已經(jīng)解決了。

那么問題來了:如果我想要在H5、小程序等其他場景下觀看直播,沒有辦法接入SDK,需要怎么處理呢?

這個時候需要引入一個新的概念——旁路推流。

旁路推流指的是:通過協(xié)議轉換將音視頻流對接到標準的直播 CDN 系統(tǒng)上。

目前云直播開啟旁路推流后,會通過互動直播后臺將音視頻流推送到云直播后臺,云直播后臺負責將收到音視頻流轉碼成通用的協(xié)議格式并且推送到CDN,這樣H5、小程序等端就可以通過CDN拉取到通用格式的音視頻流進行播放了。

目前蘑菇街直播旁路開啟的協(xié)議類型有HLS、FLV、RTMP三種,已經(jīng)可以覆蓋到所有的播放場景,在后續(xù)章節(jié)會對這幾種協(xié)議做詳細的介紹。

5、推拉流架構3:RTMP推流

隨著直播業(yè)務發(fā)展,一些主播逐漸不滿足于手機開播的效果,并且電商直播需要高保真地將商品展示在屏幕上,需要通過更加高清專業(yè)的設備進行直播,RTMP推流技術應運而生。

我們通過使用OBS等流媒體錄影程序,對專業(yè)設備錄制的多路流進行合并,并且將音視頻流上傳到指定的推流地址。由于OBS推流使用了RTMP協(xié)議,因此我們稱這一種推流類型為RTMP推流。

我們首先在云直播后臺申請到推流地址和秘鑰,將推流地址和秘鑰配置到OBS軟件當中,調整推流各項參數(shù),點擊推流以后,OBS就會通過RTMP協(xié)議向對應的推流地址推送音視頻流。

這一種推流方式和SDK推流的不同之處在于音視頻流是直接被推送到了云直播后臺進行轉碼和上傳CDN的,沒有直接將直播流轉推到用戶端的下行方式,因此相比SDK推流延遲會長一些。

總結下來RTMP推流的優(yōu)勢和劣勢比較明顯。

優(yōu)勢主要是:

  • 1)可以接入專業(yè)的直播攝像頭、麥克風,直播的整體效果明顯優(yōu)于手機開播;

  • 2)OBS已經(jīng)有比較多成熟的插件,比如目前蘑菇街主播常用YY助手做一些美顏的處理,并且OBS本身已經(jīng)支持濾鏡、綠幕、多路視頻合成等功能,功能比手機端強大。

劣勢主要是:

  • 1)OBS本身配置比較復雜,需要專業(yè)設備支持,對主播的要求明顯更高,通常需要一個固定的場地進行直播;

  • 2)RTMP需要云端轉碼,并且本地上傳時也會在OBS中配置GOP和緩沖,延時相對較長。

6、高可用架構方案:云互備

業(yè)務發(fā)展到一定階段后,我們對于業(yè)務的穩(wěn)定性也會有更高的要求,比如當云服務商服務出現(xiàn)問題時,我們沒有備用方案就會出現(xiàn)業(yè)務一直等待服務商修復進度的問題。

因此云互備方案就出現(xiàn)了:云互備指的是直播業(yè)務同時對接多家云服務商,當一家云服務商出現(xiàn)問題時,快速切換到其他服務商的服務節(jié)點,保證業(yè)務不受影響。

直播業(yè)務中經(jīng)常遇到服務商的CDN節(jié)點下行速度較慢,或者是CDN節(jié)點存儲的直播流有問題,此類問題有地域性,很難排查,因此目前做的互備云方案,主要是備份CDN節(jié)點。

目前蘑菇街整體的推流流程已經(jīng)依賴了原有云平臺的服務,因此我們通過在云直播后臺中轉推一路流到備份云平臺上,備份云在接收到了直播流后會對流轉碼并且上傳到備份云自身的CDN系統(tǒng)當中。一旦主平臺CDN節(jié)點出現(xiàn)問題,我們可以將下發(fā)的拉流地址替換成備份云拉流地址,這樣就可以保證業(yè)務快速修復并且觀眾無感知。

7、視頻直播數(shù)據(jù)流解封裝原理

介紹流協(xié)議之前,先要介紹我們從云端拿到一份數(shù)據(jù),要經(jīng)過幾個步驟才能解析出最終需要的音視頻數(shù)據(jù)。

如上圖所示,總體來說,從獲取到數(shù)據(jù)到最終將音視頻播放出來要經(jīng)歷四個步驟。

第一步:解協(xié)議。

協(xié)議封裝的時候通常會攜帶一些頭部描述信息或者信令數(shù)據(jù),這一部分數(shù)據(jù)對我們音視頻播放沒有作用,因此我們需要從中提取出具體的音視頻封裝格式數(shù)據(jù),我們在直播中常用的協(xié)議有HTTP和RTMP兩種。

第二步:解封裝。

獲取到封裝格式數(shù)據(jù)以后需要進行解封裝操作,從中分別提取音頻壓縮流數(shù)據(jù)和視頻壓縮流數(shù)據(jù),封裝格式數(shù)據(jù)我們平時經(jīng)常見到的如MP4、AVI,在直播中我們接觸比較多的封裝格式有TS、FLV。

第三步:解碼音視頻。

到這里我們已經(jīng)獲取了音視頻的壓縮編碼數(shù)據(jù)。

我們日常經(jīng)常聽到的視頻壓縮編碼數(shù)據(jù)有H.26X系列和MPEG系列等,音頻編碼格式有我們熟悉的MP3、ACC等。

之所以我們能見到如此多的編碼格式,是因為各種組織都提出了自己的編碼標準,并且會相繼推出一些新的議案,但是由于推廣和收費問題,目前主流的編碼格式也并不多。

獲取壓縮數(shù)據(jù)以后接下來需要將音視頻壓縮數(shù)據(jù)解碼,獲取非壓縮的顏色數(shù)據(jù)和非壓縮的音頻抽樣數(shù)據(jù)。顏色數(shù)據(jù)有我們平時熟知的RGB,不過在視頻的中常用的顏色數(shù)據(jù)格式是YUV,指的是通過明亮度、色調、飽和度確定一個像素點的色值。音頻抽樣數(shù)據(jù)通常使用的有PCM。

第四步:音視頻同步播放。

最后我們需要比對音視頻的時間軸,將音視頻解碼后的數(shù)據(jù)交給顯卡聲卡同步播放。

PS:如果你對上述流程還不太理解,建議進一步閱讀以下系列文章:

  1. 《移動端實時音視頻直播技術詳解(一):開篇》

  2. 《移動端實時音視頻直播技術詳解(二):采集》

  3. 《移動端實時音視頻直播技術詳解(三):處理》

  4. 《移動端實時音視頻直播技術詳解(四):編碼和封裝》

  5. 《移動端實時音視頻直播技術詳解(五):推流和傳輸》

  6. 《移動端實時音視頻直播技術詳解(六):延遲優(yōu)化》

另外:有關音視頻編解碼技術的文章,也可以詳細學習以下文章:

  1. 視頻編解碼之:《理論概述》、《數(shù)字視頻介紹》、《編碼基礎》、《預測技術介紹》

  2. 《認識主流視頻編碼技術H.264》

  3. 《如何開始音頻編解碼技術的學習》

  4. 《音頻基礎及編碼原理入門》

  5. 《常見的實時語音通訊編碼標準》

  6. 《實時視頻編碼H.264的特點與優(yōu)勢》、《視頻編碼H.264、VP8的前世今生》

  7. 《詳解音頻編解碼的原理、演進和應用選型》、《零基礎,史上最通俗視頻編碼技術入門》

8、視頻直播傳輸協(xié)議1:HLS

首先介紹一下HLS協(xié)議。HLS是HTTP Live Streaming的簡寫,是由蘋果公司提出的流媒體網(wǎng)絡傳輸協(xié)議。

從名字可以明顯看出:這一套協(xié)議是基于HTTP協(xié)議傳輸?shù)摹?/p>

說到HLS協(xié)議:首先需要了解這一種協(xié)議是以視頻切片的形式分段播放的,協(xié)議中使用的切片視頻格式是TS,也就是我們前文提到的封裝格式。

在我們獲取TS文件之前:協(xié)議首先要求請求一個M3U8格式的文件,M3U8是一個描述索引文件,它以一定的格式描述了TS地址的指向,我們根據(jù)M3U8文件中描述的內容,就可以獲取每一段TS文件的CDN地址,通過加載TS地址分段播放就可以組合出一整段完整的視頻。

使用HLS協(xié)議播放視頻時:首先會請求一個M3U8文件,如果是點播只需要在初始化時獲取一次就可以拿到所有的TS切片指向,但如果是直播的話就需要不停地輪詢M3U8文件,獲取新的TS切片。

獲取到M3U8后:我們可以看一下里面的內容。首先開頭是一些通用描述信息,比如第一個分片序列號、片段最大時長和總時長等,接下來就是具體TS對應的地址列表。如果是直播,那么每次請求M3U8文件里面的TS列表都會隨著最新的直播切片更新,從而達到直播流播放的效果。

HLS這種切片播放的格式在點播播放時是比較適用的,一些大的視頻網(wǎng)站也都有用這一種協(xié)議作為播放方案。

首先:切片播放的特性特別適用于點播播放中視頻清晰度、多語種的熱切換。比如我們播放一個視頻,起初選擇的是標清視頻播放,當我們看了一半覺得不夠清晰,需要換成超清的,這時候只需要將標清的M3U8文件替換成超清的M3U8文件,當我們播放到下一個TS節(jié)點時,視頻就會自動替換成超清的TS文件,不需要對視頻做重新初始化。

其次:切片播放的形式也可以比較容易地在視頻中插入廣告等內容。

在直播場景下,HLS也是一個比較常用的協(xié)議,他最大的優(yōu)勢是蘋果大佬的加持,對這一套協(xié)議推廣的比較好,特別是移動端。將M3U8文件地址喂給video就可以直接播放,PC端用MSE解碼后大部分瀏覽器也都能夠支持。但是由于其分片加載的特性,直播的延遲相對較長。比如我們一個M3U8有5個TS文件,每個TS文件播放時長是2秒,那么一個M3U8文件的播放時長就是10秒,也就是說這個M3U8播放的直播進度至少是10秒之前的,這對于直播場景來說是一個比較大的弊端。

HLS中用到的TS封裝格式,視頻編碼格式是通常是H.264或MPEG-4,音頻編碼格式為AAC或MP3。

一個ts由多個定長的packtet組成,通常是188個字節(jié),每個packtet有head和payload組成,head中包含一些標識符、錯誤信息、包位置等基礎信息。payload可以簡單理解為音視頻信息,但實際上下層還有還有兩層封裝,將封裝解碼后可以獲取到音視頻流的編碼數(shù)據(jù)。

9、視頻直播傳輸協(xié)議2:HTTP-FLV

HTTP-FLV協(xié)議,從名字上就可以明顯看出是通過HTTP協(xié)議來傳輸FLV封裝格式的一種協(xié)議。

FLV是Flash Video的簡寫,是一種文件體積小,適合在網(wǎng)絡上傳輸?shù)姆獍绞?。FlV的視頻編碼格式通常是H.264,音頻編碼是ACC或MP3。

HTTP-FLV在直播中是通過走HTTP長連接的方式,通過分塊傳輸向請求端傳遞FLV封包數(shù)據(jù)。

在直播中,我們通過HTTP-FLV協(xié)議的拉流地址可以拉取到一段chunked數(shù)據(jù)。

打開文件后可以讀取到16進制的文件流,通過和FLV包結構對比,可以發(fā)現(xiàn)這些數(shù)據(jù)就是我們需要的FLV數(shù)據(jù)。

首先開頭是頭部信息:464C56轉換ASCII碼后是FLV三個字符,01指的是版本號,05轉換為2進制后第6位和第8位分別代表是否存在音頻和視頻,09代表頭部長度占了幾個字節(jié)。

后續(xù)就是正式的音視頻數(shù)據(jù):是通過一個個的FLV TAG進行封裝,每一個TAG也有頭部信息,標注這個TAG是音頻信息、視頻信息還是腳本信息。我們通過解析TAG就可以分別提取音視頻的壓縮編碼信息。

FLV這一種格式在video中并不是原生支持的,我們要播放這一種格式的封包格式需要通過MSE對影視片的壓縮編碼信息進行解碼,因此需要瀏覽器能夠支持MSE這一API。由于HTTP-FLV的傳輸是通過長連接傳輸文件流的形式,需要瀏覽器支持Stream IO或者fetch,對于瀏覽器的兼容性要求會比較高。

FLV在延遲問題上相比切片播放的HLS會好很多,目前看來FLV的延遲主要是受編碼時設置的GOP長度的影響。

這邊簡單介紹一下GOP:在H.264視頻編碼的過程中,會生成三種幀類型:I幀、B幀和P幀。I幀就是我們通常說的關鍵幀,關鍵幀內包括了完整的幀內信息,可以直接作為其他幀的參考幀。B幀和P幀為了將數(shù)據(jù)壓縮得更小,需要由其他幀推斷出幀內的信息。因此兩個I幀之間的時長也可以被視作最小的視頻播放片段時長。從視頻推送的穩(wěn)定性考慮,我們也要求主播將關鍵幀間隔設置為定長,通常是1-3秒,因此除去其他因素,我們的直播在播放時也會產(chǎn)生1-3秒的延時。

10、視頻直播傳輸協(xié)議3:RTMP

RTMP協(xié)議實際可以與HTTP-FLV協(xié)議歸做同一種類型。

他們的封包格式都是FlV,但HTTP-FLV使用的傳輸協(xié)議是HTTP,RTMP拉流使用RTMP作為傳輸協(xié)議。

RTMP是Adobe公司基于TCP做的一套實時消息傳輸協(xié)議,經(jīng)常與Flash播放器匹配使用。

RTMP協(xié)議的優(yōu)缺點非常明顯。

RTMP協(xié)議的優(yōu)點主要是:

  • 1)首先和HTTP-FLV一樣,延遲比較低;

  • 2)其次它的穩(wěn)定性非常好,適合長時間播放(由于播放時借用了Flash player強大的功能,即使開多路流同時播放也能保證頁面不出現(xiàn)卡頓,很適合監(jiān)控等場景)。

但是Flash player目前在web端屬于墻倒眾人推的境地,主流瀏覽器漸漸都表示不再支持Flash player插件,在MAC上使用能夠立刻將電腦變成燒烤用的鐵板,資源消耗很大。在移動端H5基本屬于完全不支持的狀態(tài),兼容性是它最大的問題。

11、視頻直播傳輸協(xié)議4:MPEG-DASH

MPEG-DASH這一協(xié)議屬于新興勢力,和HLS一樣,都是通過切片視頻的方式進行播放。

他產(chǎn)生的背景是早期各大公司都自己搞自己的一套協(xié)議。比如蘋果搞了HLS、微軟搞了 MSS、Adobe還搞了HDS,這樣使用者需要在多套協(xié)議封裝的兼容問題上痛苦不堪。

于是大佬們湊到一起,將之前各個公司的流媒體協(xié)議方案做了一個整合,搞了一個新的協(xié)議。

由于同為切片視頻播放的協(xié)議,DASH優(yōu)劣勢和HLS類似,可以支持切片之間多視頻碼率、多音軌的切換,比較適合點播業(yè)務,在直播中還是會有延時較長的問題。

12、如何選擇最優(yōu)的視頻直播傳輸協(xié)議

視頻直播協(xié)議選擇非常關鍵的兩點,在前文都已經(jīng)有提到了,即低延時和更優(yōu)的兼容性。

首先從延時角度考慮:不考慮云端轉碼以及上下行的消耗,HLS和MPEG-DASH通過將切片時長減短,延時在10秒左右;RTMP和FLV理論上延時相當,在2-3秒。因此在延時方面HLS ≈ DASH > RTMP ≈ FLV。

從兼容性角度考慮:HLS > FLV > RTMP,DASH由于一些項目歷史原因,并且定位和HLS重復了,暫時沒有對其兼容性做一個詳盡的測試,被推出了選擇的考慮范圍。

綜上所述:我們可以通過動態(tài)判斷環(huán)境的方式,選擇當前環(huán)境下可用的最低延遲的協(xié)議。大致的策略就是優(yōu)先使用HTTP-FLV,使用HLS作為兜底,在一些特殊需求場景下通過手動配置的方式切換為RTMP。

對于HLS和HTTP-FLV:我們可以直接使用?hls.js?和?flv.js?做做解碼播放,這兩個庫內部都是通過MSE做的解碼。首先根據(jù)視頻封裝格式提取出對應的音視頻chunk數(shù)據(jù),在MediaSource中分別對音頻和視頻創(chuàng)建SourceBuffer,將音視頻的編碼數(shù)據(jù)喂給SourceBuffer后SourceBuffer內部會處理完剩下的解碼和音視頻對齊工作,最后MediaSource將Video標簽中的src替換成MediaSource 對象進行播放。

在判斷播放環(huán)境時我們可以參照flv.js內部的判斷方式,通過調用MSE判斷方法和模擬請求的方式判斷MSE和StreamIO是否可用:

// 判斷MediaSource是否被瀏覽器支持,H.264視頻編碼和Acc音頻編碼是否能夠被支持解碼

window.MediaSource && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"');

如果FLV播放不被支持的情況下:需要降級到HLS,這時候需要判斷瀏覽器環(huán)境是否在移動端,移動端通常不需要?hls.js?通過MSE解碼的方式進行播放,直接將M3U8的地址交給video的src即可。如果是PC端則判斷MSE是否可用,如果可用就使用hls.js解碼播放。

這些判讀可以在自己的邏輯里提前判斷后去拉取對應解碼庫的CDN,而不是等待三方庫加載完成后使用三方庫內部的方法判斷,這樣在選擇解碼庫時就可以不把所有的庫都拉下來,提高加載速度。

13、同層播放如何解決

電商直播需要觀眾操作和互動的部分比起傳統(tǒng)的直播更加多,因此產(chǎn)品設計的時候很多的功能模塊會懸浮在直播視頻上方減少占用的空間。這個時候就會遇到一個移動端播放器的老大難問題——同層播放。

同層播放問題:是指在移動端H5頁面中,一些瀏覽器內核為了提升用戶體驗,將video標簽被劫持替換為native播放器,導致其他元素無法覆蓋于播放器之上。

比如我們想要在直播間播放器上方增加聊天窗口,將聊天窗口通過絕對定位提升z-index置于播放器上方,在PC中測試完全正常。但在移動端的一些瀏覽器中,video被替換成了native播放器,native的元素層級高于我們的普通元素,導致聊天窗口實際顯示的時候在播放器下方。

要解決這個問題,首先要分多個場景。

首先在iOS系統(tǒng)中:正常情況下video標簽會自動被全屏播放,但iOS10以上已經(jīng)原生提供了video的同層屬性,我們在video標簽上增加playsinline/webkit-playsinline可以解決iOS系統(tǒng)中大部分瀏覽器的同層問題,剩下的低系統(tǒng)版本的瀏覽器以及一些App內的webview容器(譬如微博),用上面提的屬性并不管用,調用三方庫iphone-inline-video可以解決大部分剩余問題。

在Android端:大部分騰訊系的App內置的webview容器用的都是X5內核,X5內核會將video替換成原生定制的播放器已便于增強一些功能。X5也提供了一套同層的方案(該方案官方文檔鏈接已無法打開),給video標簽寫入X5同層屬性也可以在X5內核中實現(xiàn)內聯(lián)播放。不過X5的同層屬性在各個X5版本中表現(xiàn)都不太一樣(比如低版本X5中需要使用X5全屏播放模式才能保證MSE播放的視頻同層生效),需要注意區(qū)分版本。

在蘑菇街App中,目前集成的X5內核版本比較老,在使用MSE的情況下會導致X5同層參數(shù)不生效。但如果集成新版本的X5內核,需要對大量的線上頁面做回歸測試,成本比較高,因此提供了一套折中的解決方案。通過在頁面URL中增加一個開關參數(shù),容器讀取到參數(shù)以后會將X5內核降級為系統(tǒng)原生的瀏覽器內核,這樣可以在解決瀏覽器視頻同層問題的同時也將內核變動的影響范圍控制在單個頁面當中。

14、相關文章

[1]?移動端實時音視頻直播技術詳解(四):編碼和封裝

[2]?移動端實時音視頻直播技術詳解(五):推流和傳輸

[3]?實現(xiàn)延遲低于500毫秒的1080P實時音視頻直播的實踐分享

[4]?淺談開發(fā)實時視頻直播平臺的技術要點

[5]?直播系統(tǒng)聊天技術(七):直播間海量聊天消息的架構設計難點實踐

[6]?從0到1:萬人在線的實時音視頻直播技術實踐分享(視頻+PPT) [附件下載]

[7]?實時視頻編碼H.264的特點與優(yōu)勢

[8]?視頻編碼H.264、VP8的前世今生

[9]?零基礎,史上最通俗視頻編碼技術入門

[10]?視頻編解碼之編碼基礎

[11]?零基礎入門:實時音視頻技術基礎知識全面盤點

[12]?實時音視頻面視必備:快速掌握11個視頻技術相關的基礎概念

[13]?寫給小白的實時音視頻技術入門提綱

(本文已同步發(fā)布于:http://www.52im.net/thread-3922-1-1.html)


視頻直播技術干貨:一文讀懂主流視頻直播系統(tǒng)的推拉流架構、傳輸協(xié)議等的評論 (共 條)

分享到微博請遵守國家法律
株洲市| 辛集市| 台南县| 莫力| 汤阴县| 吴堡县| 无棣县| 吉安市| 沂源县| 丹寨县| 彭阳县| 沈阳市| 孟连| 江西省| 温宿县| 外汇| 陵川县| 木里| 肥乡县| 扎赉特旗| 和平区| 邵东县| 漳浦县| 新昌县| 栾川县| 桓仁| 临安市| 江阴市| 平和县| 颍上县| 万荣县| 沂水县| 什邡市| 台中县| 福泉市| 策勒县| 鄂托克前旗| 蓝山县| 商洛市| 黎城县| 抚远县|