WebRTC學習(三)WebRTC設備管理


一:WebRTC設備管理

(一)重要API,用於獲取音視頻設備

其中返回的ePromise結果,是一個Promise對象。

Promise對象的結構體:MediaDevicesInfo 

deviceID:是設備唯一標識符ID
label:是設備的名字(可讀的)
kind:設備的種類(音頻輸入/輸出兩種,視頻輸入/輸出兩類)
groupID:同一個設備可能包含兩種類型,比如輸入/輸出;但是這兩種都是包含同一個groupID

(二)JavaScript中的Promise (異步調用中的其中一種方式)

補充:javascript中是使用單線程去處理邏輯,所以為了防止阻塞,大量使用了異步調用

詳解見:https://segmentfault.com/a/1190000017312249

(三)獲取音視頻設備

1.開啟web服務器indexEnt.js

'use strict'

var http = require("http");
var https = require("https");
var fs = require("fs");

var express = require("express");
var serveIndex = require("serve-index");


var app = express();                    //實例化express
app.use(serveIndex("./"));        //設置首路徑,url會直接去訪問該目錄下的文件
app.use(express.static("./"));    //可以訪問目錄下的所有文件

//http server
var http_server = http.createServer(app);    //這里不使用匿名函數,使用express對象
http_server.listen(80,"0.0.0.0");

//https server
var options = {
    key : fs.readFileSync("./ca/learn.webrtc.com-key.pem"),            //同步讀取文件key
    cert: fs.readFileSync("./ca/learn.webrtc.com.pem"),                //同步讀取文件證書
};

var https_server = https.createServer(options,app);
https_server.listen(443,"0.0.0.0");

2.設置index.html

<html>
    <head>
        <title>    WebRTC get audio and video devices </title>
        <script type="text/javascript" src="./js/client.js"></script>
    </head>
    <body>
        <h1>Index.html</h1>
    </body>
</html>

3.設置client.js

'use strict'

