WebRTC网页打开摄像头并录制视频

前面我们能打开本地摄像头,并且在网页上看到摄像头的预览图像。
本文我们使用MediaRecorder来录制视频。在网页上播放录制好的视频,并能提供下载功能。
html 首先创建一个html界面,放上一些元素

录制使用的视频格式:视频设置回声消除:

  • video
    • v1 用来预览
    • v2 用来播放录制好的视频
  • button 控制摄像头开启、录制,下载等等
  • select 选择录制用的视频格式
  • input 选择回声消除
js 准备
先把界面上的元素拿到
'use strict'; let mediaRecorder; let recordedBlobs; // 录制下来的内容 let isRecording = false; // 先把页面元素拿到 const startCameraBtn = document.querySelector('button#startCamera'); // 启动摄像头按钮 const stopCameraBtn = document.querySelector('button#stopCamera'); const recordBtn = document.querySelector('button#record'); // 开始录制按钮 const playBtn = document.querySelector('button#play'); // 播放按钮 const downloadBtn = document.querySelector('button#download'); // 下载视频按钮 const codecSelector = document.querySelector('#codecSelect'); // 选择格式 const msgEle = document.querySelector('span#msg'); // 显示消息 const previewV1 = document.querySelector('video#v1'); // 预览用的 const recordedV2 = document.querySelector('video#v2'); // 用来播放录制好的视频

视频支持的格式
先预定几个可能的格式,然后一个个来判断是否支持。找到支持的格式。
function getSupportedMimeTypes() { const possibleTypes = [ 'video/webm; codecs=vp9,opus', 'video/webm; codecs=vp8,opus', 'video/webm; codecs=h264,opus', 'video/mp4; codecs=h264,aac', ]; return possibleTypes.filter(mimeType => { return MediaRecorder.isTypeSupported(mimeType); }); }

开启摄像头
同样要使用getUserMedia方法。这里给视频指定了宽高。回声消除是可选项。
// 启动摄像头 startCameraBtn.addEventListener('click', async () => { startCameraBtn.disabled = true; const isEchoCancellation = document.querySelector('#echoCancellation').checked; const constraints = { audio: { echoCancellation: { exact: isEchoCancellation } }, video: { width: 1280, height: 720 } }; await init(constraints); }); async function init(constraints) { try { const stream = await navigator.mediaDevices.getUserMedia(constraints); gotStream(stream); } catch (e) { showMsg(`navigator.getUserMedia error:${e.toString()}`); } }function gotStream(stream) { recordBtn.disabled = false; showMsg('拿到了 stream:', stream); window.stream = stream; previewV1.srcObject = stream; // 重置 var codecOption = codecSelector.lastChild; while (codecOption != null) { codecSelector.removeChild(codecOption); codecOption = codecSelector.lastChild; }getSupportedMimeTypes().forEach(mimeType => { const option = document.createElement('option'); option.value = https://www.it610.com/article/mimeType; option.innerText = option.value; codecSelector.appendChild(option); }); codecSelector.disabled = false; // 可以进行选择了 }

下面是停止摄像头的方法
stopCameraBtn.addEventListener('click', () => { var stream = previewV1.srcObject; if (stream == null) { return; } const tracks = stream.getTracks(); tracks.forEach(function (track) { track.stop(); }); previewV1.srcObject = null; window.stream = null; codecSelector.disabled = true; startCameraBtn.disabled = false; });

开始录制
开始录制视频
function startRecording() { recordedBlobs = []; const mimeType = codecSelector.options[codecSelector.selectedIndex].value; const options = { mimeType }; try { mediaRecorder = new MediaRecorder(window.stream, options); } catch (e) { showMsg(`创建MediaRecorder出错: ${JSON.stringify(e)}`); return; }showMsg('创建MediaRecorder', mediaRecorder, ' -> options', options); recordBtn.textContent = '停止录制'; isRecording = true; playBtn.disabled = true; downloadBtn.disabled = true; codecSelector.disabled = true; mediaRecorder.onstop = (event) => { showMsg('录制停止了: ' + event); showMsg('录制的数据Blobs: ' + recordedBlobs); }; mediaRecorder.ondataavailable = handleDataAvailable; mediaRecorder.start(); showMsg('录制开始 mediaRecorder: ' + mediaRecorder); }function handleDataAvailable(event) { if (event.data && event.data.size > 0) { recordedBlobs.push(event.data); } }recordBtn.addEventListener('click', () => { if (isRecording == false) { startRecording(); } else { stopRecording(); recordBtn.textContent = '开始录制'; playBtn.disabled = false; downloadBtn.disabled = false; codecSelector.disabled = false; } });

  • 重置录制内容recordedBlobs = []
  • 拿到选定的视频格式mimeType
  • 新建MediaRecorder对象,传入前面获取到的流
  • 处理各个按钮(ui)的状态
  • mediaRecorder
    • 设置停止监听器 onstop
    • 监听录制数据 ondataavailable,有数据来的时候存放在recordedBlobs
    • 启动录制 mediaRecorder.start()
停止录制
function stopRecording() { mediaRecorder.stop(); }

播放录制好的视频
录制好的视频内容存放在recordedBlobs。新建Blob,交给video(recordedV2)来播放
playBtn.addEventListener('click', () => { const mimeType = codecSelector.options[codecSelector.selectedIndex].value.split('; ', 1)[0]; const superBuffer = new Blob(recordedBlobs, { type: mimeType }); recordedV2.src = https://www.it610.com/article/null; recordedV2.srcObject = null; recordedV2.src = window.URL.createObjectURL(superBuffer); recordedV2.controls = true; recordedV2.play(); });

下载视频
录制好的视频内容存放在recordedBlobs
downloadBtn.addEventListener('click', () => { const blob = new Blob(recordedBlobs, { type: 'video/webm' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = https://www.it610.com/article/url; a.download ='视频_' + new Date().getTime() + '.webm'; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 100); });

新建Blob和一个a元素。根据blob创建ObjectURL,并传给a元素的href。
修改下载文件的默认名字a.download
触发a元素的click(),即能让浏览器下载这个文件。
延迟把这个a移除掉。
小结 getUserMedia()开启视频拿到视频流。MediaRecorder录制视频。用Blob来播放和下载。
实现一个小的录制视频效果。视频数据缓存在对象里。
完整的效果请参考 视频录制
【WebRTC网页打开摄像头并录制视频】原文链接

    推荐阅读