在 HTML5 中捕獲音頻和視頻

來源:互聯網
上載者:User

標籤:nsa   mcu   efi   應該   政策   name   gpu   dem   img   

簡介

長久以來,音頻/視頻捕獲都是網路開發中的“聖杯”。多年來,我們總是依賴於瀏覽器外掛程式(Flash 或 Silverlight)實現這一點。快來看看吧!

現在輪到 HTML5 大顯身手了。也許看起來不是很顯眼,但是 HTML5 的崛起引發了對裝置硬體訪問的激增。地理位置 (GPS)、Orientation API(加速計)、WebGL(GPU) 和 Web Audio API(視頻硬體)都是很好的例子。這些功能非常強大,展示了基於系統底層硬體功能之上的進階 JavaScript API。

本教程介紹了一種新 API:navigator.getUserMedia(),可讓網路應用訪問使用者的相機和麥克風。

getUserMedia() 的曆史

如果您還不知道,getUserMedia() 的曆史可謂一段有趣的故事。

過去幾年中出現過好幾種“Media Capture API”的變體。很多人意識到,需要能夠在網路上訪問本地裝置,但這要所有人合力開發出一種新的規範。局面一片混亂,以至於 W3C 最終決定成立一個工作群組。他們只有一個目的:理清混亂的局面!裝置 API 政策 (DAP) 工作群組負責對過剩的提議進行統一和標準化。

我會試著總結一下 2011 所發生的事情...

第 1 輪:HTML 媒體捕獲

HTML 媒體捕獲是 DAP 在網路媒體捕獲標準化上邁出的第一步。具體方法是超載<input type="file"> 並為 accept 參數添加新值。

如果您要讓使用者通過網路攝影機拍攝自己的快照,就可以使用 capture=camera

<input type="file" accept="image/*;capture=camera">

  

錄製視頻或音頻也是類似的:

<input type="file" accept="video/*;capture=camcorder"><input type="file" accept="audio/*;capture=microphone">

  

挺不錯吧?它可以重複使用檔案輸入,這點我特別喜歡。這在語義上非常有意義。這種特定“API”的不足之處在於,無法處理即時效果(例如將即時網路攝影機資料呈現到 <canvas> 並應用 WebGL 過濾器)。HTML 媒體捕獲只能讓您錄製媒體檔案或及時拍攝快照。

支援

  • Android 3.0 瀏覽器 - 首次實施的一個例子。請觀看此視頻,瞭解其實際使用方式。
  • Android 版 Chrome 瀏覽器 (0.16)

除非您使用的是以上某個行動瀏覽器,否則我建議您不要使用該 API。供應商紛紛轉向 getUserMedia()。其他任何人都不太可能會長期實施 HTML 媒體捕獲。

第 2 輪:裝置元素

很多人認為 HTML 媒體捕獲的局限性太大,因此一種新的規範應運而生,可以支援任何類型的(未來)裝置。不出意料地,該設計需要新的 <device> 元素,也就是getUserMedia() 的前身。

Opera 是第一批根據 <device> 元素建立視頻捕獲的初始實施的瀏覽器之一。不久之後(準確地說是同一天),WhatWG 決定廢止 <device> 標記,以支援稱為navigator.getUserMedia() 的新興 JavaScript API。一周后,Opera 推出的新版本中加入了對更新的 getUserMedia() 規範的支援。當年年底,Microsoft 也加入這一行列,發布了 IE9 實驗室以支援新規範。

<device> 的效果如下:

<device type="media" onchange="update(this.data)"></device><video autoplay></video><script>  function update(stream) {    document.querySelector(‘video‘).src = stream.url;  }</script>

  

支援

很遺憾,發行的瀏覽器中沒有任何一款曾經包含 <device>。我猜這是一個不太需要擔心的 API。但是 <device> 確實有兩大優點:一是語義方面,二是可以輕鬆進行擴充,而不僅僅是支援音頻/視頻裝置。

現在深吸一口氣。這玩意兒速度飛快!

第 3 輪:WebRTC

<device> 元素最終還是像渡渡鳥一樣銷聲匿跡了。

依靠 WebRTC(網路即時通訊)的大力協助,最近幾個月尋找合適捕獲 API 的步伐加快了很多。該規範由 W3C WebRTC 工作群組負責監管。Google、Opera、Mozilla 和其他一些公司目前正致力於在自己的瀏覽器中實施該 API。

getUserMedia() 與 WebRTC 相關,因為它是通向這組 API 的門戶。它提供了訪問使用者本地相機/麥克風媒體流的手段。

支援

在 Chrome 瀏覽器 18.0.1008 和更高版本中,可在 about:flags 下啟用 WebRTC。

使用入門

利用 navigator.getUserMedia(),我們最終實現了在沒有外掛程式的情況下訪問網路攝影機和麥克風輸入內容。相機存取權限現在和調用有關,而不是和安裝有關。它直接內嵌在瀏覽器中。感到興奮了嗎?

啟用

getUserMedia() API 還很新,只有 Google 和 Opera 在開發人員版本中加入了它。在 Chrome 18 和更高版本中,可通過訪問 about:flags 啟用該 API。

在 Chrome 瀏覽器的 about:flags 頁中啟用 getUserMedia()

 

對於 Opera,請下載某個實驗性 Android 和案頭電腦版本。

功能檢測

功能檢測是簡單地檢查是否存在 navigator.getUserMedia

