PC端调用摄像头拍照(vue)以及解决getUserMedia is not implemented in this browser

下面这段代码是在html文件中执行调用摄像头,然后进行拍照的功能,一切都是按照里面的步骤去走的,功能也确实可以实现,后面的代码就是 vue 实现这个功能的逻辑代码(如果你还直接使用,你就会发现一个坑爹的问题,请继续看下去)

html文件内容

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>拍照2</title>
</head>

<body>
<button id="button_take">拍照</button><br />
<div style="float: left;width:50%"><video id="v"></video></div>
<canvas id="canvas" style="display:none;"></canvas><br />
<img src="http://placehold.it/640&text=Your%20image%20here%20..." id="photo" alt="photo" style="float: left;">
</body>

<script>
    !(function () {
        // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
        if (navigator.mediaDevices === undefined) {
            navigator.mediaDevices = {};
        }
        if (navigator.mediaDevices.getUserMedia === undefined) {
            navigator.mediaDevices.getUserMedia = function (constraints) {
                // 首先,如果有getUserMedia的话,就获得它
                var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

                // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
                if (!getUserMedia) {
                    return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
                }

                // 否则,为老的navigator.getUserMedia方法包裹一个Promise
                return new Promise(function (resolve, reject) {
                    getUserMedia.call(navigator, constraints, resolve, reject);
                });
            }
        }
        const constraints = {
            video: true,
            audio: false
        };
        let videoPlaying = false;
        let v = document.getElementById('v');
        let promise = navigator.mediaDevices.getUserMedia(constraints);
        promise.then(stream => {
            // 旧的浏览器可能没有srcObject
            if ("srcObject" in v) {
                v.srcObject = stream;
            } else {
                // 防止再新的浏览器里使用它,应为它已经不再支持了
                v.src = window.URL.createObjectURL(stream);
            }
            v.onloadedmetadata = function (e) {
                v.play();
                videoPlaying = true;
            };
        }).catch(err => {
            console.error(err.name + ": " + err.message);
        });
        document.getElementById('button_take').addEventListener('click', function () {
            if (videoPlaying) {
                let canvas = document.getElementById('canvas');
                canvas.width = v.videoWidth;
                canvas.height = v.videoHeight;
                canvas.getContext('2d').drawImage(v, 0, 0);
                let data = canvas.toDataURL('image/webp');
                document.getElementById('photo').setAttribute('src', data);
                //   canvas.getContext("2d").drawImage(Img,0,0,width,height); //将图片绘制到canvas中
            }
        }, false);
    })();
</script>
</html>

vue项目中使用(组件),你会发现无法调起摄像头,提示getUserMedia is not implemented in this browser,那是谷歌的安全策略,下面附带解决办法

<template>
    <div class="flc">
        <div class="video-Box">
            <div>
                <video id="videoCamera" width="250" height="250" autoplay style="border-radius:180px;box-shadow: darkgrey 0 0  30px 5px ;"></video>
            </div>
            <canvas style="display:none; " id="canvasCamera" width="250" height="250"></canvas>
        </div>
        <div class="img_bg_camera" v-if="imgSrc">
            <p style="color: #000000;">图片显示</p>
            <img :src="imgSrc" alt="" class="tx_img" style="border-radius:360px;box-shadow: darkgrey 0 0  30px 5px ;" v-if="imgif">
        </div>
        <div class="bommen" style="margin-top: 50px;">
           <el-button type="success" @click="getCompetence()">打开摄像头</el-button>
           <el-button type="success" @click="closeCarama()">关闭摄像头</el-button>
            <el-button type="success" @click="setImage()">拍照</el-button>
           <el-button type="primary" @click="uploadImage()">提交</el-button>
            <el-button type="primary" @click="save">保存</el-button>
        </div>
    </div>
</template>

