国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開發(fā) > HTML5 > 正文

HTML5通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭問(wèn)題

2024-09-05 07:23:25
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

navigator.mediaDevices.getUserMedia

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

API環(huán)境

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

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

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

根據(jù)官方文檔,目前navigator.mediaDevices.getUserMedia在ios上只支持11版本以上,且只能在safari正常運(yùn)行。安卓目前沒(méi)有發(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);	});  }}

問(wèn)題三:(第一次啟用成功調(diào)用前置攝像頭,第二次需要調(diào)用后置卻黑屏或者失敗)

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

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

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

var deviceInfoId="", //攝像頭ID    num = 0, //攝像頭數(shù)量    carema = []; //攝像頭ID數(shù)組    //在頁(yè)面加載完成后獲得設(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è)加不加好像沒(méi)有影響                })                .catch(function (err) {                    console.log(err.name + ": " + err.message);                });

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

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

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

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

完整代碼如下:
頁(yè)面代碼:

<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="h5" 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();            }        },

到此這篇關(guān)于HTML5通過(guò)navigator.mediaDevices.getUserMedia調(diào)用手機(jī)攝像頭問(wèn)題的文章就介紹到這了,更多相關(guān)HTML5調(diào)用 攝像頭內(nèi)容請(qǐng)搜索武林網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持武林網(wǎng)!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 德钦县| 天祝| 张掖市| 山西省| 城口县| 中阳县| 隆尧县| 安新县| 卫辉市| 屏山县| 长阳| 临夏市| 额济纳旗| 瑞安市| 休宁县| 二连浩特市| 温州市| 重庆市| 司法| 台东县| 永清县| 库伦旗| 阿图什市| 富民县| 屏山县| 瑞丽市| 古交市| 吉林市| 汉川市| 瑞昌市| 上高县| 苏尼特右旗| 抚顺县| 波密县| 昭通市| 新和县| 惠来县| 宜城市| 阳新县| 奈曼旗| 木兰县|