if(!navigator.mediaDevices || 
    !navigator.mediaDevices.enumerateDevices){
    console.log("enumerateDevices is not supported!");
}else{
    navigator.mediaDevices.enumerateDevices()
        .then(gotDevices)
        .catch(handleError);
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

4.開啟服務

5.查看結果 

id=default;
label=Default;
kind=audioinput;
groupId=8d355f6b4ffa173a4a3abe47cc76b4dedbbda93d62b957ad304464800815a8c2
id=fa3e397324529d0c1be02a329546e19a7db69350fe732303452e6d244faea4c1;
label=USB2.0 PC CAMERA Analog Mono;
kind=audioinput;
groupId=c5b67b2337e654ff12177ec8ed48e5580bdc5b8a8ee7fdce3602b8a4a802a99f
id=bf54ed3e6df71ed91193adde9d206e51b1d4a5afdaeb231c75a35466842df89e;
label=USB2.0 PC CAMERA (1908:2310);
kind=videoinput;
groupId=c5b67b2337e654ff12177ec8ed48e5580bdc5b8a8ee7fdce3602b8a4a802a99f
id=default;
label=Default;
kind=audiooutput;
groupId=default
id=dcc0783c108eda571ae81899ece6885794e66f772a47bc77e8977b9c92ca0c77;
label=GK107 HDMI Audio Controller Digital Stereo (HDMI);
kind=audiooutput;
groupId=640919e62e4194110dbe498a3852671af27dd8b1e91315cb4f8a5b55aa5bea4c
id=4bdac7c5ce801e116da8fbb3ee278f7559af4ff55f58c48c78be855dc21932fc;
label=Built-in Audio Analog Stereo;
kind=audiooutput;
groupId=4aaccae20f6f54f68e7d1b6df6ba9f7118de2af094b2ed5cefd0ff5c64afeb43

注意:我們需要先設置站點,允許攝像頭和麥克風才能獲取信息

(四)顯示設備到頁面

1.修改index.html

<html>
    <head>
        <title>    WebRTC get audio and video devices </title>
    </head>
    <body>
        <h1>Index.html</h1>
        <div>
            <label>Audio Input Device:</label>
            <select id="audioInput"></select>
        </div>
        <div>
            <label>Audio Output Device:</label>
            <select id="audioOutput"></select>
        </div>
        <div>
            <label>Video Input Device:</label>
            <select id="videoInput"></select>
        </div>
    </body>
    <script type="text/javascript" src="./js/client.js"></script>
    
</html>

注意:script中要使用到id信息,所以script應該寫在所有需要的id元素后面!!

2.修改client.js文件

'use strict'

var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");

if(!navigator.mediaDevices || 
    !navigator.mediaDevices.enumerateDevices){
    console.log("enumerateDevices is not supported!");
}else{
    navigator.mediaDevices.enumerateDevices()
        .then(gotDevices)
        .catch(handleError);
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

二:WebRTC獲取音視頻數據

(一)采集音視頻數據

 

其中constraints參數類型為MediaStreamConstraints 

分別對video與audio進行限制,可以用布爾類型或者MediaTrackConstraints類型,其中MediaTrackConstraints可以進行詳細的設置(比如幀率、分辨率、聲道)

1.實現index2.html

<html>
    <head>
        <title>    WebRTC capture audio and video data </title>
    </head>
    <body>
        <h1>Index2.html</h1>
        <p>autoplay:獲取視頻源后自動播放</p>
        <p>playsinline:在頁面中播放,而不是調用第三方工具</p>
        <video autoplay playsinline id="player"></video>
    </body>
    <script type="text/javascript" src="./js/client2.js"></script>
    
</html>

2.實現client2.js

'use strict'

var videoplay = document.querySelector("video#player");

if(!navigator.mediaDevices || 
    !navigator.mediaDevices.getUserMedia){
    console.log("getUserMedia is not supported!");
}else{
    var constraints = {
        video : true,
        audio : true
    }

    navigator.mediaDevices.getUserMedia(constraints)
                .then(getUserMedia)
                .catch(handleError);
}

function getUserMedia(stream){
    videoplay.srcObject = stream;    //設置采集到的流進行播放
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

(二)getUserMedia適配問題(在WebRTC規范1.0之前)

對於不同的瀏覽器,實現了不同版本的getUserMedia

解決方法一:自己實現

解決方法二:使用google開源庫 adapter.js 適配各個瀏覽器接口

隨着規范的使用,以后可以不用考慮適配問題!

<html>
    <head>
        <title>    WebRTC capture audio and video data </title>
    </head>
    <body>
        <h1>Index2.html</h1>
        <p>autoplay:獲取視頻源后自動播放</p>
        <p>playsinline:在頁面中播放,而不是調用第三方工具</p>
        <video autoplay playsinline id="player"></video>
    </body>
    <script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="text/javascript" src="./js/client2.js"></script>
</html>

(三)獲取音視頻設備的訪問權限

在一中獲取了音視頻設備之后,雖然在chrome中可以顯示結果,但是在其他瀏覽器中並沒有顯示,比如Firefox

左(chrome)右(Firefox),因為我們沒有允許訪問權限。其實前面的chrome權限也是我們提前去設置中開啟的。

但是我們可以使用前面(一)中的getUserMedia方法,去使得瀏覽器彈出訪問權限請求窗口,從而去獲取權限!!

1.index3.html實現

<html>
    <head>
        <title>    WebRTC get audio and video devices </title>
    </head>
    <body>
        <h1>Index.html</h1>
        <div>
            <label>Audio Input Device:</label>
            <select id="audioInput"></select>
        </div>
        <div>
            <label>Audio Output Device:</label>
            <select id="audioOutput"></select>
        </div>
        <div>
            <label>Video Input Device:</label>
            <select id="videoInput"></select>
        </div>
        <video autoplay playsinline id="player"></video>
    </body>
    <script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="text/javascript" src="./js/client3.js"></script>
    
</html>
View Code

2.client3.js實現

'use strict'

var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");


var videoplay = document.querySelector("video#player");

if(!navigator.mediaDevices || 
    !navigator.mediaDevices.getUserMedia){
    console.log("getUserMedia is not supported!");
}else{
    var constraints = {
        video : true,
        audio : true
    }

    navigator.mediaDevices.getUserMedia(constraints)
                .then(getUserMedia)  //getUserMedia獲取權限,返回enumerateDevices進行串聯
               .then(gotDevices) //可以進行串聯處理
                .catch(handleError);
}

function getUserMedia(stream){
    videoplay.srcObject = stream;    //設置采集到的流進行播放
    return navigator.mediaDevices.enumerateDevices(); //為了進行串聯處理!!!
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

結果顯示: 

三:WebRTC音視頻采集約束

通過約束,可以精確的控制音視頻的采集數據!!

(一)視頻參數調整

width與height用來控制分辨率,寬高比
aspectRatio = 寬/高
frameRate幀率
facingMode設置攝像頭模式
resizeMode是否進行裁剪

'use strict'

var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");

var videoplay = document.querySelector("video#player");

if(!navigator.mediaDevices || 
    !navigator.mediaDevices.getUserMedia){
    console.log("getUserMedia is not supported!");
}else{
    var constraints = {
        video : {
            width:320,
            height:240,
            frameRate:30,
            facingMode:"user"
        },
        audio : false
    }

    navigator.mediaDevices.getUserMedia(constraints)
                .then(getUserMedia)
                .then(gotDevices)    //可以進行串聯處理
                .catch(handleError);
}

function getUserMedia(stream){
    videoplay.srcObject = stream;    //設置采集到的流進行播放
    return navigator.mediaDevices.enumerateDevices();    //為了進行串聯處理!!!
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

(二)音頻參數調整

sampleSize:采樣大小(位深)
echoCancellation:回音消除
autoGainControl:自動增益,是否在原有聲音基礎上,增強音量
noiseSuppression:降噪
latency:延遲大小(延遲小,則實時性強)
channelCount:聲道數量
deviceID:選取設備的切換
groupID:組ID 
'use strict'

var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");


var videoplay = document.querySelector("video#player");

function start(){
    console.log("start......");
    if(!navigator.mediaDevices || 
        !navigator.mediaDevices.getUserMedia){
        console.log("getUserMedia is not supported!");
    }else{
        var devId = videoInput.value;
        var constraints = {
            video : {
                width:320,
                height:240,
                frameRate:30,
                facingMode:"user"
            },
            audio : {
                noiseSuppression:true,
                echoCancellation:true
            },
            deviceId : devId ? devId : undefined    //undefined是使用默認設備
        }

        navigator.mediaDevices.getUserMedia(constraints)
                    .then(getUserMedia)
                    .then(gotDevices)    //可以進行串聯處理
                    .catch(handleError);
    }
}

function getUserMedia(stream){
    videoplay.srcObject = stream;    //設置采集到的流進行播放
    return navigator.mediaDevices.enumerateDevices();    //為了進行串聯處理!!!
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

start(); //開始執行邏輯

//---------設置事件-----select選擇攝像頭之后
videoInput.onchange = start;

四:WebRTC視頻特效處理

(一)瀏覽器視頻特效

在瀏覽器中使用CSS filter進行特效處理,在不同的瀏覽器中,filter不同。
在瀏覽器中使用filter進行渲染的時候,底層最終就是調用OpenGL或者Metal等等

(二)支持的特效種類(常見的)

(三)代碼實現

<html>
    <head>
        <title>    WebRTC get audio and video devices </title>
        <style>
            .none {
                -webkit-filter: none;
            }

            .blue {
                -webkit-filter: blur(3px); 
            }

            .grayscale {
                -webkit-filter: grayscale(1);
            }

            .invert {
                -webkit-filter: invert(1);
            }

            .sepia {
                -webkit-filter: sepia(1);
            }
        </style>
    </head>
    <body>
        <h1>Index3.html</h1>
        <div>
            <label>Audio Input Device:</label>
            <select id="audioInput"></select>
        </div>
        <div>
            <label>Audio Output Device:</label>
            <select id="audioOutput"></select>
        </div>
        <div>
            <label>Video Input Device:</label>
            <select id="videoInput"></select>
        </div>
        <div>
            <label>Filter:</label>
            <select id="filter">
                <option value="none">None</option>
                <option value="blur">blur</option>
                <option value="grayscale">grayscale</option>
                <option value="invert">invert</option>
                <option value="sepia">sepia</option>
            </select>
        </div>
        <video autoplay playsinline id="player"></video>
    </body>
    <script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="text/javascript" src="./js/client3.js"></script>
    
</html>
index3.html

實現client3.js

'use strict'

var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");
var filtersSelect = document.getElementById("filter"); var videoplay = document.querySelector("video#player");

function start(){
    console.log("start......");
    if(!navigator.mediaDevices || 
        !navigator.mediaDevices.getUserMedia){
        console.log("getUserMedia is not supported!");
    }else{
        var devId = videoInput.value;
        var constraints = {
            video : {
                width:320,
                height:240,
                frameRate:30,
                facingMode:"user"
            },
            audio : {
                noiseSuppression:true,
                echoCancellation:true
            },
            deviceId : devId ? devId : undefined    //undefined是使用默認設備
        }

        navigator.mediaDevices.getUserMedia(constraints)
                    .then(getUserMedia)
                    .then(gotDevices)    //可以進行串聯處理
                    .catch(handleError);
    }
}

function getUserMedia(stream){
    videoplay.srcObject = stream;    //設置采集到的流進行播放
    return navigator.mediaDevices.enumerateDevices();    //為了進行串聯處理!!!
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

start();    //開始執行邏輯

//---------設置事件-----select選擇攝像頭之后
videoInput.onchange = start;
filtersSelect.onchange = function(){ videoplay.className = filtersSelect.value;  //修改使用的類名 }

五:從視頻中獲取圖片

通過html中canvas標簽去視頻流中獲取對應的幀,輸出為圖片即可。

1.添加button控件,觸發事件去獲取圖片(從視頻流中)

2.添加canvas,去將幀轉換為圖片
<html>
    <head>
        <title>    WebRTC get audio and video devices </title>
        <style>
            .none {
                -webkit-filter: none;
            }

            .blue {
                -webkit-filter: blur(3px); 
            }

            .grayscale {
                -webkit-filter: grayscale(1);
            }

            .invert {
                -webkit-filter: invert(1);
            }

            .sepia {
                -webkit-filter: sepia(1);
            }
        </style>
    </head>
    <body>
        <h1>Index3.html</h1>
        <div>
            <label>Audio Input Device:</label>
            <select id="audioInput"></select>
        </div>
        <div>
            <label>Audio Output Device:</label>
            <select id="audioOutput"></select>
        </div>
        <div>
            <label>Video Input Device:</label>
            <select id="videoInput"></select>
        </div>
        <div>
            <label>Filter:</label>
            <select id="filter">
                <option value="none">None</option>
                <option value="blur">blur</option>
                <option value="grayscale">grayscale</option>
                <option value="invert">invert</option>
                <option value="sepia">sepia</option>
            </select>
        </div>
        <div>
            <button id="snapshot">Take snapshot</button>
        </div>
        <div>
            <canvas id="picture"></canvas>
        </div>
        <video autoplay playsinline id="player"></video>
    </body>
    <script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="text/javascript" src="./js/client3.js"></script>
    
</html>
index3.html

client.js文件實現

'use strict'

//設備
var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");
//過濾器
var filtersSelect = document.getElementById("filter");
//圖片
var snapshot = document.getElementById("snapshot"); var picture = document.getElementById("picture"); picture.width = 320; picture.height = 240; //視頻
var videoplay = document.querySelector("video#player");

function start(){
    console.log("start......");
    if(!navigator.mediaDevices || 
        !navigator.mediaDevices.getUserMedia){
        console.log("getUserMedia is not supported!");
    }else{
        var devId = videoInput.value;
        var constraints = {
            video : {
                width:320,
                height:240,
                frameRate:30,
                facingMode:"user"
            },
            audio : {
                noiseSuppression:true,
                echoCancellation:true
            },
            deviceId : devId ? devId : undefined    //undefined是使用默認設備
        }

        navigator.mediaDevices.getUserMedia(constraints)
                    .then(getUserMedia)
                    .then(gotDevices)    //可以進行串聯處理
                    .catch(handleError);
    }
}

function getUserMedia(stream){
    videoplay.srcObject = stream;    //設置采集到的流進行播放
    return navigator.mediaDevices.enumerateDevices();    //為了進行串聯處理!!!
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

start();    //開始執行邏輯

//---------設置事件-----select選擇攝像頭之后
videoInput.onchange = start;

filtersSelect.onchange = function(){
    videoplay.className = filtersSelect.value;
}

snapshot.onclick = function(){
   picture.className = filtersSelect.value; //設置圖片的特效
picture.getContext("2d") //獲取圖像上下文,為2d圖像 .drawImage(videoplay, //從視頻流源中,獲取數據 0,0, picture.width,picture.height);
}

圖片的保存並不會保存特效信息!!! 

六:WebRTC只采集音頻數據

1.index4.html

<html>
    <head>
        <title>    WebRTC get audio devices </title>
    </head>
    <body>
        <h1>Index4.html</h1>
        <div>
            <label>Audio Input Device:</label>
            <select id="audioInput"></select>
        </div>
        <div>
            <label>Audio Output Device:</label>
            <select id="audioOutput"></select>
        </div>
        <div>
            <label>Video Input Device:</label>
            <select id="videoInput"></select>
        </div>

        <div>
  <!--controls會將控制按鈕顯示出來-->  <audio autoplay controls id="audioplayer"></audio>   
        </div>
    </body>
    <script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="text/javascript" src="./js/client4.js"></script>
    
</html>

2.client4.js實現

'use strict'

//設備
var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");

//音頻
var audioplay = document.querySelector("audio#audioplayer");

function start(){
    console.log("start......");
    if(!navigator.mediaDevices || 
        !navigator.mediaDevices.getUserMedia){
        console.log("getUserMedia is not supported!");
    }else{
        var constraints = { video : false, audio : true }

        navigator.mediaDevices.getUserMedia(constraints)
                    .then(getUserMedia)
                    .then(gotDevices)    //可以進行串聯處理
                    .catch(handleError);
    }
}

function getUserMedia(stream){
 audioplay.srcObject = stream;    //設置采集到的流進行播放
    return navigator.mediaDevices.enumerateDevices();    //為了進行串聯處理!!!
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

start();    //開始執行邏輯

七:MediaStream API及獲取視頻約束

(一)MediaStream中的方法和事件

1.方法

addTrack:   向媒體流中添加軌 removeTrack: 從媒體流中移除軌 getVideoTracks:將所有的視頻軌獲取 getAudioTracks:將所有的音頻軌獲取

2.事件

(二)獲取視頻約束

<html>
    <head>
        <title>    WebRTC get audio and video devices </title>
        <style>
            .none {
                -webkit-filter: none;
            }

            .blue {
                -webkit-filter: blur(3px); 
            }

            .grayscale {
                -webkit-filter: grayscale(1);
            }

            .invert {
                -webkit-filter: invert(1);
            }

            .sepia {
                -webkit-filter: sepia(1);
            }
        </style>
    </head>
    <body>
        <h1>Index3.html</h1>
        <div>
            <label>Audio Input Device:</label>
            <select id="audioInput"></select>
        </div>
        <div>
            <label>Audio Output Device:</label>
            <select id="audioOutput"></select>
        </div>
        <div>
            <label>Video Input Device:</label>
            <select id="videoInput"></select>
        </div>
        <div>
            <label>Filter:</label>
            <select id="filter">
                <option value="none">None</option>
                <option value="blur">blur</option>
                <option value="grayscale">grayscale</option>
                <option value="invert">invert</option>
                <option value="sepia">sepia</option>
            </select>
        </div>
        <div>
            <button id="snapshot">Take snapshot</button>
        </div>
        <div>
            <canvas id="picture"></canvas>
        </div>

        <div>
            <table>
                <tr>
                    <td>
                        <video autoplay playsinline id="player"></video>
                    </td>
                    <td>
                        <div id="constraints"></div>
                    </td>
                </tr>
            </table>
        </div>
    </body>
    <script type="text/javascript" src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script type="text/javascript" src="./js/client3.js"></script>
    
</html>
index3.html
'use strict'

//設備
var audioInput = document.getElementById("audioInput");
var audioOutput = document.getElementById("audioOutput");
var videoInput = document.getElementById("videoInput");
//過濾器
var filtersSelect = document.getElementById("filter");
//圖片
var snapshot = document.getElementById("snapshot");
var picture = document.getElementById("picture");
//約束顯示
var divConstraints = document.querySelector("div#constraints");

picture.width = 320;
picture.height = 240;
//視頻
var videoplay = document.querySelector("video#player");

function start(){
    console.log("start......");
    if(!navigator.mediaDevices || 
        !navigator.mediaDevices.getUserMedia){
        console.log("getUserMedia is not supported!");
    }else{
        var devId = videoInput.value;
        var constraints = {
            video : {
                width:320,
                height:240,
                frameRate:30,
                facingMode:"user"
            },
            audio : {
                noiseSuppression:true,
                echoCancellation:true
            },
            deviceId : devId ? devId : undefined    //undefined是使用默認設備
        }

        navigator.mediaDevices.getUserMedia(constraints)
                    .then(getUserMedia)
                    .then(gotDevices)    //可以進行串聯處理
                    .catch(handleError);
    }
}

function getUserMedia(stream){
    videoplay.srcObject = stream;    //設置采集到的流進行播放

    //獲取視頻的track
    var videoTrack = stream.getVideoTracks()[0];    //只有一個,所以只取一個
    var videoConstraints = videoTrack.getSettings();    //獲取約束對象

    divConstraints.textContent = JSON.stringify(videoConstraints,null,2);        //轉為json

    return navigator.mediaDevices.enumerateDevices();    //為了進行串聯處理!!!
}

function gotDevices(deviceInfos){
    deviceInfos.forEach(function(deviceInfo){
        console.log("id="+deviceInfo.deviceId+
                    ";label="+deviceInfo.label+
                    ";kind="+deviceInfo.kind+
                    ";groupId="+deviceInfo.groupId);

        var option = document.createElement("option");
        option.text = deviceInfo.label;
        option.value = deviceInfo.deviceId;

        if(deviceInfo.kind === "audioinput"){
            audioInput.appendChild(option);
        }else if(deviceInfo.kind === "audiooutput"){
            audioOutput.appendChild(option);
        }else if(deviceInfo.kind === "videoinput"){
            videoInput.appendChild(option);
        }
    });
}

function handleError(err){
    console.log(err.name+":"+err.message);
}

start();    //開始執行邏輯

//---------設置事件-----select選擇攝像頭之后
videoInput.onchange = start;

filtersSelect.onchange = function(){
    videoplay.className = filtersSelect.value;
}

snapshot.onclick = function(){
    picture.className = filtersSelect.value;    //設置圖片的特效
    picture.getContext("2d")        //獲取圖像上下文
            .drawImage(videoplay,    //從視頻流源中,獲取數據
                0,0,
                picture.width,picture.height);    
}
client3.js

 

{ 
"aspectRatio": 1.3333333333333333,
"brightness": 128,
"contrast": 130,
"deviceId": "bf54ed3e6df71ed91193adde9d206e51b1d4a5afdaeb231c75a35466842df89e",
"frameRate": 30,
"groupId": "d0a8260d845d1e294dbf6819b7c36eedf635dd555e2529b7609c1fe25c9a1f82",
"height": 240,
"resizeMode": "none",
"saturation": 64,
"sharpness": 13,
"whiteBalanceMode": "none",
"width": 320
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM