javascript|html调用摄像头实现拍照或录制视频


html调用摄像头实现拍照或录制视频

从网上搜刮了两个可以实现的demo,记录一下。

  1. 示例1
Document - 锐客网 > /* 镜像显示哈哈 */ #gumVideo { transform: rotateY(180deg); } > var beginButton = document.querySelector('button#begin'); var recordButton = document.querySelector('button#record'); var playButton = document.querySelector('button#play'); var downloadButton = document.querySelector('button#download'); var reStartButton = document.querySelector('button#reStart'); var uploadBtn = document.querySelector('button#upload'); var gumVideo = document.querySelector('#gumVideo'); var gumVideo2 = document.querySelector('#gumVideo2'); var mediaRecorder; var recordedBlobs; var sourceBuffer; console.log(gumVideo) //打开摄像头 function getUserMediaStream(constraints, cb) { navigator.mediaDevices.getUserMedia(constraints) .then(handleSuccess) .catch(err => { cb(err, null); }); } //页面播放视频流 function handleSuccess(stream) { console.log(stream) recordButton.disabled = false; console.log('getUserMedia() got stream: ', stream); window.stream = stream; if (window.URL) { // gumVideo.src = https://www.it610.com/article/window.URL.createObjectURL(stream); gumVideo.srcObject = stream; // return new Promise((resolve) => { //gumVideo.onloadedmetadata = https://www.it610.com/article/() => { //resolve(gumVideo); //}; // }); // gumVideo.play() console.log(gumVideo.srcObject) } else { gumVideo.src = https://www.it610.com/article/stream; console.log(gumVideo) }var c = document.getElementById("myCanvas"); c.width = 400; c.height = 300; var i; gumVideo.addEventListener('play', function () { var p = document.createElement('p'); p.innerText = 'hello'; // i = window.setInterval(function () { //if (littleVideo) { //drawLittleVideo(c); //} else { //drawBigVideo(c); //} // }, 20); }, false); gumVideo.addEventListener('pause', function () { if (i) { window.clearInterval(i); } }, false); gumVideo.addEventListener('ended', function () { if (i) { clearInterval(i); } }, false); }function startRecording() { recordedBlobs = []; var options = { mimeType: 'video/webm; codecs=vp9' }; if (!MediaRecorder.isTypeSupported(options.mimeType)) { console.log(options.mimeType + ' is not Supported'); options = { mimeType: 'video/webm; codecs=vp8' }; if (!MediaRecorder.isTypeSupported(options.mimeType)) { console.log(options.mimeType + ' is not Supported'); options = { mimeType: 'video/webm' }; if (!MediaRecorder.isTypeSupported(options.mimeType)) { console.log(options.mimeType + ' is not Supported'); options = { mimeType: '' }; } } } try { mediaRecorder = new MediaRecorder(window.stream, options); } catch (e) { console.error('Exception while creating MediaRecorder: ' + e); alert('Exception while creating MediaRecorder: ' + e + '. mimeType: ' + options.mimeType); return; } console.log('Created MediaRecorder', mediaRecorder, 'with options', options); recordButton.textContent = '停止'; playButton.disabled = true; downloadButton.disabled = true; reStartButton.disabled = true; mediaRecorder.onstop = handleStop; mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start(10); // collect 10ms of data console.log('MediaRecorder started', mediaRecorder); } function handleStop(event) { console.log('Recorder stopped: ', event); } function handleDataAvailable(event) { if (event.data && event.data.size > 0) { recordedBlobs.push(event.data); } } function toggleRecording() { if (recordButton.textContent === '录制' || recordButton.textContent === '重录') { // littleVideo = false; startRecording(); setTimeout(() => { stopRecording(); recordButton.textContent = '重录'; playButton.disabled = false; downloadButton.disabled = false; reStartButton.disabled = false; }, 5000); } else { stopRecording(); recordButton.textContent = '重录'; playButton.disabled = false; downloadButton.disabled = false; reStartButton.disabled = false; } } function stopRecording() { //影藏录制中提 mediaRecorder.stop(); bufferToDataUrl() console.log('Recorded Blobs: ', recordedBlobs); //recordedVideo.controls = true; } function play() { var superBuffer = new Blob(recordedBlobs, { type: 'video/mp4' }); //recordedVideo.src = https://www.it610.com/article/window.URL.createObjectURL(superBuffer); gumVideo2.src = window.URL.createObjectURL(superBuffer); gumVideo2.play() } function upload() { //保存在本地,通过post请求 var blob = new Blob(recordedBlobs, { type:'video/mp4' }); // var data = https://www.it610.com/article/new FormData(); // data.append('video', blob); // data.append('qw', 123); // data.append('question', 1); // $.ajax({ //type: "POST", //url: "/form/data", //data: data, //processData: false,//告诉jquery不要处理发送的数据 //contentType: false,// 告诉jquery不要设置content-Type请求头 //success: function (msg) { //console.log(msg); //} // }); } //buffer转dataUrl function bufferToDataUrl() { let blob = new Blob(recordedBlobs, { type: "video/webm" }); let reader = new FileReader(); reader.onload = function () { var a = document.createElement('a'); a.style.display = 'none'; a.href = https://www.it610.com/article/reader.result; //文件名 通过方法传进来 检测是否合法? a.download ='record.mp4'; document.body.appendChild(a); a.click(); setTimeout(function () { document.body.removeChild(a); window.URL.revokeObjectURL(reader.result); }, 100); }; reader.readAsDataURL(blob); } function restartRecord() { //清楚存留 按钮功能重置 recordButton.textContent = '录制'; playButton.disabled = true; downloadButton.disabled = true; reStartButton.disabled = true; //handleSuccess(); navigator.mediaDevices.getUserMedia({ audio: true, video: { facingMode: 'user' } }). then(handleSuccess).catch(handleError); } //转文件 function dataUrlToFile(dataUrl) { let binary = atob(dataUrl.split(",")[1]); let data = https://www.it610.com/article/[]; for (var i = 0; i < binary.length; i++) data.push(binary.charCodeAt(i)); return new File([new Uint8Array(data)],"recorded-video.webm", { type: "video/webm" }); } //获取屏幕流 function getDisplayMediaStream(cb) { navigator.mediaDevices.getDisplayMedia() .then(stream => { cb(null, stream); }) .catch(err => { cb(err, null); }) }

  1. 示例2
摄像头拍照 - 锐客网
> //访问用户媒体设备的兼容方法 function getUserMedia(constraints, success, error) { if (navigator.mediaDevices.getUserMedia) { //最新的标准API navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error); } else if (navigator.webkitGetUserMedia) { //webkit核心浏览器 navigator.webkitGetUserMedia(constraints,success, error) } else if (navigator.mozGetUserMedia) { //firfox浏览器 navigator.mozGetUserMedia(constraints, success, error); } else if (navigator.getUserMedia) { //旧版API navigator.getUserMedia(constraints, success, error); } }let video = document.getElementById('video'); let canvas = document.getElementById('canvas'); let context = canvas.getContext('2d'); function success(stream) { //兼容webkit核心浏览器 let CompatibleURL = window.URL || window.webkitURL; //将视频流设置为video元素的源 console.log(stream); //video.src = https://www.it610.com/article/CompatibleURL.createObjectURL(stream); video.srcObject = stream; video.play(); }function error(error) { console.log(`访问用户媒体设备失败${error.name}, ${error.message}`); }if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) { //调用用户媒体设备, 访问摄像头 getUserMedia({video : {width: 480, height: 320}}, success, error); } else { alert('不支持访问用户媒体'); }document.getElementById('capture').addEventListener('click', function () { context.drawImage(video, 0, 0, 480, 320); })

  1. 示例3 配合fileSaver.js
video recoder - 锐客网 src="https://www.it610.com/article/fileSaver.js"> > body{ background-color:#EFEDEF; }
class="experiment" style="width:320px; height:240px; border:1px solid green; margin:50px auto; ">
class="experiment" style="text-align:center; border:none; margin-top:20px; ">
> var mediaStream; var recorderFile; var stopRecordCallback; var openBtn = document.getElementById("openCamera"); var startBtn = document.getElementById("start-recording"); var saveBtn = document.getElementById("save-recording"); openBtn.onclick = function() { this.disabled = true; startBtn.disabled=false; openCamera(); }; startBtn.onclick = function() { this.disabled = true; startRecord(); }; saveBtn.onclick = function() { saver(); // alert('Drop WebM file on Chrome or Firefox. Both can play entire file. VLC player or other players may not work.'); }; var mediaRecorder; var videosContainer = document.getElementById('videos-container'); function openCamera(){ var len = videosContainer.childNodes.length; for(var i=0; i 0) { for (let j = 0; j < tracks.length; j++) { let track = tracks[j]; if (typeof track.stop === 'function') { track.stop(); } } } } } } }; function startRecord() { console.log("开始: "+new Date()); mediaRecorder.start(); setTimeout(function(){ // 结束 stopRecord(function() { //alert("录制成功!"); openBtn.disabled=false; saveBtn.disabled=false; console.log("录制结束: "+new Date()); saver(); //send(); }); }, 10000); alert(111); }function saver(){ var file = new File([recorderFile], 'msr-' + (new Date).toISOString().replace(/:|\./g, '-') + '.mp4', { type: 'video/mp4' }); console.log("保存开始: "+new Date()); saveAs(file); console.log("保存结束: "+new Date()); }function send(){ var file = new File([recorderFile], 'msr-' + (new Date).toISOString().replace(/:|\./g, '-') + '.mp4', { type: 'video/mp4' }); var data = https://www.it610.com/article/new FormData(); data.append("username", "test"); data.append("userfile", file); var req = new XMLHttpRequest(); req.open("POST", "com.spinsoft.bip.frame.utils.image.saveMp4.biz.ext"); req.send(data); }

【javascript|html调用摄像头实现拍照或录制视频】fileSaver.js
/* FileSaver.js * A saveAs() FileSaver implementation. * 1.3.2 * 2016-06-16 18:25:19 * * By Eli Grey, http://eligrey.com * License: MIT *See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md *//*global self */ /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true *//*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */var saveAs = saveAs || (function(view) { "use strict"; // IE <10 is explicitly unsupported if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { return; } var doc = view.document // only get URL when necessary in case Blob.js hasn't overridden it yet , get_URL = function() { return view.URL || view.webkitURL || view; } , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") , can_use_save_link = "download" in save_link , click = function(node) { var event = new MouseEvent("click"); node.dispatchEvent(event); } , is_safari = /constructor/i.test(view.HTMLElement) || view.safari , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) , throw_outside = function(ex) { (view.setImmediate || view.setTimeout)(function() { throw ex; }, 0); } , force_saveable_type = "application/octet-stream" // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to , arbitrary_revoke_timeout = 1000 * 40 // in ms , revoke = function(file) { var revoker = function() { if (typeof file === "string") { // file is an object URL get_URL().revokeObjectURL(file); } else { // file is a File file.remove(); } }; setTimeout(revoker, arbitrary_revoke_timeout); } , dispatch = function(filesaver, event_types, event) { event_types = [].concat(event_types); var i = event_types.length; while (i--) { var listener = filesaver["on" + event_types[i]]; if (typeof listener === "function") { try { listener.call(filesaver, event || filesaver); } catch (ex) { throw_outside(ex); } } } } , auto_bom = function(blob) { // prepend BOM for UTF-8 XML and text/* types (including HTML) // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*; .*charset\s*=\s*utf-8/i.test(blob.type)) { return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); } return blob; } , FileSaver = function(blob, name, no_auto_bom) { if (!no_auto_bom) { blob = auto_bom(blob); } // First try a.download, then web filesystem, then object URLs var filesaver = this , type = blob.type , force = type === force_saveable_type , object_url , dispatch_all = function() { dispatch(filesaver, "writestart progress write writeend".split(" ")); } // on any filesys errors revert to saving with object URLs , fs_error = function() { if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { // Safari doesn't allow downloading of blob urls var reader = new FileReader(); reader.onloadend = function() { var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^; ]*; /, 'data:attachment/file; '); var popup = view.open(url, '_blank'); if(!popup) view.location.href = https://www.it610.com/article/url; url=undefined; // release reference before dispatching filesaver.readyState = filesaver.DONE; dispatch_all(); }; reader.readAsDataURL(blob); filesaver.readyState = filesaver.INIT; return; } // don't create more object URLs than needed if (!object_url) { object_url = get_URL().createObjectURL(blob); } if (force) { view.location.href = https://www.it610.com/article/object_url; } else { var opened = view.open(object_url,"_blank"); if (!opened) { // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html view.location.href = https://www.it610.com/article/object_url; } } filesaver.readyState = filesaver.DONE; dispatch_all(); revoke(object_url); } ; filesaver.readyState = filesaver.INIT; if (can_use_save_link) { object_url = get_URL().createObjectURL(blob); setTimeout(function() { save_link.href = object_url; save_link.download = name; click(save_link); dispatch_all(); revoke(object_url); filesaver.readyState = filesaver.DONE; }); return; }fs_error(); } , FS_proto = FileSaver.prototype , saveAs = function(blob, name, no_auto_bom) { return new FileSaver(blob, name || blob.name ||"download", no_auto_bom); } ; // IE 10+ (native saveAs) if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { return function(blob, name, no_auto_bom) { name = name || blob.name || "download"; if (!no_auto_bom) { blob = auto_bom(blob); } return navigator.msSaveOrOpenBlob(blob, name); }; }FS_proto.abort = function(){}; FS_proto.readyState = FS_proto.INIT = 0; FS_proto.WRITING = 1; FS_proto.DONE = 2; FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; return saveAs; }( typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content )); // `self` is undefined in Firefox for Android content script context // while `this` is nsIContentFrameMessageManager // with an attribute `content` that corresponds to the windowif (typeof module !== "undefined" && module.exports) { module.exports.saveAs = saveAs; } else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) { define("FileSaver.js", function() { return saveAs; }); }

    推荐阅读