Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 好男人社区在线播放,欧美freesex黑人又粗又,欧美精品成人一区二区视频一

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          為什么視頻網站的視頻鏈接地址是blob

          為什么視頻網站的視頻鏈接地址是blob

          從HTML5提供了video標簽,在網頁中播放視頻已經變成一個非常簡單的事,只要一個video標簽,src屬性設置為視頻的地址就完事了。由于src指向真實的視頻網絡地址,在早期一般網站資源文件不怎么通過referer設置防盜鏈,當我們拿到視頻的地址后可以隨意的下載或使用(每次放假回家,就會有親戚找我幫忙從一些視頻網站上下東西)。

          目前的云存儲服務商大部分都支持referer防盜鏈。其原理就是在訪問資源時,請求頭會帶上發起請求的頁面地址,判斷其不存在(表示直接訪問圖片地址)或不在白名單內,即為盜鏈。

          可是從某個時間開始我們打開調試工具去看各大視頻網站的視頻src會發現,它們統統變成了這樣的形式。

          拿b站的一個視頻來看,紅框中的視頻地址,這個blob是個什么東西?。

          其實這個Blob URL也不是什么新技術,國內外出來都有一陣子了,但是網上的相關的文章不多也不是很詳細,今天就和大家一起分享學習一下。

          Blob和ArrayBuffer

          最早是數據庫直接用Blob來存儲二進制數據對象,這樣就不用關注存儲數據的格式了。在web領域,Blob對象表示一個只讀原始數據的類文件對象,雖然是二進制原始數據但是類似文件的對象,因此可以像操作文件對象一樣操作Blob對象。

          ArrayBuffer對象用來表示通用的、固定長度的原始二進制數據緩沖區。我們可以通過new ArrayBuffer(length)來獲得一片連續的內存空間,它不能直接讀寫,但可根據需要將其傳遞到TypedArray視圖或 DataView 對象來解釋原始緩沖區。實際上視圖只是給你提供了一個某種類型的讀寫接口,讓你可以操作ArrayBuffer里的數據。TypedArray需指定一個數組類型來保證數組成員都是同一個數據類型,而DataView數組成員可以是不同的數據類型。

          TypedArray視圖的類型數組對象有以下幾個:

          • Int8Array:8位有符號整數,長度1個字節。
          • Uint8Array:8位無符號整數,長度1個字節。
          • Uint8ClampedArray:8位無符號整數,長度1個字節,溢出處理不同。
          • Int16Array:16位有符號整數,長度2個字節。
          • Uint16Array:16位無符號整數,長度2個字節。
          • Int32Array:32位有符號整數,長度4個字節。
          • Uint32Array:32位無符號整數,長度4個字節。
          • Float32Array:32位浮點數,長度4個字節。
          • Float64Array:64位浮點數,長度8個字節。

          Blob與ArrayBuffer的區別是,除了原始字節以外它還提供了mime type作為元數據,Blob和ArrayBuffer之間可以進行轉換。

          File對象其實繼承自Blob對象,并提供了提供了name , lastModifiedDate, size ,type 等基礎元數據。

          創建Blob對象并轉換成ArrayBuffer:

          //創建一個以二進制數據存儲的html文件
          const text="<div>hello world</div>";
          const blob=new Blob([text], { type: "text/html" }); // Blob {size: 22, type: "text/html"}
          //以文本讀取
          const textReader=new FileReader();
          textReader.readAsText(blob);
          textReader.onload=function() {
           console.log(textReader.result); // <div>hello world</div>
          };
          //以ArrayBuffer形式讀取
          const bufReader=new FileReader();
          bufReader.readAsArrayBuffer(blob);
          bufReader.onload=function() {
           console.log(new Uint8Array(bufReader.result)); // Uint8Array(22) [60, 100, 105, 118, 62, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 60, 47, 100, 105, 118, 62]
          };
          

          創建一個相同數據的ArrayBuffer,并轉換成Blob:

          //我們直接創建一個Uint8Array并填入上面的數據
          const u8Buf=new Uint8Array([60, 100, 105, 118, 62, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 60, 47, 100, 105, 118, 62]);
          const u8Blob=new Blob([u8Buf], { type: "text/html" }); // Blob {size: 22, type: "text/html"}
          const textReader=new FileReader();
          textReader.readAsText(u8Blob);
          textReader.onload=function() {
           console.log(textReader.result); // 同樣得到div>hello world</div>
          };
          

          更多Blob和ArrayBuffer的相關內容可以參看下面的資料:

          • MDN Blob
          • MDN ArrayBuffer
          • 阮一峰js標準參考教程二進制數組

          URL.createObjectURL

          video標簽,audio標簽還是img標簽的src屬性,不管是相對路徑,絕對路徑,或者一個網絡地址,歸根結底都是指向一個文件資源的地址。既然我們知道了Blob其實是一個可以當作文件用的二進制數據,那么只要我們可以生成一個指向Blob的地址,是不是就可以用在這些標簽的src屬性上,答案肯定是可以的,這里我們要用到的就是URL.createObjectURL()。

          const objectURL=URL.createObjectURL(object); //blob:http://localhost:1234/abcedfgh-1234-1234-1234-abcdefghijkl
          復制代碼
          

          這里的object參數是用于創建URL的File對象、Blob 對象或者 MediaSource 對象,生成的鏈接就是以blob:開頭的一段地址,表示指向的是一個二進制數據。

          其中localhost:1234是當前網頁的主機名稱和端口號,也就是location.host,而且這個Blob URL是可以直接訪問的。需要注意的是,即使是同樣的二進制數據,每調用一次URL.createObjectURL方法,就會得到一個不一樣的Blob URL。這個URL的存在時間,等同于網頁的存在時間,一旦網頁刷新或卸載,這個Blob URL就失效。

          通過URL.revokeObjectURL(objectURL) 釋放一個之前已經存在的、通過調用 URL.createObjectURL() 創建的 URL 對象。當你結束使用某個 URL 對象之后,應該通過調用這個方法來讓瀏覽器知道不用在內存中繼續保留對這個文件的引用了,允許平臺在合適的時機進行垃圾收集。

          如果是以文件協議打開的html文件(即url為file://開頭),則地址中http://localhost:1234會變成null,而且此時這個Blob URL是無法直接訪問的。

          實戰一:上傳圖片預覽

          有時我們通過input上傳圖片文件之前,會希望可以預覽一下圖片,這個時候就可以通過前面所學到的東西實現,而且非常簡單。

          html

          <input id="upload" type="file" />
          <img id="preview" src="" alt="預覽"/>
          

          javascript

          const upload=document.querySelector("#upload");
          const preview=document.querySelector("#preview");
          upload.onchange=function() {
           const file=upload.files[0]; //File對象
           const src=URL.createObjectURL(file); 
           preview.src=src;
          };
          

          這樣一個圖片上傳預覽就實現了,同樣這個方法也適用于上傳視頻的預覽。

          實戰二:以Blob URL加載網絡視頻

          現在我們有一個網絡視頻的地址,怎么能將這個視頻地址變成Blob URL是形式呢,思路肯定是先要拿到存儲這個視頻原始數據的Blob對象,但是不同于input上傳可以直接拿到File對象,我們只有一個網絡地址。

          我們知道平時請求接口我們可以使用xhr(jquery里的ajax和axios就是封裝的這個)或fetch,請求一個服務端地址可以返回我們相應的數據,那如果我們用xhr或者fetch去請求一個圖片或視頻地址會返回什么呢?當然是返回圖片和視頻的數據,只不過要設置正確responseType才能拿到我們想要的格式數據。

          function ajax(url, cb) {
           const xhr=new XMLHttpRequest();
           xhr.open("get", url);
           xhr.responseType="blob"; // ""|"text"-字符串 "blob"-Blob對象 "arraybuffer"-ArrayBuffer對象
           xhr.onload=function() {
           cb(xhr.response);
           };
           xhr.send();
          }
          

          注意XMLHttpRequest和Fetch API請求會有跨域問題,可以通過跨域資源共享(CORS)解決。

          看到responseType可以設置blob和arraybuffer我們應該就有譜了,請求返回一個Blob對象,或者返回ArrayBuffer對象轉換成Blob對象,然后通過createObjectURL生成地址賦值給視頻的src屬性就可以了,這里我們直接請求一個Blob對象。

          ajax('video.mp4', function(res){
           const src=URL.createObjectURL(res); 
           video.src=src;
          })
          

          用調試工具查看視頻標簽的src屬性已經變成一個Blob URL,表面上看起來是不是和各大視頻網站形式一致了,但是考慮一個問題,這種形式要等到請求完全部視頻數據才能播放,小視頻還好說,要是視頻資源大一點豈不爆炸,顯然各大視頻網站不可能這么干。

          解決這個問題的方法就是流媒體,其帶給我們最直觀體驗就是使媒體文件可以邊下邊播(像我這樣的90后男性最早體會到流媒體好處的應該是源于那款快子頭的播放器),web端如果要使用流媒體,有多個流媒體協議可以供我們選擇。

          HLS和MPEG DASH

          HLS (HTTP Live Streaming), 是由 Apple 公司實現的基于 HTTP 的媒體流傳輸協議。HLS以ts為傳輸格式,m3u8為索引文件(文件中包含了所要用到的ts文件名稱,時長等信息,可以用播放器播放,也可以用vscode之類的編輯器打開查看),在移動端大部分瀏覽器都支持,也就是說你可以用video標簽直接加載一個m3u8文件播放視頻或者直播,但是在pc端,除了蘋果的Safari,需要引入庫來支持。

          用到此方案的視頻網站比如優酷,可以在視頻播放時通過調試查看Network里的xhr請求,會發現一個m3u8文件,和每隔一段時間請求幾個ts文件。

          但是除了HLS,還有Adobe的HDS,微軟的MSS,方案一多就要有個標準點的東西,于是就有了MPEG DASH。

          DASH(Dynamic Adaptive Streaming over HTTP) ,是一種在互聯網上傳送動態碼率的Video Streaming技術,類似于蘋果的HLS,DASH會通過media presentation description (MPD)將視頻內容切片成一個很短的文件片段,每個切片都有多個不同的碼率,DASH Client可以根據網絡的情況選擇一個碼率進行播放,支持在不同碼率之間無縫切換。

          Youtube,B站都是用的這個方案。這個方案索引文件通常是mpd文件(類似HLS的m3u8文件功能),傳輸格式推薦的是fmp4(Fragmented MP4),文件擴展名通常為.m4s或直接用.mp4。所以用調試查看b站視頻播放時的網絡請求,會發現每隔一段時間有幾個m4s文件請求。

          不管是HLS還是DASH們,都有對應的庫甚至是高級的播放器方便我們使用,但我們其實是想要學習一點實現。其實拋開掉索引文件的解析拿到實際媒體文件的傳輸地址,擺在我們面前的只有一個如何將多個視頻數據合并讓video標簽可以無縫播放。

          與之相關的一篇B站文章推薦給感興趣的朋友:我們為什么使用DASH

          MediaSource

          video標簽src指向一個視頻地址,視頻播完了再將src修改為下一段的視頻地址然后播放,這顯然不符合我們無縫播放的要求。其實有了我們前面Blob URL的學習,我們可能就會想到一個思路,用Blob URL指向一個視頻二進制數據,然后不斷將下一段視頻的二進制數據添加拼接進去。這樣就可以在不影響播放的情況下,不斷的更新視頻內容并播放下去,想想是不是有點流的意思出來了。

          要實現這個功能我們要通過MediaSource來實現,MediaSource接口功能也很純粹,作為一個媒體數據容器可以和HTMLMediaElement進行綁定。基本流程就是通過URL.createObjectURL創建容器的BLob URL,設置到video標簽的src上,在播放過程中,我們仍然可以通過MediaSource.appendBuffer方法往容器里添加數據,達到更新視頻內容的目的。

          實現代碼如下:

          const video=document.querySelector('video');
          //視頻資源存放路徑,假設下面有5個分段視頻 video1.mp4 ~ video5.mp4,第一個段為初始化視頻init.mp4
          const assetURL="http://www.demo.com";
          //視頻格式和編碼信息,主要為判斷瀏覽器是否支持視頻格式,但如果信息和視頻不符可能會報錯
          const mimeCodec='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; 
          if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {
           const mediaSource=new MediaSource();
           video.src=URL.createObjectURL(mediaSource); //將video與MediaSource綁定,此處生成一個Blob URL
           mediaSource.addEventListener('sourceopen', sourceOpen); //可以理解為容器打開
          } else {
           //瀏覽器不支持該視頻格式
           console.error('Unsupported MIME type or codec: ', mimeCodec);
          }
          function sourceOpen () {
           const mediaSource=this;
           const sourceBuffer=mediaSource.addSourceBuffer(mimeCodec);
           let i=1;
           function getNextVideo(url) {
           //ajax代碼實現翻看上文,數據請求類型為arraybuffer
           ajax(url, function(buf) {
           //往容器中添加請求到的數據,不會影響當下的視頻播放。
           sourceBuffer.appendBuffer(buf);
           });
           }
           //每次appendBuffer數據更新完之后就會觸發
           sourceBuffer.addEventListener("updateend", function() {
           if (i===1) {
           //第一個初始化視頻加載完就開始播放
           video.play();
           }
           if (i < 6) {
           //一段視頻加載完成后,請求下一段視頻
           getNextVideo(`${assetURL}/video${i}.mp4`);
           }
           if (i===6) {
           //全部視頻片段加載完關閉容器
           mediaSource.endOfStream();
           URL.revokeObjectURL(video.src); //Blob URL已經使用并加載,不需要再次使用的話可以釋放掉。
           }
           i++;
           });
           //加載初始視頻
           getNextVideo(`${assetURL}/init.mp4`);
          };
          

          這段代碼修改自MDN的MediaSource詞條中的示例代碼,原例子中只有加載一段視頻,我修改為了多段視頻,代碼里面很多地方還可以優化精簡,這里沒做就當是為了方便我們看邏輯。

          此時我們已經基本實現了一個簡易的流媒體播放功能,如果愿意可以再加入m3u8或mpd文件的解析,設計一下UI界面,就可以實現一個流媒體播放器了。

          最后提一下一個坑,很多人跑了MDN的MediaSource示例代碼,可能會發現使用官方提供的視頻是沒問題的,但是用了自己的mp4視頻就會報錯,這是因為fmp4文件擴展名通常為.m4s或直接用.mp4,但卻是特殊的mp4文件。

          Fragmented MP4

          通常我們使用的mp4文件是嵌套結構的,客戶端必須要從頭加載一個 MP4 文件,才能夠完整播放,不能從中間一段開始播放。而Fragmented MP4(簡稱fmp4),就如它的名字碎片mp4,是由一系列的片段組成,如果服務器支持 byte-range 請求,那么,這些片段可以獨立的進行請求到客戶端進行播放,而不需要加載整個文件。

          我們可以通過這個網站判斷一個mp4文件是否為Fragmented MP4,網站地址。

          我們通過FFmpeg或Bento4的mp4fragment來將普通mp4轉換為Fragmented MP4,兩個工具都是命令行工具,按照各自系統下載下來對應的壓縮包,解壓后設置環境變量指向文件夾中的bin目錄,就可以使用相關命令了。

          Bento4的mp4fragment,沒有太多參數,命令如下:

          mp4fragment video.mp4 video-fragmented.mp4
          

          FFmpeg會需要設置一些參數,命令如下:

          ffmpeg -i video.mp4 -movflags empty_moov+default_base_moof+frag_keyframe video-fragmented.mp4
          

          Tips:網上大部分的資料中轉換時是不帶default_base_moof這個參數的,雖然可以轉換成功,但是經測試如果不添加此參數網頁中MediaSource處理視頻時會報錯。

          視頻的切割分段可以使用Bento4的mp4slipt,命令如下:

          mp4split video.mp4 --media-segment video-%llu.mp4 --pattern-parameters N
          

          最后

          之所以寫這篇文章其實是之前公司有個需求要了解一下Blob URL,稍微看了一下,后來不了了之。這次忙里偷閑重拾起來把它搞清楚,一邊學習一邊記錄,這篇文章中的很多點展開了其實有很多內容,希望大家看了這篇文章能夠有所啟發或引起興趣,我的目的也就達到了,另外視頻這方面的東西真的是有點深的,文章中如果有錯誤和疏漏也歡迎大家指出,我將及時修正。

          作者:wangzy2019

          鏈接:https://juejin.im/post/5d1ea7a8e51d454fd8057bea

          來源:掘金



          lob(BinaryLargeObject)術語最初來自數據庫(oracle中也有類似的欄位類型。),早期數據庫因為要存儲聲音、圖片、以及可執行程序等二進制數據對象所以給該類對象取名為Blob。

          在Web領域,Blob被定義為包含只讀數據的類文件對象。Blob中的數據不一定是js原生數據形式。常見的File接口就繼承自Blob,并擴展它用于支持用戶系統的本地文件。


          構建一個Blob對象通常有三種方式:

          用法:新方法創建Blob對象(構造函數來構建)


          構造函數,接受兩個參數

          第一個參數:為一個數據序列,可以是任意格式的值,例如,任意數量的字符串,Blobs以及ArrayBuffers。

          第二個參數:用于指定將要放入Blob中的數據的類型(MIME)(后端可以通過枚舉MimeType,獲取對應類型:



          Blob對象的基本屬性:

          原生對象構建Blob


          提示出錯:

          原因在于Blob構造函數要求第一個參數必須是數組,而這里第一個參數既不是一個數組,也沒有可索引的屬性。既然這里提到了對象的可索引屬性,讓我聯想到了類數組的概念,而Arguments就是一個很好的例子。來試一試:


          可以看到即使是類數組對象,而數組元素類型是Number也能得出正確的結論,猜想大概是由于構造函數內部把Number轉化為String的緣故吧!

          再來試一試其他的參數類型:


          blob.type等于application/json沒問題。arg轉為字符串后的長度為16加上制表符\t的寬度4個字節等于20。

          Blob對象的基本方法:

          大文件分割(slice()方法),slice方法與數組的slice類似。


          slice()方法接受三個參數,起始偏移量,結束偏移量,還有可選的mime類型。如果mime類型,沒有設置,那么新的Blob對象的mime類型和父級一樣。

          當要上傳大文件的時候,此方法非常有用,可以將大文件分割分段,然后各自上傳,因為分割之后的Blob對象和原始的是獨立存在的。

          不過目前瀏覽器實現此方法還沒有統一,火狐使用的是mozSlice(),Chrome使用的是webkitSlice(),其他瀏覽器則正常的方式slice()

          可以寫一個兼容各瀏覽器的方法:


          利用Blob顯示縮略圖`


          由于File對象繼承自Blob,所以我們可以很方便的利用File對象加載本地系統圖片文件,并通過createObjectURL生成一個URL并加以顯示。

          以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持小編。



          lob對象介紹

          一個Blob對象表示一個不可變的,原始數據的類似文件對象。Blob表示的數據不一定是一個JavaScript原生格式blob對象本質上是js中的一個對象,里面可以儲存大量的二進制編碼格式的數據。

          創建blob對象

          創建blob對象本質上和創建一個其他對象的方式是一樣的,都是使用Blob()的構造函數來進行創建。構造函數接受兩個參數:

          第一個參數為一個數據序列,可以是任意格式的值。

          第二個參數是一個包含兩個屬性的對象{type:MIME的類型,endings:決定第一個參數的數據格式,可以取值為"transparent"或者"native"(transparent的話不變,是默認值,native的話按操作系統轉換)。}

          Blob()構造函數允許使用其他對象創建一個Blob對象,比如用字符串構建一個blob


          既然是對象,那么blob也擁有自己的屬性以及方法

          屬性

          布爾值,指示Blob.close()是否在該對象上調用過。關閉的blob對象不可讀。

          Blob對象中所包含數據的大小(字節)。

          一個字符串,表明該Blob對象所包含數據的MIME類型。如果類型未知,則該值為空字符串。

          方法

          關閉Blob對象,以便能釋放底層資源。

          返回一個新的Blob對象,包含了源Blob對象中指定范圍內的數據。其實就是對這個blob中的數據進行切割,我們在對文件進行分片上傳的時候需要使用到這個方法。

          看到上面這些方法和屬性,使用過HTML5提供的File接口的應該都很熟悉,這些屬性和方法在File接口中也都有。其實File接口就是基于Blob,繼承blob功能并將其擴展為支持用戶系統上的文件,也就是說:

          File接口中的Flie對象就是繼承與Blob對象。

          blob對象的使用

          上面說了很多關于Blob對象的一些概念性的東西,下面我們來看看實際用途。

          分片上傳

          首先說說分片上傳,我們在進行文件上傳的時候,因為服務器的限制,會限制每一次上傳到服務器的文件大小不會很大,這個時候我們就需要把一個需要上傳的文件進行切割,然后分別進行上傳到服務器。

          假如需要做到這一步,我們需要解決兩個問題:

          首先怎么切割的問題上面已經有過說明,因為File文件對象是繼承與Blob對象的,因此File文件對象也擁有slice這個方法,我們可以使用這個方法將任何一個File文件進行切割。

          代碼如下:


          通過上面的方法。我們就得到了一個切割之后的File對象組成的數組blobs;

          接下來要做的時候就是講這些文件分別上傳到服務器。

          在HTTP1.1以上的協議中,有Transfer-Encoding這個編碼協議,用以和服務器通信,來得知當前分片傳遞的文件進程。

          這樣解決了這兩個問題,我們不僅可以對文件進行分片上傳,并且能夠得到文件上傳的進度。

          粘貼圖片

          blob還有一個應用場景,就是獲取剪切板上的數據來進行粘貼的操作。例如通過QQ截圖后,需要在網頁上進行粘貼操作。

          粘貼圖片我們需要解決下面幾個問題

          首先我們可以通過paste事件來監聽用戶的粘貼操作:


          然后通過事件對象中的clipboardData對象來獲取圖片的文件數據。

          clipboardData對象介紹

          介紹一下clipboardData對象,它實際上是一個DataTransfer類型的對象,DataTransfer是拖動產生的一個對象,但實際上粘貼事件也是它。

          clipboardData的屬性介紹


          items介紹

          items是一個DataTransferItemList對象,自然里面都是DataTransferItem類型的數據了。

          屬性

          items的DataTransferItem有兩個屬性kind和type


          方法


          在原型上還有一些其他方法,不過在處理剪切板操作的時候一般用不到了。

          type介紹

          一般types中常見的值有text/plain、text/html、Files。


          有了上面這些方法,我們可以解決第二個問題即獲取到剪切板上的數據。


          最后我們需要將獲取到的數據渲染到網頁上。

          其實這個本質上就是一個類似于上傳圖片本地瀏覽的問題。我們可以直接通過HTML5的File接口將獲取到的文件上傳到服務器然后通過講服務器返回的url地址來對圖片進行渲染。也可以使用fileRender對象來進行圖片本地瀏覽。

          fileRender對象簡介

          從Blob中讀取內容的唯一方法是使用FileReader。

          FileReader接口有4個方法,其中3個用來讀取文件,另一個用來中斷讀取。無論讀取成功或失敗,方法并不會返回讀取結果,這一結果存儲在result屬性中。


          FileReader接口包含了一套完整的事件模型,用于捕獲讀取文件時的狀態。


          通過上面的方法以及事件,我們可以發現,通過readAsDataURL方法及onload事件就可以拿到一個可本地瀏覽圖片的DataURL。

          最終代碼如下:


          這樣我們就可以監聽到用戶的粘貼操作,并且將用戶粘貼的圖片文件實時的渲染到網頁之中了。

          總結

          以上是我對Blob對象的一些學習分享,希望在實際應用上能對大家有所幫助。也希望大家多多支持小編。


          主站蜘蛛池模板: 精品伦精品一区二区三区视频 | 国产福利电影一区二区三区,免费久久久久久久精 | 奇米精品一区二区三区在线观看| 亚洲福利一区二区三区| 精品在线一区二区| 鲁丝丝国产一区二区| 亚洲乱码av中文一区二区| 久久精品动漫一区二区三区| 99久久国产精品免费一区二区| 精品视频一区二区| 成人免费一区二区三区在线观看| 国产精品视频分类一区| ...91久久精品一区二区三区 | 亚洲av无码不卡一区二区三区| chinese国产一区二区| 色一乱一伦一区一直爽| 精品一区二区三区在线视频观看| 在线视频一区二区三区四区| 日本一区二区三区在线看| 成人免费视频一区| 欧洲精品码一区二区三区免费看| 国产综合视频在线观看一区| 亚洲AV无码一区二区三区鸳鸯影院 | 麻豆AV一区二区三区| 精品一区二区三区在线成人| 国产一区二区免费| 亚洲美女一区二区三区| 国产精品av一区二区三区不卡蜜| 亚洲AV日韩综合一区尤物| 亚洲av无码片vr一区二区三区 | 亚洲日韩国产一区二区三区| 国产美女av在线一区| 波多野结衣免费一区视频| 91video国产一区| 国产午夜精品一区二区三区极品| 日韩一区二区精品观看| 日本一区二区三区高清| 日韩人妻不卡一区二区三区| 怡红院一区二区三区| 综合久久一区二区三区 | 国产欧美色一区二区三区|