Web调用电脑摄像头【实时画面、拍照、截图】

一、播放本地视频+截图

在这里插入图片描述

案例一代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>demo01</title>
</head>

<body>
     <video id="myVideo" src="madashuai.mp4" loop="loop" autoplay="autoplay" controls="controls"></video><br>
     <button id="snapScreen">截屏</button>
     <canvas id="mycanvas" width="400" height="240"></canvas>
</body>

 <script>
   let mycanvas = document.getElementById('mycanvas').getContext('2d');
   let video = document.getElementById('myVideo');

   let snapScreen = document.getElementById('snapScreen');
   snapScreen.onclick = function () { // 按钮点击事件,将
     mycanvas.drawImage(video, 0, 0, 400, 240);
   }
 </script>

</html>

二、电脑摄像头的调用

实时显示画面
在这里插入图片描述

案例二代码:

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

<head>
    <meta charset="UTF-8">
    <title>摄像头调用2</title>
</head>

<body>
    <video id="v"></video>
</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 promise = navigator.mediaDevices.getUserMedia(constraints);
        promise.then(stream => {
            let v = document.getElementById('v');
            // 旧的浏览器可能没有srcObject
            if ("srcObject" in v) {
                v.srcObject = stream;
            } else {
                // 防止再新的浏览器里使用它,应为它已经不再支持了
                v.src = window.URL.createObjectURL(stream);
            }
            v.onloadedmetadata = function (e) {
                v.play();
            };
        }).catch(err => {
            console.error(err.name + ": " + err.message);
        })
    })();
</script>
</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>

码农云库交流群:1139680855

