HTML5如何通過navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭

這篇文章主要介紹了HTML5如何通過navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

公司主營業(yè)務(wù):成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。成都創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)推出克山免費(fèi)做網(wǎng)站回饋大家。

navigator.mediaDevices.getUserMedia

應(yīng)項(xiàng)目要求,需要實(shí)現(xiàn)移動(dòng)端app嵌入H5頁面完成實(shí)人認(rèn)證的功能。打開getUserMedia文檔,鏈接如下:
https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia
看上去很簡單,最終卻寫的懷疑人生。

API環(huán)境

問題一:(為什么不管怎么配置都顯示前置攝像頭)

想正常使用API必須在https環(huán)境下進(jìn)行,否則你會發(fā)現(xiàn)不管怎么寫,都只能調(diào)用默認(rèn)的攝像頭(大部分都是前置,只有少部分是后置)
前端開發(fā)者可以將文件上傳至"碼云"倉庫,獲取https鏈接然后在手機(jī)上預(yù)覽
鏈接:碼云倉庫入口

問題二:(API在安卓和ios效果一樣嗎?)

根據(jù)官方文檔,目前navigator.mediaDevices.getUserMedia在ios上只支持11版本以上,且只能在safari正常運(yùn)行。安卓目前沒有發(fā)現(xiàn)版本限制,需要兼容的代碼如下

if (navigator.mediaDevices === undefined) {
    navigator.mediaDevices = {};
 }
if (navigator.mediaDevices.getUserMedia === undefined) {
    navigator.mediaDevices.getUserMedia = function (constraints) {
    var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
	if (!getUserMedia) {
	    return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
	}
	return new Promise(function (resolve, reject) {
		getUserMedia.call(navigator, constraints, resolve, reject);
	});
  }
}