<script>
import { Message  } from 'element-ui'
export default {
    data() {
        return {
            imgif: false,
            videoWidth: 250,
            videoHeight: 250,
            imgSrc: '', //图片src
            canvasCamera: null,
            contextCamera: null,
            videoCamera: null,
        }
    },
    mounted() {
    },
    methods: {
        // 打开摄像头
        getCompetence() {
            this.canvasCamera = document.getElementById('canvasCamera')
            this.contextCamera = this.canvasCamera.getContext('2d')
            this.videoCamera = document.getElementById('videoCamera')
            var _this = this
            // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
            if (navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {}
            }
            // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
            // 使用getUserMedia,因为它会覆盖现有的属性。
            // 这里,如果缺少getUserMedia属性,就添加它。
            if (navigator.mediaDevices.getUserMedia === undefined) {
                navigator.mediaDevices.getUserMedia = function (constraints) {
                    // 首先获取现存的getUserMedia(如果存在)
                    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia
                    // 有些浏览器不支持,会返回错误信息
                    // 保持接口一致
                    if (!getUserMedia) {
                        return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
                    }
                    // 否则,使用Promise将调用包装到旧的navigator.getUserMedia
                    return new Promise(function (resolve, reject) {
                        getUserMedia.call(navigator, constraints, resolve, reject)
                    })
                }
            }
            var constraints = {
                audio: false,
                video: {
                    width: this.videoWidth,
                    height: this.videoHeight,
                    transform: 'scaleX(-1)'
                }
            }
            navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
                // 新的浏览器使用srcObject。旧的浏览器可能没有srcObject
                if ('srcObject' in _this.videoCamera) {
                    _this.videoCamera.srcObject = stream
                } else {
                    // 避免在新的浏览器中使用它,因为它正在被弃用。
                    _this.videoCamera.src = window.URL.createObjectURL(stream)
                }
                _this.videoCamera.onloadedmetadata = function (e) {
                    _this.videoCamera.play()
                }
            }).catch(err => {
                console.log(err)
                Message({ message: '没有开启摄像头权限或浏览器版本不兼容', type: 'warning' })
            })
        },
        closeCarama() {
            this.videoCamera.srcObject.getTracks()[0].stop()
        },
        //  绘制图片(拍照功能)
        setImage() {
            this.imgif = true
            // 点击,canvas画图
            this.contextCamera.drawImage(this.videoCamera, 0, 0, 250, 250)
            // 获取图片base64链接
            var image = this.canvasCamera.toDataURL('image/png')
            this.imgSrc = image
            console.log(this.imgSrc);
        },
        save () {
            if (this.imgSrc) return this.$emit('creamOver',this.imgSrc)
            Message({ message: '还未进行拍摄', type: 'error' })
        },
        //上传数据
        uploadImage() {
            var file = this.imgSrc
            console.log(file);
            //base64数据放formData里面
            var formData = new FormData(); //*
            formData.append("multipartFile", file); //*
            formData.append("password", this.ruleForm.password); //*
            formData.append("username", this.ruleForm.name); //*
            //自己配置axios。上传
            
        },

    }
}
</script>

<style scoped lang="scss">
.flc {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.face {
  width: 400px;
  height: 450px;
  position: relative;
}

.face .face-img {
  width: 400px;
  height: 450px;
  position: absolute;
  left: 0px;
  top: 0px;
}

.face .face-content {
  width: 310px;
  height: 322px;
  position: absolute;
  top: 64px;
  left: 45px;
}

.face .face-content #video {
  object-fit: fill;
}

.step {
  text-align: center;
  margin-top: 30px;
}

.step .step-ul .step-li .step-title {
  font-size: 16px;
  color: #65dffe;
  padding-bottom: 10px;
}

.step .step-ul .step-li .step-title .step-titleimg {
  height: 26px;
  width: 26px;
  margin-left: 20px;
  cursor: pointer;
}

.step .step-ul .step-li .step-img {
  height: 150px;
  width: 150px;
  border: 3px solid #eecfa1;
  border-radius: 50%;
}

.step .step-ul .step-li .step-img img {
  height: 100%;
  width: auto;
}
</style>

getUserMedia is not implemented in this browser解决办法

  1. 使用 https 协议
  2. 客户端浏览器手动指定域名安全

在谷歌输入网址的地方输入

chrome://flags/#unsafely-treat-insecure-origin-as-secure

在里面配置指定域名,然后选择 select 为 enabled 然后重启,就解决问题啦

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我是一个语言模型AI,我没有能力调用摄像头录制视频。不过,您可以尝试使用WebRTC技术来实现在浏览器端调用摄像头录制视频。在Vue中,可以使用vue-webrtc库来实现。这个库提供了一些Vue组件,可以方便地实现WebRTC功能。以下是实现WebRTC录制视频的基本步骤: 1. 安装vue-webrtc库 运行以下命令: ``` npm install vue-webrtc --save ``` 2. 在Vue组件中导入vue-webrtc 在组件中引入vue-webrtc: ```javascript import { Webrtc } from 'vue-webrtc' ``` 3. 在组件中使用Webrtc元素 在组件的template中添加Webrtc元素,用于显示摄像头捕获的视频: ```html <template> <div> <webrtc :autoPlay="true"></webrtc> </div> </template> ``` 4. 实现录制视频功能 使用MediaRecorder API来录制视频: ```javascript let mediaRecorder = null let chunks = [] function startRecording() { const stream = this.$refs.webrtc.getStream() mediaRecorder = new MediaRecorder(stream) mediaRecorder.ondataavailable = function(e) { chunks.push(e.data) } mediaRecorder.onstop = function() { const blob = new Blob(chunks, { type: 'video/mp4' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = 'recording.mp4' a.click() chunks = [] } mediaRecorder.start() } function stopRecording() { mediaRecorder.stop() } ``` 这个例子中,我们使用MediaRecorder API来捕获摄像头视频,并将录制的数据保存到Blob对象中。最后,我们将Blob对象转换为URL,并创建一个链接,使用户可以下载录制的视频。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值