無需Flash錄視頻——HTML5中級進階

ImaWDMB 8年前發布 | 405K 次閱讀 HTML5 前端技術

前言

HTML5的權限越來越大了,瀏覽器可以直接調用攝像頭、麥克風了,好激動啊。我們要用純潔的HTML代碼造出自己的天地。

視頻采集

本篇介紹的栗子 都是在chrome 47 版本以上的,低版本的可能會出現白屏和錯誤。

1.安全環境

隨著Chrome版本的升高,安全性問題也越來越被重視,較新版本的Chrome瀏覽器在調用一些API時需要頁面處在安全環境中。 本篇文章所介紹的API函數,都需要在安全環境中執行。 如果處在非安全環境下 ( http頁面 ) 這些API就會有意想不到的問題。

比如 getUserMedia() 就會報出警告,并執行出錯。而在設備枚舉 enumerateDevices() 時,雖然不會報錯,但是他隱藏了設備label。

getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.

根據谷歌的意思,常用的安全環境有如下

  • http://localhost
  • http://127.0.0.1
  • https 開頭的地址頁面

如果你做了一個視頻測試的頁面,想嘚瑟給局域網的其他人,但是又沒有域名證書怎么辦?

這時候只能通過修改其他人的hosts文件了

比如你的測試服務器IP地址是192.168.2.18,那么其他人的hosts文件修改如下:

#localhost 127.0.0.1
localhost 192.168.2.18

當使用別人的Chrome瀏覽器訪問 http://localhost/[getUserMediaTestPage]時,就會順利的執行這些API了。

但是移動端的瀏覽器并不認localhost,就算你修改了hosts ,移動端的瀏覽器根本不理你,解析都不解析。

所以想在手機上測試,只能老老實實申請個證書了。

2.設備枚舉

在開啟攝像頭之前,先要把可以使用的麥克風和攝像頭 ( 輸入設備 ) 列出來,如果沒有這兩樣設備也就無法繼續。

代碼如下:

<label for="audioDevice"> 錄音設備: </label>
<select id="audioDevice">

</select> <br> <label for="videoDevice"> 錄影設備: </label> <select id="videoDevice">

</select>

<script> navigator.mediaDevices.enumerateDevices().then(function (data) { data.forEach(function (item) { if(item.kind=="audioinput"){ //麥克風 document.getElementById("audioDevice").innerHTML += "<option value='"+ item.deviceId +"'>" + item.label + " </option> " }else if(item.kind=="videoinput"){ //攝像頭 document.getElementById("videoDevice").innerHTML += "<option value='"+ item.deviceId +"'>" + item.label + " </option> " } }) },function (error) { console.log(error); }) </script></code></pre>

效果如下圖,和瀏覽器自己獲取的一模一樣。

這里寫圖片描述

注意:上圖的實例中,瀏覽器地址欄最右邊的攝像頭標識是需要使用 getUserMedia() 函數時才會出現。

<script>
    var getUserMedia = navigator.webkitGetUserMedia; //Chrome瀏覽器的方法
    getUserMedia.call(navigator, {
      video:true, // 開啟音頻
      audio:true  // 開啟視頻
    }, function(stream){
        console.log(stream); // 成功獲取媒體流
    }, function(error){
        //處理媒體流創建失敗錯誤
    });
</script>

這時候可以通過瀏覽器給出的菜單下拉選擇設備。

3.設置參數,預覽

我們可以通過代碼來指定使用哪個攝像頭和麥克風設備。

也可以通過代碼設置視頻的寬、高和幀率。

代碼如下:

<video id="video" autoplay></video> <!-- 一定要有 autoplay -->

<script> var getUserMedia = navigator.webkitGetUserMedia ;

getUserMedia.call(navigator, { "audio":{ "mandatory":{ "sourceId":"" // 指定設備的 deviceId } }, "video":{ "optional":[ {"minWidth":400}, {"maxWidth":400}, // 數字類型,固定寬度 {"minHeight":220}, {"maxHeight":220}, // 數字類型,固定高度 {"frameRate":"12"} // 幀率 ],"mandatory":{ "sourceId":"" // 指定設備的 deviceId } } }, function(stream){ //綁定本地媒體流到video標簽用于輸出 document.getElementById("video").src = URL.createObjectURL(stream); }, function(error){ //處理媒體流創建失敗錯誤 });

</script></code></pre>

輸出的視頻流通過blob對象鏈接綁定到video標簽輸出。

這個 deviceId 就是從上文設備枚舉 enumerateDevices() 獲取到的。

兩種設備,如果有一個 deviceId 填寫不正確,就會報出一個 DevicesNotFoundError 的錯誤。而且一旦指定了設備后,瀏覽器自己的設備選擇就會變成灰色不可選。

視頻的寬高,并不會因為填寫的數值比例不合法而失真。

比如你設定了寬度30,高度100,那么他會從視頻中心截取 30x100 的畫面,而不是把原畫面擠壓到這個30x100的尺寸。

效果如下:

這里寫圖片描述

如果您的預覽一片漆黑,或者只有一個小黑點,那么說明您的攝像頭正在被占用...

可是Chrome并沒有遵循它,而且差距還挺大...

視頻保存

1. 格式支持

Chrome瀏覽器是大力推廣webm的視頻格式的。可以用 MediaRecorder.isTypeSupported("video/webm") 來測試是否支持這種類型的編碼。如果返回true,那么我們錄制的視頻就可以被保存為這種指定的格式。如果不指定,那么將會使用瀏覽器自動指定的文件格式。文檔原話如下

If this paramater is not specified, the UA will use a platform-specific default format.

但是這個默認值卻無法直接獲取,全靠猜...

2. 視頻錄制 MediaRecorder

我們使用 MediaRecorder 來錄制視頻,參數是通過 getUserMedia() 獲取的媒體流。

  • 通過綁定 ondataavailable 事件,來獲取視頻片段數據,并在內存中累積。
  • 錄制的開始和結束分別使用 start 和 stop 函數。
  • 執行 start 之后會周期性觸發 ondataavailable 事件。
  • 執行 stop 之后會停止觸發 ondataavailable 事件。
  • 錄制結束后,把累計的片段數據保存為blob對象,并從瀏覽器下載存為視頻文件。

代碼如下:

<script>

var getUserMedia = navigator.webkitGetUserMedia ; var g_stream = null, g_recorder = null; function startPreview(){ getUserMedia.call(navigator, { video:true, audio:true }, function(stream){ g_stream = stream; }, function(error){

}); }

function stopRecording(){ g_recorder.stop(); }

function startRecording(){ var chunks = []; g_recorder = new MediaRecorder(g_stream,{mimeType:"video/webm"}); g_recorder.ondataavailable = function(e) { chunks.push(e.data); } g_recorder.onstop = function(e) { var blob = new Blob(chunks, { 'type' : 'video/webm' }); var audioURL = URL.createObjectURL(blob); window.open(audioURL); } g_recorder.start(); } </script></code></pre>

注意:本例并沒有填寫視頻文件頭,所以保存出來的視頻文件沒有時間軌,無法快進和跳躍。

 

 

來自:http://www.jianshu.com/p/231f6c92f3fb

 

 本文由用戶 ImaWDMB 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!