function hasGetUserMedia() {  // Note: Opera builds are unprefixed.  return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||            navigator.mozGetUserMedia || navigator.msGetUserMedia);}if (hasGetUserMedia()) {  // Good to go!} else {  alert(‘getUserMedia() is not supported in your browser‘);}

  

擷取輸入裝置的存取權限:

要使用網路攝影機或麥克風,我們需要請求許可權。getUserMedia() 的第一個參數用於指定您要訪問的媒體類型。例如,如果您要請求訪問網路攝影機,第一個參數就應該是 "video"。要同時使用麥克風和相機,則傳遞 "video, audio"

<video autoplay></video><script>  var onFailSoHard=function(e) {    console.log(‘Reeeejected!‘, e);  };  // Not showing vendor prefixes.  navigator.getUserMedia(‘video, audio‘, function(localMediaStream) {    var video = document.querySelector(‘video‘);    video.src = window.URL.createObjectURL(localMediaStream);    // Note: onloadedmetadata doesn‘t fire in Chrome when using it with getUserMedia.    // See crbug.com/110938.    video.onloadedmetadata = function(e) {      // Ready to go. Do some stuff.    };  }, onFailSoHard);</script>

  

好吧,這到底是怎麼一回事呢?媒體捕獲是各種新 HTML5 API 進行協作的絕佳樣本。參與協作的還有其他一些 HTML 元素,例如 <audio> 和 <video>。請注意,我們不是要設定 src 屬性或在 <video> 元素中加入 <source> 元素。我們不會向視頻饋入媒體檔案的網址,而是饋入從代表網路攝影機的 LocalMediaStream 對象獲得的 Blob 網址。

我還會將 <video> 設定為 autoplay,否則它會停在第一幀。添加 controls 也能達到您預期的效果。

請注意:在 Chrome 瀏覽器中存在一個錯誤,導致僅僅傳遞“audio”無效:crbug.com/112367。我也無法在 Opera 中正常使用 <audio>

Opera 和 Chrome 瀏覽器實施的是該規範的不同版本。這導致實際使用起來要比預期的更有“挑戰性”。

在 Chrome 瀏覽器中

該程式碼片段適用於 Chrome 18 和更高版本(在 about:flags 中啟用):

navigator.webkitGetUserMedia(‘audio, video‘, function(localMediaStream) {  var video = document.querySelector(‘video‘);  video.src = window.webkitURL.createObjectURL(localMediaStream);}, onFailSoHard);

  

在 Opera 中

Opera 開發人員版本不支援該規範的更新版本。該程式碼片段適用於 Opera:

navigator.getUserMedia({audio: true, video: true}, function(localMediaStream) {  video.src = localMediaStream;}, onFailSoHard);

  

關鍵的區別之處在於:

  • getUserMedia() 是無首碼的。
  • 對象作為第一個參數而不是字串列表進行傳遞。
  • 將 video.src 直接設定為 LocalMediaStream 對象,而不是 Blob 網址。據我所知,Opera 最終會更新此設定,改為要求 Blob 網址。

對於這兩者

如果您希望能跨瀏覽器通用(但是這樣很容易出問題),請嘗試如下方法:

var video = document.querySelector(‘video‘);if (navigator.getUserMedia) {  navigator.getUserMedia({audio: true, video: true}, function(stream) {    video.src = stream;  }, onFailSoHard);} else if (navigator.webkitGetUserMedia) {  navigator.webkitGetUserMedia(‘audio, video‘, function(stream) {    video.src = window.webkitURL.createObjectURL(stream);  }, onFailSoHard);} else {  video.src = ‘somevideo.webm‘; // fallback.}

  

請務必查看 Mike Taylor 和 Mike Robinson 的 gUM Shield。它可以很好地將各瀏覽器實施之間的不一致“標準化”。

安全

將來,瀏覽器在調用 getUserMedia() 時可能會彈出資訊列,讓使用者選擇授予還是拒絕對其相機/麥克風的存取權限。很遺憾,該規範在安全方面非常薄弱。目前,沒有任何瀏覽器實施了許可權欄。

提供回退

對於無法獲得 getUserMedia() 支援的使用者,如果 API 不受支援且/或由於某些原因而調用失敗,可以選擇回退到現有的視頻檔案:

// Not showing vendor prefixes or code that works cross-browser:function fallback(e) {  video.src = ‘fallbackvideo.webm‘;}function success(stream) {  video.src = window.URL.createObjectURL(stream);}if (!navigator.getUserMedia) {  fallback();} else {  navigator.getUserMedia({video: true}, success, fallback);}

<canvas> API 的 ctx.drawImage(video, 0, 0) 方法可以輕鬆地將 <video> 幀繪製到 <canvas> 上。當然,既然我們通過 getUserMedia() 獲得了視頻輸入,就可輕鬆地使用即時視頻建立照相亭應用了。

<video autoplay></video><img src=""><canvas style="display:none;"></canvas>var video = document.querySelector(‘video‘);var canvas = document.querySelector(‘canvas‘);var ctx = canvas.getContext(‘2d‘);var localMediaStream = null;function snapshot() {  if (localMediaStream) {    ctx.drawImage(video, 0, 0);    // "image/webp" works in Chrome 18. In other browsers, this will fall back to image/png.    document.querySelector(‘img‘).src = canvas.toDataURL(‘image/webp‘);  }}video.addEventListener(‘click‘, snapshot, false);// Not showing vendor prefixes or code that works cross-browser.navigator.getUserMedia({video: true}, function(stream) {  video.src = window.URL.createObjectURL(stream);  localMediaStream = stream;}, onFailSoHard);

  

總結

總體而言,網路上的裝置訪問向來是一大難題。很多人曾經嘗試過,但是沒什麼人取得成功。大多數早期的思路從未在專有環境之外佔據主導地位,也從未廣泛採用過。

真正的問題在於,網路的安全模式與本地系統有天壤之別。例如,我可能不希望隨便什麼網站都有權訪問我的攝像機,但是這個問題很難解決。

PhoneGap 等橋接架構有助於突破這方面的限制,但這種臨時性的解決方案對於深層的根本問題而言還遠遠不夠。要讓網路應用具備與案頭電腦應用一較高下的實力,我們需要能夠訪問本地裝置。

getUserMedia() 僅僅是對新裝置類型的第一波訪問。我希望在不久的將來能看到更多。

其他資源
  • W3C 規範
  • 布魯斯·勞森 (Bruce Lawson) 的 HTML5Doctor 文章
  • 布魯斯·勞森的 dev.opera.com 文章
示範
  • 即時照相亭
  • 保羅·尼夫 (Paul Neave) 的 WebGL 相機效果
  • Snapster
  • WebGL 中的直播視頻

摘自:https://www.html5rocks.com/zh/tutorials/getusermedia/intro/

在 HTML5 中捕獲音頻和視頻

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.