JavaScript 浏览器调用摄像头拍摄视频

拍摄视频和录制音频的方法其实是差不多的,使用的也是 MediaRecorder 媒体录制接口,录制音频只需要申请麦克风,录制视频需要同时申请麦克风和摄像头。

目录

代码实现

HTML 放几个 button 和 video:

1
2
3
4
5
6
7
<!--Mr. Ma's Blog www.misterma.com-->
<button type="button" id="start-camera-btn">打开摄像头</button>
<button type="button" id="start-btn">开始录像</button>
<button type="button" id="stop-btn">停止录像</button>
<button type="button" id="play-btn">播放视频</button>
<button type="button" id="export-btn">导出视频</button>
<video width="720" height="360" controls></video>

video 主要用来预览摄像头画面和播放拍摄的视频。

下面的 JavaScript 因为注释比较多,看上去会有点长,但比较容易理解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
const startCameraBtn = document.querySelector('#start-camera-btn');  // 打开摄像头按钮
const startBtn = document.querySelector('#start-btn'); // 开始录像按钮
const stopBtn = document.querySelector('#stop-btn'); // 停止录像按钮
const playBtn = document.querySelector('#play-btn'); // 播放视频按钮
const exportBtn = document.querySelector('#export-btn'); // 导出视频按钮
const videoEl = document.querySelector('video'); // 视频播放元素
let videoData = []; // 存放视频数据
let cameraStream = null; // 存放媒体流
let mediaRecorder = null; // 存放媒体录制对象

// 打开摄像头按钮点击
startCameraBtn.addEventListener('click', () => {
// 申请视频和音频的参数
const constraints = {
audio: true,
video: {
width: 720,
height: 360
}
};
// 申请摄像头和麦克风权限
navigator.mediaDevices.getUserMedia(constraints).then(stream => {
cameraStream = stream;
// 禁用 video 的控制组件
videoEl.controls = false;
// 把媒体流传给 video 的 srcObject
videoEl.srcObject = cameraStream;
// 播放画面和声音
videoEl.play();
}).catch(info => {
alert('错误' + info);
});
});

// 开始录像按钮点击
startBtn.addEventListener('click', () => {
// 创建媒体录制
mediaRecorder = new MediaRecorder(cameraStream, {mimeType: 'video/webm'});
// 开始录制
mediaRecorder.start();

// 处理视频数据
mediaRecorder.addEventListener('dataavailable', ev => {
videoData.push(ev.data);
});

// 录制停止事件
mediaRecorder.addEventListener('stop', () => {
videoData = new Blob(videoData);
});
});

// 停止录像按钮点击
stopBtn.addEventListener('click', () => {
mediaRecorder.stop();
});

// 播放视频点击
playBtn.addEventListener('click', () => {
if (videoData === null) return false;
// 清除 video 的媒体流
videoEl.srcObject = null;
// 把视频数据转为 URL 传给 video 的 src
videoEl.src = URL.createObjectURL(videoData);
// 播放视频
videoEl.play();
// 启用 video 的控制组件
videoEl.controls = true;
// 删除媒体流
cameraStream = null;
});

// 导出视频按钮点击
exportBtn.addEventListener('click', () => {
if (videoData === null) return false;
const link = document.createElement('a');
link.href = URL.createObjectURL(videoData);
link.download = 'video.webm';
link.click();
});

上面的代码只是简单演示,没有做重复点击之类的判断。

详细说明

还是分几步写:

  1. 显示摄像头画面
  2. 录制视频
  3. 播放视频
  4. 导出视频

显示摄像头画面

使用 navigator.mediaDevices.getUserMedia 请求媒体输入许可,需要传入一个参数来设置媒体类型,我用的参数如下:

1
2
3
4
5
6
7
const constraints = {
audio: true,
video: {
width: 720,
height: 360
}
};

上面的参数是同时申请视频和音频输入设备,视频使用的尺寸是 720*360。

用户授权完成后会返回一个 Promise,成功 then 会返回一个媒体流,失败 catch 会返回错误信息。

把返回的媒体流传给 video 的 srcObject ,video 就可以显示摄像头画面了,同时也能播放麦克风声音。

录制视频

有了媒体流就可以创建 MediaRecorder 媒体录制接口,第一个参数 MediaStream 是媒体流,可以使用申请设备权限返回的媒体流,第二个参数是录制选项,我的录制选项是 {mimeType: 'video/webm'} ,使用 webm 格式来录制视频。webm 是 Google 的视频格式,Chromium 系的浏览器一般都支持,Firefox 和 Safari 不一定支持,可能需要把 mimeType 设置为 video/mp4 。

使用 MediaRecorder 的 start 方法开始录制,start 方法也可以传入一个 timeslice 参数,timeslice 参数可以设置一个毫秒值来把视频数据分割成多个数据块。

MediaRecorder 的 dataavailable 事件会在停止录制时触发,如果在 start 中设置了 timeslice 的话,每个 timeslice 周期结束也会触发。dataavailable 事件会返回一个 event ,使用 event.data 可以获取视频数据。

MediaRecorder 的 stop 方法可以停止录制,停止录制也会触发 MediaRecorder 的 stop 事件,停止录制后我使用 Blob 把视频数据转为了 Blob 数据。

播放视频

我用来播放视频的 video 元素和显示摄像头画面的是同一个,把 video 的 srcObject 设置为 null 可以停止播放摄像头画面。使用 URL.createObjectURL 把 Blob 视频数据转换为 DataURL 传给 video 的 src ,调用 video 的 play 方法就可以自动播放视频了。

我使用了 video 的 controls 控制组件来控制视频播放,给 video 加入 controls 属性,video 就会包含基本的播放控制功能,不需要手动编写播放控制。在 video 显示摄像头画面的时候我会禁用 controls 组件,在 video 需要播放视频的时候启用 controls 组件。

导出视频

  1. 使用 document.createElement 创建一个链接(不需要插入到页面)
  2. 使用 URL.createObjectURL 把 Blob 视频数据转为 DataURL 传给链接的 href
  3. 通过链接的 download 属性来设置文件名
  4. 调用链接的 click 来触发链接的点击事件

如果需要把视频上传到服务器,可以把视频 Blob 数据添加到 FormData 上传。

🔰本文标题: JavaScript 浏览器调用摄像头拍摄视频

🔞本文链接: https://193.gs/jslqljqipduipb/index.html

🌡️本文总热度℃