Web 实现客户端录音或录像的流程大致分为:
采集音频/视频
浏览器兼容
注意事项
开始采集
利用 navigator.mediaDevices 对象的 getUserMedia 方法采集音频和视频媒体流。
// 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象if (navigator.mediaDevices === undefined) { navigator.mediaDevices = {};}
// 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia// 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = function(constraints) {
// 首先,如果有getUserMedia的话,就获得它 var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口 if (!getUserMedia) { return Promise.reject(new Error('getUserMedia is not implemented in this browser')); }
// 否则,为老的navigator.getUserMedia方法包裹一个Promise return new Promise(function(resolve, reject) { getUserMedia.call(navigator, constraints, resolve, reject); }); }}
// 开始采集输入媒体navigator.mediaDevices.getUserMedia({ // 采集音频 audio: true, // 采集视频 video: true}).then(function(stream) { // TODO}).catch(function(err) { console.log(err.name + ": " + err.message);});
复制代码
录制
创建录制实例
利用 new 指令 创建一个 MediaRecorder 对象。
// 定义录制的编码格式const options = { mimeType: "video/webm;codecs=opus"};// 录制实例const mediaRecorder = new MediaRecorder(audioStream, options);
复制代码
监听录制回调事件
// 创建一个集合存储录制的数据const recordedBlobs = [];
// 监听录制错误mediaRecorder.onerror = async (event) => { // TODO}
// 监听录制开始mediaRecorder.onstart = async (event) => { // TODO}
// 监听录制结束或者中断的回调mediaRecorder.onstop = async (event) => { // 这里我们可以将录制的数据,进行处理之后,存储至服务端,例如:上传 OSS}
// 监听录制暂停mediaRecorder.onpause = async (event) => { // TODO}
// 监听录制恢复mediaRecorder.onstart = async (event) => { // TODO}
// 监听录制过程中返回数据mediaRecorder.ondataavailable = (event) => { console.log('handleDataAvailable', event); if (event.data && event.data.size > 0) { recordedBlobs.push(event.data); }}
复制代码
检测编码类型是否支持
利用 isTypeSupported 方法,我们可以检测出是否支持我们想要录制的音频编码或者视频编码。
var types = ["video/webm", "audio/webm", "video/webm\;codecs=vp8", "video/webm\;codecs=daala", "video/webm\;codecs=h264", "audio/webm\;codecs=opus", "video/mpeg"];
for (var i in types) { console.log( "Is " + types[i] + " supported? " + (MediaRecorder.isTypeSupported(types[i]) ? "Maybe!" : "Nope :("));}
复制代码
开始录制
// 一直录mediaRecorder.start();// 录制置顶时间,单位为浩渺mediaRecorder.start(60000); // 录制 60秒
复制代码
暂停录制
恢复录制
结束录制
定时获取录制数据
上面我们监听录制数据回调 ondataavailable,只会在 stop、pause 时才会触发,如果录制的时间很长,那么对应处理的数据量也越大,因此,录制实例还提供了一个方法 requestData 方便我们获取数据。
需要注意的是:当前录制状态必须为正在录制中,否则会报错。
captureMedia.onclick = function() { mediaRecorder.requestData(); // makes snapshot available of data so far // ondataavailable fires, then capturing continues // in new Blob}
复制代码
下载 Or 转码
下载
// 模拟下载按钮点击实现下载function download () { 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 = url; a.download = 'test.webm'; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 100);});
复制代码
转码
我们可以将数据发送至服务端(或 OSS),由服务端转码,感兴趣的同学也可以去试试 ffmpeg。
Ending
我们可以对采集或者录制之后音频、视频数据进行很多处理,例如对视频数据的处理,感兴趣的小伙伴们可以查看以下文章:
一篇前端图像处理秘籍
前端秘籍之“易容”术
评论