1. 程式人生 > >WebRTC系列(1)-手把手教你實現一個瀏覽器拍照室Demo

WebRTC系列(1)-手把手教你實現一個瀏覽器拍照室Demo

1.WebRTC開發背景

  由於業務需求,需要在專案中實現實時音視訊通話功能,之前基於瀏覽器開發的Web專案要進行音視訊通話,需要安裝flash外掛才能實現或者使用C/S客戶端進行通訊。隨著網際網路技術的驅動下,在很多場景下需要進行音視訊通訊,在生活中我們現在使用電話越來越少,使用微信和視訊越來越多。在一些行業也需要進行音視訊實時通訊,如:線上教育,遠端醫療,保險理賠等等。有了WebRTC,可以開發一些好的網頁應用,使得音視訊通話越來越簡單,無需安裝任何外掛,只需開啟網頁,就能實現音視訊通話,方然也能實現訊息收發,檔案收發等等,下面,根據自己平時的專案開發與,對WebRTC就行一個簡單的理解與概述,最終實現一個簡單的拍照室Demo。

2.WebRTC歷史和概述

  WebRTC是“網路實時通訊”(Web Real Time Communication)的縮寫。它最初是為了解決瀏覽器上視訊通話而提出的,即兩個瀏覽器之間直接進行視訊和音訊的通訊,不經過伺服器。後來發展到除了音訊和視訊,還可以傳輸文字和其他資料。2010年5月,Google以6820萬美元收購VoIP軟體開發商Global IP Solutions的GIPS引擎,並改為名為“WebRTC”。WebRTC使用GIPS引擎,實現了基於網頁的視訊會議,並支援722,PCM,ILBC,ISAC等編碼,同時使用谷歌自家的VP8視訊解碼器;同時支援RTP/SRTP傳輸等。Google是WebRTC的主要支持者和開發者,它推動了WebRTC標準的確立。

  WebRTC是一門年輕的技術,從2011推出到2017年,一直髮展的不溫不火。根據一段時間的開發,個人認為主要原因有:各個瀏覽器的支援相容程度和在網際網路環境下點對點能夠連線的成功率。從2017年蘋果公司宣佈iOS11的Safari瀏覽器支援WebRTC,一些雲通訊產品例如騰訊雲通訊和網易雲通訊也是基於WebRTC上進行封裝二次開發,也間接的說明了WebRTC發展會越來越好。

   

3.基本概念的瞭解

  為了簡化開發,WebRTC在瀏覽器中API集成了大量的技術,解決了一些繁重的問題,如捕捉攝像頭和麥克風,處理音視訊流,傳輸層等等。

      

  • 捕捉攝像頭和麥克風

  建立通訊平臺第一步要檢測使用者裝置的攝像頭和麥克風許可權,先檢測裝置的可用性,然後在獲取使用者授權並與裝置建立連線,最後獲取一段資料流。

  • 音訊與視訊的編解碼

  在網際網路要傳送一段音視訊資料,技術優化了網路資料,資料尺寸也還是很大,所以要對資料在傳送端編碼,然後在接收端解碼。WebRTC內建的幾種編解碼器包括:H.264,Opcus,iSAC,VP8。作為前端開發的我,最這些編解碼技術當然不是很瞭解。幸運的是,當兩個瀏覽器回話時,會綜合兩端情況選擇最優的編解碼器。

  • 傳輸層

  主要處理資料丟包,資料包排序以及建立使用者之間的連線問題

  • 會話管理

  通常來說就是信令(Signaling),負責在瀏覽器中建立並管理多個連線。

4.獲取使用者媒體

  建立一個基於WebRTC的通訊平臺,首先要通過使用者的網路攝像頭和麥克風獲取實時的視訊和音訊流,可以通過呼叫瀏覽器的getUserMedia API來實現。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>獲取媒體流</title>
</head>
<body>
<div id="app">
  <h1>獲取媒體流</h1>
  <video autoplay></video>
