<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                &emsp;&emsp;WebRTC (Web Real-Time Communications) 是一項實時通訊技術,在 2011 年由 Google 提出,經過 10 年的發展,W3C 于 2021 年正式發布 WebRTC 1.0 標準。 :-: ![](https://img.kancloud.cn/bf/7a/bf7aa23f2c6c9a98eecf24898ef302b0_688x388.png =400x) &emsp;&emsp;WebRTC 標準概括介紹了兩種不同的技術:媒體捕獲設備和點對點連接(P2P,Peer-to-Peer),可讓用戶無需安裝任何插件或第三方軟件的情況下,實現共享桌面、文件傳輸、視頻直播等功能。 &emsp;&emsp;下圖是[官方](https://webrtc.github.io/webrtc-org/architecture/)給出的一張 WebRTC 整體架構設計圖: :-: ![](https://img.kancloud.cn/57/e7/57e738ed8019aa6a79b4345aeed5c3bb_740x482.png =500x) * 紫色部分是前端開發所使用的 API。 * 藍色實線部分是各大瀏覽器廠商所使用的 API。 * 藍色虛線部分包含可自定義的 3 塊:音頻引擎、視頻引擎和網絡傳輸。 &emsp;&emsp;由于各個瀏覽器對 WebRTC 的實現有所不同,因此 Google 官方提供了一個適配器腳本庫:[adapter.js](https://github.com/webrtc/adapter/),省去很多兼容工作。 &emsp;&emsp;本文的源碼已上傳至[Github](https://github.com/pwstrick/webrtc),有需要的可以隨意下載。 ## 一、自拍 &emsp;&emsp;自拍是指通過攝像頭拍照生成圖片,先看下 HTML 結構,其實就 4 個元素。 ~~~html <video id="video"></video> <button id="btn">拍照</button> <canvas id="canvas" width="300" height="300"></canvas> <img id="img" alt="照片"/> ~~~ **1)getUserMedia()** &emsp;&emsp;然后在腳本中聲明各個元素,通過 navigator.[mediaDevices](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices).getUserMedia() 方法獲取媒體流。 ~~~ const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); const btn = document.getElementById('btn'); const img = document.getElementById('img'); const size = 300; /** * 獲取媒體流 */ navigator.mediaDevices.getUserMedia({ video: { width: size, height: size, }, audio: false }).then((stream) => { video.srcObject = stream; video.play(); }); ~~~ &emsp;&emsp;getUserMedia() 的參數是一個包含了video 和 audio 兩個成員的 MediaStreamConstraints 對象,上面代碼將攝像頭的分辨率限制為 300 x 300。 &emsp;&emsp;then() 中的 stream 參數是一個[MediaStream](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaStream)媒體流,一個流相當于容器,可以包含幾條軌道,例如視頻和音頻軌道,每條軌道都是獨立的。 &emsp;&emsp;video 元素中的 src 和[srcObject](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLMediaElement/srcObject)是一對互斥的屬性,后者可關聯媒體源,根據規范也可以是 Blob 或者 File 等類型的數據。 &emsp;&emsp;接著為按鈕綁定點擊事件,并且在點擊時從流中捕獲幀,畫到 Canvas 內,再導出賦給 img 元素。 ~~~ /** * 點擊拍照 */ btn.addEventListener('click', (e) => { const context = canvas.getContext('2d'); // 從流中捕獲幀 context.drawImage(video, 0, 0, size, size); // 將幀導出為圖片 const data = canvas.toDataURL('image/png'); img.setAttribute('src', data); }, false); ~~~ &emsp;&emsp;在下圖中,左邊是 video 元素,打開攝像頭后就會有畫面,在點擊拍照按鈕后,右邊顯示捕獲的幀。 :-: ![](https://img.kancloud.cn/31/c8/31c84cd431fd843277237c65c91befb8_1374x642.png =600x) **2)enumerateDevices()** &emsp;&emsp;MediaDevices 提供了訪問媒體輸入和輸出的設備,例如攝像頭、麥克風等,得到硬件資源的媒體數據。 &emsp;&emsp;mediaDevices.[enumerateDevices()](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/enumerateDevices)會得到一個描述設備的[MediaDeviceInfo](https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo)的數組。 &emsp;&emsp;其中 groupId 用于標識多個設備屬于同一個物理設備,例如一個顯示器內置了攝像頭和麥克風。 ~~~ navigator.mediaDevices.enumerateDevices() .then((devices) => { devices.forEach((device) => { console.log(`${device.kind}: ${device.label} id = ${device.deviceId}`); }); }) ~~~ **3)devicechange** &emsp;&emsp;當媒體設備(例如麥克風、攝像頭等)連接到系統或從系統中移除時,[devicechange](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/devicechange_event)事件就會被發送給設備實例。 ~~~ navigator.mediaDevices.ondevicechange = (event) => { }; ~~~ &emsp;&emsp;event 參數沒有附加任何特殊的屬性。 ## 二、共享桌面 &emsp;&emsp;Windows 系統采用的共享桌面協議是 RDP(Remote Desktop Protocal),另一種可在不同操作系統共享桌面的協議是 VNC(Virtual Network Console)。 &emsp;&emsp;像 TeamViewer 采用的就是后一種協議,而 WebRTC 的遠程桌面沒有采用傳統的 RDP、VNC 等協議,因為不需要遠程控制。 &emsp;&emsp;WebRTC 提供了[getDisplayMedia()](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getDisplayMedia)方法采集桌面,在使用上與之前的 getUserMedia() 方法類似。 ~~~ navigator.mediaDevices.getDisplayMedia({ video: { width: 2000, height: 1000 } }).then((stream) => { video.srcObject = stream; video.play(); }); ~~~ &emsp;&emsp;在刷新頁面后,會要求選擇共享的桌面,包括整個屏幕、窗口或 Chrome 標簽頁。 :-: ![](https://img.kancloud.cn/18/b6/18b6c43f47ff38b4f4237fbb68b2fbea_1216x1076.png =800x) ## 三、錄像 &emsp;&emsp;WebRTC 的錄像包括錄制音頻和視頻兩種流,通過[Blob](https://developer.mozilla.org/zh-CN/docs/Web/API/Blob)對象將數據保存成多媒體文件。 **1)MediaRecorder** &emsp;&emsp;WebRTC 提供了[MediaRecorder](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaRecorder)類,它能接收兩個參數,第一個是遠程的 MediaStream 媒體流,第二個是配置項。 &emsp;&emsp;其配置項包括編解碼器、音視頻碼率、容器的[MIME](https://www.iana.org/assignments/media-types/media-types.xhtml)類型(例如 video/webm、video/mp4 )等相關信息。 &emsp;&emsp;先看個示例,HTML結構如下所示,一個 video 元素和兩個 button 元素:回放和下載。 ~~~html <video id="video"></video> <button id="playback">回放</button> <button id="download">下載</button> ~~~ &emsp;&emsp;然后看下錄像的整體邏輯,和之前自拍一節類似,也需要調用 getUserMedia() 獲取媒體流。 &emsp;&emsp;在 then() 的回調中實例化 MediaRecorder 類,并配置多媒體格式。 &emsp;&emsp;其中WebM是一個由Google資助,免版權費用的視頻文件格式;VP8是一個開放的影像壓縮格式。 ~~~ const video = document.getElementById('video'); const playback = document.getElementById('playback'); const download = document.getElementById('download'); const size = 300; const chunks = []; // 一個由 Blob 對象組成的數組 navigator.mediaDevices.getUserMedia({ video: { width: size, height: size, }, audio: true }).then((stream) => { // 配置多媒體格式 const options = { mimeType: 'video/webm;codecs=vp8' }; // 實例化錄制對象 const recorder = new MediaRecorder(stream, options); // 當收到數據時觸發該事件 recorder.ondataavailable = function(e) { chunks.push(e.data); // data 是一個可用的 Blob 對象 } // 開始錄制 recorder.start(10); }); ~~~ &emsp;&emsp;recorder 的[dataavailable](https://developer.mozilla.org/zh-CN/docs/Web/API/MediaRecorder/dataavailable_event)事件會在收到數據時觸發,e 參數的 data 屬性是一個可用的 Blob 對象。 &emsp;&emsp;最后在開始錄制調用 start() 方法時,可以配置一個毫秒級的時間片,那么在錄制時會按照配置的值分割成一個個單獨的區塊,而不是錄制一個非常大的整塊內容。 &emsp;&emsp;分塊可以提高效率和可靠性,如果是一整塊,那么會變得越來越大,讀寫效率也會變差。 **2)回放** &emsp;&emsp;首先根據 chunks 生成 Blob 對象,再根據 Blob 對象生成 URL 對象。 ~~~ playback.addEventListener('click', () => { // 根據 chunks 生成 Blob 對象 const blob = new Blob(chunks, {type: 'video/webm'}); // 根據 Blob 對象生成 URL 對象 video.src = window.URL.createObjectURL(blob); video.play(); }, false); ~~~ &emsp;&emsp;URL.[createObjectURL](https://developer.mozilla.org/zh-CN/docs/Web/API/URL/createObjectURL)是一個靜態方法,返回值是一個指定的[File](https://developer.mozilla.org/zh-CN/docs/Web/API/File)對象或 Blob 對象。 **3)下載** &emsp;&emsp;首先與回放一樣,也是生成一個 URL 對象,然后創建 a 元素,將對象賦給 href 屬性。 &emsp;&emsp;并且要指定 download 屬性,告訴瀏覽器下載 URL 而不是導航。 ~~~ download.addEventListener('click', (e) => { const blob = new Blob(chunks, {type: 'video/webm'}); const url = window.URL.createObjectURL(blob); // 創建 a 元素 const a = document.createElement('a'); a.href = url; // 指示瀏覽器下載 URL 而不是導航 a.download = 'test.webm'; a.click(); }, false); ~~~ 參考資料: [WebRTC官方](https://webrtc.org/getting-started/overview) [WebRTC MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/WebRTC_API) [Build the backend services needed for a WebRTC app](https://web.dev/webrtc-infrastructure/) ***** > 原文出處: [博客園-HTML躬行記](https://www.cnblogs.com/strick/category/1770829.html) [知乎專欄-HTML躬行記](https://zhuanlan.zhihu.com/c_1250826149041238016) 已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎閱讀。 ![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200) 推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看