之前写了 浏览器调用麦克风录制音频调用摄像头拍摄照片 ,这里就继续来调用摄像头拍摄视频。

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

下面简单实现显示摄像头画面、拍摄视频、播放视频、导出视频,访问 浏览器录制视频demo 可以查看最终效果。

代码实现

HTML 放几个 buttonvideo

<!--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 因为注释比较多,看上去会有点长,但比较容易理解:

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 请求媒体输入许可,需要传入一个参数来设置媒体类型,我用的参数如下:

const constraints = {
  audio: true,
  video: {
    width: 720,
    height: 360
  }
};

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

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

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

录制视频

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

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

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

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

播放视频

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

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

导出视频

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

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

之前写录制音频的时候使用的也是 MediaRecorder 媒体录制接口,要查看这里没有使用到的 MediaRecorder 方法和事件说明可以访问 JavaScript 浏览器调用麦克风录音

类似文章: