JavaScript 调用摄像头并截图上传完整示例
本文详解如何使用 JavaScript 调用浏览器摄像头并截取画面。通过 getUserMedia 获取媒体流,利用 Canvas 的 drawImage 方法提取视频帧,最后将图像转换为 Base64 格式上传至后端。文中对比了新旧版 API 差异,并提供了基于 Chrome 浏览器的完整代码示例及 PHP 后端处理逻辑。
JavaScript 调用摄像头并截图上传完整示例
本文直接介绍在 JavaScript 中调用摄像头并将截图上传至后端的完整流程。
首先,打开摄像头主要依赖 getUserMedia 方法,获取到的媒体流需要赋值给 video 标签以显示画面。
其次,截取图片主要利用 Canvas 绘图功能,通过 drawImage 方法将 video 标签中的当前帧绘制到 canvas 元素上。
最后,将截取的内容上传至服务器。具体做法是将 canvas 中的图像数据转换为 Base64 格式进行上传,后端(以 PHP 为例)通过 file_put_contents 函数将其还原为图片文件保存。

需要注意的是,在 Chrome 以外的浏览器中使用摄像头功能可能会遇到兼容性问题,这并非新鲜事。因此,以下代码示例主要基于 Chrome 浏览器进行开发和测试。
例如,在最新版的 Firefox 浏览器中可能会遇到特定的报错,具体原因尚不明确。


打开摄像头:getUserMedia API 使用指南
第一步:打开摄像头。
getUserMedia API 存在新旧两个版本,建议优先使用新版本。
旧版本的方法位于 navigator 对象下,具体属性名因浏览器厂商而异。
// 获取媒体方法(旧方法)
navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
if (navigator.getMedia) {
navigator.getMedia({
video: true
}, function(stream) {
mediaStreamTrack = stream.getTracks()[0];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}, function(err) {
console.log(err);
});
}
该方法的第一个参数用于指定所需的媒体类型,可以是视频(video)或音频(audio)。
第二个参数是调用成功后的回调函数,接收一个 MediaStream 对象作为参数。在旧版本中,可以直接调用 MediaStream.stop() 来关闭摄像头;但在新版规范中该方法已被废弃,需改为调用 MediaStream.getTracks()[index].stop() 来停止特定的 Track。
第三个参数用于处理调用失败的情况,接收错误对象作为参数。
新版 API 位于 navigator.mediaDevices 对象下。
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(stream) {
console.log(stream);
mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}).catch(function(err) {
console.log(err);
})
}
新版用法与旧版类似,但 getUserMedia 方法返回一个 Promise 对象,可以通过 then 和 catch 分别处理成功和失败的回调逻辑。
需要特别注意的是,MediaStream.getTracks() 返回的 Tracks 数组是按照第一个参数定义的顺序倒序排列的。
假设当前定义了如下配置:
{
video: true,
audio: true
}
若要关闭摄像头,需要调用 MediaStream.getTracks()[1].stop();
同理,索引 0 对应于 audio 的 track。
使用 createObjectURL 将 MediaStream 赋值给 video 标签的 src 属性,即可存储并实时显示媒体流数据。
在旧版本中,webkitURL 对象已不再被支持,应统一使用标准的 URL 对象。
<video width="200" height="150"></video>
<canvas width="200" height="150"></canvas>
<p>
<button id="snap">截取图像</button>
<button id="close">关闭摄像头</button>
<button id="upload">上传图像</button>
</p>
<img id="uploaded" width="200" height="150" />
截取图像与上传处理流程
第二步:截取图像。
只需在点击事件中执行绘制操作即可将画面写入 Canvas。
// 截取图像
snap.addEventListener('click', function() {
context.drawImage(video, 0, 0, 200, 150);
}, false);
第三步:关闭摄像头。
// 关闭摄像头
close.addEventListener('click', function() {
mediaStreamTrack && mediaStreamTrack.stop();
}, false);
第四步:上传截取的图像。
使用 canvas.toDataURL('image/png') 获取图像的 Base64 编码字符串。
// 上传截取的图像
upload.addEventListener('click', function() {
jQuery.post('/uploadSnap.php', {
snapData: canvas.toDataURL('image/png')
}).done(function(rs) {
rs = JSON.parse(rs);
console.log(rs);
uploaded.src = rs.path;
}).fail(function(err) {
console.log(err);
});
}, false);
后端的 PHP 代码负责接收该数据并将其转换为图像文件保存。
需要注意的是,保存前必须去除 Base64 数据头部信息字段(如 data:image/png;base64,),否则生成的图像文件可能损坏无法打开。
<?php
$snapData = $_POST['snapData'];
$snapData = str_replace('data:image/png;base64,', '', $snapData);
// $snapData = str_replace(' ', '+', $snapData);
$img = base64_decode($snapData);
$uploadDir = 'upload/';
$fileName = date('YmdHis', time()) . uniqid();
if (!(file_put_contents($uploadDir . $fileName, $img))) {
echo json_encode(array('code' => 500, 'msg' => '文件上传失败'));
} else {
echo json_encode(array('code' => 200, 'msg' => '文件上传成功', 'path' => $uploadDir . $fileName));
}
?>
以下是完整的 JavaScript 代码示例。
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
function $(elem) {
return document.querySelector(elem);
}
// 获取媒体方法(旧方法)
navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
var canvas = $('canvas'),
context = canvas.getContext('2d'),
video = $('video'),
snap = $('#snap'),
close = $('#close'),
upload = $('#upload'),
uploaded = $('#uploaded'),
mediaStreamTrack;
// 获取媒体方法(新方法)
// 使用新方法打开摄像头
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(stream) {
console.log(stream);
mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}).catch(function(err) {
console.log(err);
})
}
// 使用旧方法打开摄像头
else if (navigator.getMedia) {
navigator.getMedia({
video: true
}, function(stream) {
mediaStreamTrack = stream.getTracks()[0];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}, function(err) {
console.log(err);
});
}
// 截取图像
snap.addEventListener('click', function() {
context.drawImage(video, 0, 0, 200, 150);
}, false);
// 关闭摄像头
close.addEventListener('click', function() {
mediaStreamTrack && mediaStreamTrack.stop();
}, false);
// 上传截取的图像
upload.addEventListener('click', function() {
jQuery.post('/uploadSnap.php', {
snapData: canvas.toDataURL('image/png')
}).done(function(rs) {
rs = JSON.parse(rs);
console.log(rs);
uploaded.src = rs.path;
}).fail(function(err) {
console.log(err);
});
}, false);
</script>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
AOS.js 动画不触发怎么办?排查 DOM 加载与移动端兼容问题
2026-11-05 17:02:26
sigma.js 怎么实现节点点击、拖拽与悬停提示交互
2026-11-05 15:03:27
Matter.js 与 PixiJS/Three.js 集成:分离物理计算与渲染
2026-11-05 13:43:48
主流JS弹幕库选型指南:Danmaku.js等库的功能与体积对比
2026-11-05 09:28:19
JavaScript点击事件监听与交互效果实例
2026-11-05 09:10:19