以下是一个使用ExtJS 6调用电脑摄像头实现拍照录像且保存照片,保存录像的例子。需要注意的是,实现这个例子需要一定的前端开发和后端上传等技术,因此涉及的功能较多,需要具备一定的相关技能方能实现。 前端代码: ``` Ext.define('MyApp.view.main.Main', { extend: 'Ext.panel.Panel', xtype: 'app-main', layout: 'border', items: [{ region: 'west', xtype: 'panel', title: 'Photos', width: 200, split: true, layout: 'fit', items: [{ xtype: 'dataview', store: 'Photos', tpl: '<tpl for="."><div style="margin: 10px;text-align:center;"><img src="{url}" width="150" height="150"><br>{name}</div></tpl>', itemSelector: 'div.thumb-wrap', listeners: { itemclick: function(view, record) { var img = Ext.getCmp('photo'); img.setSrc(record.get('url')); } } }] },{ region: 'center', xtype: 'panel', title: 'Camera', layout: 'fit', items: [{ xtype: 'image', id: 'photo', src: '/resources/images/nophoto.png', style: 'border: 5px solid silver', alt: 'Photo' }], tools: [{ type: 'camera', handler: 'onCameraClick' },{ type: 'videocam', handler: 'onVideoClick' }] }] }); ``` 在这个页面中,我们定义了一个`dataview`用于展示已保存的照片,以及一个展示当前选中照片的`image`,另外还添加了两个工具按钮用于拍照和录像。 我们在控制器中实现这两个工具按钮的功能。在这个例子中,我们通过发送Ajax请求调用后端API实现拍照和录像,并将结果保存到服务器上。 控制器代码: ``` Ext.define('MyApp.view.main.MainController', { extend: 'Ext.app.ViewController', alias: 'controller.main', onCameraClick: function() { Ext.Ajax.request({ url: '/take_photo', params: { format: 'jpeg', width: 800, height: 600 }, success: function(response) { var data = Ext.decode(response.responseText); if (data.success) { Ext.getStore('Photos').add({ name: data.filename, url: data.url }); var img = Ext.getCmp('photo'); img.setSrc(data.url); } else { Ext.Msg.alert('Error', data.message); } }, failure: function(response) { Ext.Msg.alert('Error', response.statusText); } }); }, onVideoClick: function() { this.startRecording(); }, startRecording: function() { var _this = this; navigator.mediaDevices.getUserMedia({video: true, audio: true}) .then(function(stream) { var video = _this.getView().down('video'); if (Ext.isChrome) { video.srcObject = stream; } else { video.dom.src = URL.createObjectURL(stream); } _this.mediaRecorder = new MediaRecorder(stream); _this.mediaRecorder.start(); _this.mediaRecorder.ondataavailable = function(e) { var url = URL.createObjectURL(e.data); var filename = 'recording_' + (new Date()).getTime() + '.webm'; _this.saveRecording(url, filename); }; }) .catch(function(err) { console.log('Error: ', err.message); }); }, saveRecording: function(url, filename) { var _this = this; var file = new File([url], filename, { type: 'video/webm' }); var reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = function() { var base64data = reader.result; Ext.Ajax.request({ url: '/save_recording', params: { data: base64data, filename: filename }, success: function(response) { var data = Ext.decode(response.responseText); if (data.success) { var img = Ext.getCmp('photo'); img.setSrc(data.url); } else { Ext.Msg.alert('Error', data.message); } }, failure: function(response) { Ext.Msg.alert('Error', response.statusText); } }); }; } }); ``` 在这个控制器中,我们定义了两个点击事件,分别用于拍照和录像。在拍照事件中,我们调用后端API`/take_photo`来获取照片,并将结果保存到服务器上。如果API调用成功,则将照片添加到数据视图中并显示在照片预览区域中。 在录像事件中,我们通过`getUserMedia`方法请求用户允许访问电脑摄像头和麦克风,并开始录像。我们使用`MediaRecorder`对象来录制视频并将其保存到浏览器中。在录制完成后,我们调用后端API`/save_recording`来保存录像,并将结果显示在照片预览区域中。 后端代码: 在后端代码中,我们需要实现两个API:`/take_photo`用于拍摄照片,`/save_recording`用于保存录像。这些API的实现因服务器不同具体实现方式也不同。以下代码仅仅给出了示例代码: ``` import java.io.File; import java.io.FileOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; @RequestMapping("/") @ResponseBody public class MainController { @RequestMapping(value = "/take_photo", method = RequestMethod.GET) public Object takePhoto(HttpServletRequest request, HttpServletResponse response) { String format = request.getParameter("format"); int width = Integer.parseInt(request.getParameter("width")); int height = Integer.parseInt(request.getParameter("height")); try { String filename = "photo_" + (new Date()).getTime() + "." + format; BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())); BufferedImage scaled = Scalr.resize(image, width, height); File file = new File("/path/to/photo", filename); ImageIO.write(scaled, format, file); Map<String, Object> data = new HashMap<>(); data.put("success", true); data.put("filename", filename); data.put("url", "/path/to/photo/" + filename); return data; } catch (Exception e) { Map<String, Object> data = new HashMap<>(); data.put("success", false); data.put("message", e.getMessage()); return data; } } @RequestMapping(value = "/save_recording", method = RequestMethod.POST) public Object saveRecording(HttpServletRequest request, HttpServletResponse response, MultipartFile file) { String data = request.getParameter("data"); String filename = request.getParameter("filename"); try { File outputFile = new File("/path/to/recording", filename); FileOutputStream output = new FileOutputStream(outputFile); byte[] bytes = Base64.getDecoder().decode(data.replaceAll(".*?base64,", "")); output.write(bytes); output.flush(); output.close(); Map<String, Object> data = new HashMap<>(); data.put("success", true); data.put("url", "/path/to/recording/" + filename); return data; } catch (Exception e) { Map<String, Object> data = new HashMap<>(); data.put("success", false); data.put("message", e.getMessage()); return data; } } } ``` 在这里,我们假设拍照API通过`Robot`类截屏并将结果保存为`BufferedImage`类型的图片,然后使用`Scalr`类将图片缩放到指定大小,最后将图片保存到服务器的`/path/to/photo`目录中。保存录像API将基于Base64编码的视频数据解码并写入到文件中,同时将文件保存到服务器的`/path/to/recording`目录中。 需要注意的是,这些示例代码并没有导入所需的依赖库,也没有进行安全验证等重要细节处理,使用时需要根据具体情况进行相应的扩展和修改。 通过该程序,您可以使用Ext JS 6调用电脑摄像头实现拍照录像且保存照片,保存录像。借助于前端和后端技术,您可以实现更为丰富的功能和交互体验,例如添加照片编辑、分享等功能,扩展应用场景和提升用户体验。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

战胜.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值