問題三:(第一次啟用成功調(diào)用前置攝像頭,第二次需要調(diào)用后置卻黑屏或者失?。?/strong>

失敗的原因很多,列舉兩個(gè)一開始我遇到的問題
1.前置攝像頭調(diào)用后,攝像功能需要關(guān)閉后才能正常執(zhí)行第二次調(diào)用,否則會報(bào)錯(cuò):設(shè)備被占用。解決方法,在每次執(zhí)行調(diào)用方法前,先關(guān)閉攝像設(shè)備。

if (window.stream) {
    window.stream.getTracks().forEach(track => {
          track.stop();
    });
}

親測有用,別的找了很多停止的方法都沒有效果。
2.調(diào)用后置API的方法還是無法喚醒后置攝像頭,于是我找到另外一個(gè)方法,通過查看手機(jī)攝像頭ID,來直接喚醒后置。

var deviceInfoId="", //攝像頭ID
    num = 0, //攝像頭數(shù)量
    carema = []; //攝像頭ID數(shù)組
    //在頁面加載完成后獲得設(shè)備ID數(shù)組
window.onload = navigator.mediaDevices.enumerateDevices().then(gotDevices);
function gotDevices(deviceInfos) {
        for (let i = 0; i < deviceInfos.length; ++i) {
            if (deviceInfos[i].kind === 'videoinput') {
                carema.push(deviceInfos[i].deviceId)
              }
        }
        deviceInfoId = carema[后置位置];
}
            var constraints = {
                audio: false,
                video: {
                    deviceId: deviceInfoId,
                    //放在app里面需要下面配置一下
                    "permissions": {
                        "audio-capture": {
                            "description": "Required to capture audio using getUserMedia()"
                        },
                        "video-capture": {
                            "description": "Required to capture video using getUserMedia()"
                        }
                    }
                }
            };
            navigator.mediaDevices.getUserMedia(constraints)
                .then(function (stream) {
                    var video = document.getElementById('video');
                    try {
                        window.stream = stream;
                        video.srcObject = stream;
                    } catch (error) {
                        video.src = window.URL.createObjectURL(stream);
                    }
                    this.localMediaStream = stream;
                    // video.play();   這個(gè)加不加好像沒有影響
                })
                .catch(function (err) {
                    console.log(err.name + ": " + err.message);
                });

如果只是一部手機(jī)可以這樣,但是測試了多部手機(jī)發(fā)現(xiàn)攝像頭數(shù)組毫無規(guī)律可循,這個(gè)方法慎用。
如果頁面上添加選擇攝像設(shè)備的按鈕的話,這個(gè)方法還是不錯(cuò)的。查看設(shè)備能調(diào)用幾個(gè)攝像頭鏈接如下:https://webrtc.github.io/samples/src/content/devices/input-output/
由于我們的項(xiàng)目頁面不希望出現(xiàn)切換按鈕,面對后置出現(xiàn)的眾多BUG,最終選擇放棄,使用input調(diào)用攝像頭。

 <input class="card_input" v-on:change="appCapture($event)" type="file" accept="image/*" capture="camera" />

成功調(diào)用后用canvas實(shí)現(xiàn)成像并適應(yīng)屏幕大小

我這里的代碼是取video的寬高然后復(fù)制給canvas,這樣可以讓canvas和video保持一致,只用給video設(shè)置寬度100%,高度調(diào)節(jié)成合適的值,就實(shí)現(xiàn)了適應(yīng)手機(jī)屏幕。

  var video = document.getElementById('video');
            var canvas = document.getElementById('canvas'),
                ctx = canvas.getContext('2d'),
                CHeight = video.clientHeight, //獲取屏幕大小讓canvas自適應(yīng)
                CWidth = video.clientWidth;
            canvas.width = CWidth;
            canvas.height = CHeight;
            //localMediaStream 在data里定義一個(gè){}
            if (localMediaStream) {
                ctx.drawImage(video, 0, 0, CWidth, CHeight);
                var dataURL = canvas.toDataURL('image/jpeg'); //dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA'
                img.src = dataURL;

video成像鏡像問題

API喚醒的前置攝像頭是相反的,很不舒服很不舒服。
之后用css處理一下給video添加 transform: rotate(180deg),可以實(shí)現(xiàn)反轉(zhuǎn),但是還是沒有達(dá)到和手機(jī)一樣的效果。
這時(shí)候可以選擇通過設(shè)備ID調(diào)用前置攝像頭,前置攝像頭的laval一直都是“default”,也有的是空值,但是也能實(shí)現(xiàn)。
配置代碼如下:

 var constraints = window.constraints = {
                audio: false,
                video: {
                    sourceId: 'default',
                    facingMode:  { exact: "user" } 
                }
              };

完美調(diào)用自己手機(jī)的前置攝像頭!?。?/p>

完整代碼如下:
頁面代碼:

<div @click='moveToCameraAVG()' v-cloak>
     <img v-if="imginfo!==''" :src="imginfo" />
     <div class="warm_title2">點(diǎn)擊自拍一張頭像</div>
</div>
<video id="video" class="pic_video" playsinline autoplay x5-video-player-type="h6" style='object-fit:fill'></video>
<canvas id="canvas" class="canvas_pic" style='margin: 0;padding: 0;'></canvas>
<div class="bottom_div">
    <div>拍照</div>
    <img src='images/pic_btn.png' class="capture-btn" @click='captureAvg' />
</div>
 // 頭像相機(jī)
        moveToCameraAVG() {
            var self = this;
            if (navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {};
            }
            if (navigator.mediaDevices.getUserMedia === undefined) {
                navigator.mediaDevices.getUserMedia = function (constraints) {
                    var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
                    if (!getUserMedia) {
                        return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
                    }
                    return new Promise(function (resolve, reject) {
                        getUserMedia.call(navigator, constraints, resolve, reject);
                    });
                }
            }
            if (window.stream) {
                window.stream.getTracks().forEach(track => {
                    track.stop();
                });
            }
            var constraints = window.constraints = {
                audio: false,
                video: {
                    sourceId: 'default',
                    facingMode:  { exact: "user" } 
                }
              };
            navigator.mediaDevices.getUserMedia(constraints)
                .then(function (stream) {
                    var video = document.getElementById('video');
                    try {
                        window.stream = stream;
                        video.srcObject = stream;
                    } catch (error) {
                        video.src = window.URL.createObjectURL(stream);
                    }
                    self.localMediaStream = stream;
                    video.play();
                })
                .catch(function (err) {
                    alert(err.name + ": " + err.message);
                });
        },
        //停止攝像機(jī)
        stopCapture: function () {
            var video = document.getElementById('video');
            if (!video.srcObject) return
            let stream = video.srcObject
            let tracks = stream.getTracks();
            tracks.forEach(track => {
                track.stop()
            })
        },
        // 頭像照片
        captureAvg() {
            var vm = this;
            var video = document.getElementById('video');
            var canvas = document.getElementById('canvas'),
                ctx = canvas.getContext('2d'),
                CHeight = video.clientHeight, //獲取屏幕大小讓canvas自適應(yīng)
                CWidth = video.clientWidth;
            canvas.width = CWidth;
            canvas.height = CHeight;
            if (vm.localMediaStream) {
                ctx.drawImage(video, 0, 0, CWidth, CHeight);
                var dataURL = canvas.toDataURL('image/jpeg'); //dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA'
                vm.imginfo = dataURL;
                // 停止攝像機(jī)
                video.pause();
                this.stopCapture();
            }
        },

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“HTML5如何通過navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭”這篇文章對大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

當(dāng)前名稱:HTML5如何通過navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭
文章源于:http://muchs.cn/article12/ipjdgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、云服務(wù)器靜態(tài)網(wǎng)站、網(wǎng)站制作、電子商務(wù)服務(wù)器托管

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)