</div>
<script>
  function hasUserMedia() {
    return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
  }

  if (hasUserMedia()) {
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
    navigator.getUserMedia({video: true, audio: false}, function (stream) {
      console.log(stream);
      var video = document.querySelector('video');
      video.src=window.URL.createObjectURL(stream);
    }, function (err) {
      console.log(err);
    });
  } else {
    alert("Sorry, your browser does not support getUserMedia.");
  }
</script>
</body>
</html>

是否開啟使用攝像頭許可權

  注意:開啟攝像頭後獲取到的視訊流展示在Video標籤中,video標籤需要加上autoplay屬性視訊才可以播放,在除錯中可以把getUserMedia方法引數中的audio設定為:false,避免雜音太大,同理,把video設定為false只能聽到自己說話而沒有畫面,可以代替普通電話使用。

5.限制視訊流

  我們可以通過設定引數來控制視訊和音訊是否使用,除此之外,我們可以傳入一個物件做更復雜的限制,如解析度,視訊寬高比等等。

navigator.getUserMedia({video: {
        width: 320,
        /*height:240,*/
        aspectRatio:1.77
      }, audio: false}, function (stream) {
      console.log(stream);
      var video = document.querySelector('video');
      video.src=window.URL.createObjectURL(stream);
    }, function (err) {
      console.log(err);
    });

可以根據自己業務需求來設定固定的寬高或解析度等等。

6.完成一個拍照室Demo

  通過呼叫攝像頭獲取到的視訊流以及H5的canvas標籤我們可以完成一個簡易的拍照功能。

增加一個拍照按鈕以及一個canvas,修改後的整個頁面程式碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>獲取媒體流</title>
</head>
<body>
<div id="app">
  <h1>獲取媒體流</h1>
  <video id="video" autoplay></video>
  <button type="button" onclick="capture()">點選拍照</button>
  <canvas id="canvas" width="320" height="240"></canvas>
</div>
<script>
  function hasUserMedia() {
    return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);
  }

  if (hasUserMedia()) {
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
    navigator.getUserMedia({video: {
        width: 320,
        height:240,
      }, audio: false}, function (stream) {
      console.log(stream);
      var video = document.querySelector('video');
      video.src=window.URL.createObjectURL(stream);
    }, function (err) {
      console.log(err);
    });
  } else {
    alert("Sorry, your browser does not support getUserMedia.");
  }

  function capture(){
    console.log('capture...');
    var cxt=document.getElementById('canvas').getContext('2d');
    var video=document.getElementById('video');
    cxt.drawImage(video,0,0);
  }
</script>
</body>
</html>

現在單擊一個點選拍照按鈕,可以捕捉視訊的某一幀並同時繪製到canvas上,加上canvas功能本來就很強大,後期對照片的旋轉,剪裁,濾鏡也都是可以實現的。

延伸:現在很多WebApp上要實時上傳證件功能,我們通過這種WebRTC+canvas也是可以實現的,而且是瀏覽器直接調的硬體拍照,有沒有很溜。

7.開發中遇到的問題

  在直接用http開啟本地伺服器頁面是調用不了攝像頭的,瀏覽器的限制認為http下是不安全的,但是可以用127.0.0.1或者localhost來代替本機ip。網頁部署到伺服器時也得使用https協議來返回頁面,否則,無法呼叫攝像頭。

  

  以上簡單的介紹了WebRTC的發展歷史以及一些基本概念,讓大家對其有個初步的瞭解,最後通過呼叫攝像頭完成一個拍照室的Demo。後續文章再詳細的寫如何通過WebRTC來實現點對點通訊,相信WebRTC功能會越來越強大,這只是第一步。


 

參考資料:

《Learning WebRTC 中文版》 

《JavaScript 標準參考教程(alpha) 阮一峰》

  WebRTC百科

轉載請註明出處,謝謝。