详解js的视频和音频采集


Posted in Javascript onAugust 09, 2018

今天要写的,不是大家平时会用到的东西。因为兼容性实在不行,只是为了说明下前端原来还能干这些事。
大家能想象前端是能将摄像头和麦克风的视频流和音频流提取出来,再为所欲为的么。或者说我想把我canvas画板的内容录制成一个视频,这些看似js应该做不到的事情,其实都是可以做到的,不过兼容性不好。我在这里都是以chrome浏览器举的例子。

这里先把用到的api列一下:

  • getUserMedia:打开摄像头和麦克风的接口(文档链接)
  • MediaRecorder:采集音视频流(文档链接)
  • srcObject:video标签可直接播放视频流,这是一个大家应该很少用到其实兼容性很好的属性,推荐大家了解(文档链接)
  • captureStream:可以将canvas输出流,其实不单单是canvas这里只是举有这个功能,具体的可以看文档(文档链接)

1、从摄像头展示视频

一、打开摄像头

// 这里是打开摄像头和麦克设备(会返回一个Promise对象)
navigator.mediaDevices.getUserMedia({
 audio: true,
 video: true
}).then(stream => {
 console.log(stream) // 放回音视频流
}).catch(err => {
 console.log(err) // 错误回调
})

上面我们成功打开了摄像头和麦克风,并获取到视频流。那接下来就是要把流呈现到交互界面中了。

二、展示视频

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
</head>
<body>
 <video id="video" width="500" height="500" autoplay></video>
</body>
<script>
 var video = document.getElementById('video')
 navigator.mediaDevices.getUserMedia({
 audio: true,
 video: true
 }).then(stream => {
 // 这里就要用到srcObject属性了,可以直接播放流资源
 video.srcObject = stream
 }).catch(err => {
 console.log(err) // 错误回调
 })
</script>

效果如下图:

详解js的视频和音频采集

到这里为止我们已经成功的将我们的摄像头在页面展示了。下一步就是如何将采集视频,并下载视频文件。

2、从摄像头采集视频

这里用到的是MediaRecorder对象:

创建一个新的MediaRecorder对象,返回一个MediaStream 对象用来进行录制操作,支持配置项配置容器的MIME type (例如"video/webm" or "video/mp4")或者音频的码率视频码率

MediaRecorder接收两个参数第一个是stream音视频流,第二个是option配置参数。下面我们可以把上面摄像头获取的流加入MediaRecorder中。

var video = document.getElementById('video')
navigator.mediaDevices.getUserMedia({
 audio: true,
 video: true
}).then(stream => {
 // 这里就要用到srcObject属性了,可以直接播放流资源
 video.srcObject = stream
 var mediaRecorder = new MediaRecorder(stream, {
 audioBitsPerSecond : 128000, // 音频码率
 videoBitsPerSecond : 100000, // 视频码率
 mimeType : 'video/webm;codecs=h264' // 编码格式
 })
}).catch(err => {
 console.log(err) // 错误回调
})

在上面我们创建了MediaRecorder的实例mediaRecorder。接下来就是控制mediaRecorder的开始采集和停止采集的方法了。
MediaRecorder提供了一些方法和事件供我们使用:

  • MediaRecorder.start(): 开始录制媒体,这个方法调用时可以通过给timeslice参数设置一个毫秒值,如果设置这个毫秒值,那么录制的媒体会按照你设置的值进行分割成一个个单独的区块, 而不是以默认的方式录制一个非常大的整块内容.
  • MediaRecorder.stop(): 停止录制. 同时触发dataavailable事件,返回一个存储Blob内容的录制数据.之后不再记录
  • ondataavailable事件: MediaRecorder.stop触发该事件,该事件可用于获取记录的媒体(Blob在事件的data属性中可用作对象)
// 这里我们增加两个按钮控制采集的开始和结束
var start = document.getElementById('start')
var stop = document.getElementById('stop')
var video = document.getElementById('video')
navigator.mediaDevices.getUserMedia({
 audio: true,
 video: true
}).then(stream => {
 // 这里就要用到srcObject属性了,可以直接播放流资源
 video.srcObject = stream
 var mediaRecorder = new MediaRecorder(stream, {
 audioBitsPerSecond : 128000, // 音频码率
 videoBitsPerSecond : 100000, // 视频码率
 mimeType : 'video/webm;codecs=h264' // 编码格式
 })
 // 开始采集
 start.onclick = function () {
 mediaRecorder.start()
 console.log('开始采集')
 }
 // 停止采集
 stop.onclick = function () {
 mediaRecorder.stop()
 console.log('停止采集')
 }
 // 事件
 mediaRecorder.ondataavailable = function (e) {
 console.log(e)
 // 下载视频
 var blob = new Blob([e.data], { 'type' : 'video/mp4' })
 let a = document.createElement('a')
 a.href = URL.createObjectURL(blob)
 a.download = `test.mp4`
 a.click()
 }
}).catch(err => {
 console.log(err) // 错误回调
})

ok,现在执行一波操作;

详解js的视频和音频采集

上图可以看到结束采集后ondataavailable事件返回的数据中有一个Blob对象,这就是视频资源了,再接下来我们就可以通过URL.createObjectURL()方法将Blob为url下载到本地了。视频的采集到下载就结束了,很简单粗暴。

上面是视频采集下载的例子,如果只要音频采集的,同样道理的设置“mimeType”就好了。这里我就不举例了。下面我在介绍将canvas录制为一个视频文件

2、canvas输出视频流

这里用到的是captureStream方法,将canvas输出流,再用video展现,或者用MediaRecorder采集资源也是可以的。

// 这里就闲话少说直接上重点了因为和上面视频采集的是一样的道理的。
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>Document</title>
</head>
<body>
 <canvas width="500" height="500" id="canvas"></canvas>
 <video id="video" width="500" height="500" autoplay></video>
</body>
<script>
 var video = document.getElementById('video')
 var canvas = document.getElementById('canvas')
 var stream = $canvas.captureStream(); // 这里获取canvas流对象
 // 接下来你先为所欲为都可以了,可以参考上面的我就不写了。
</script>

下面我再贴一个gif(这是结合我上次写的canvas事件的demo结合这次视频采集的结合)传送门(Canvas事件绑定)

希望大家可以实现下面的效果,其实还可以在canvas视频里插入背景音乐什么的,这些都比较简单。

详解js的视频和音频采集

Javascript 相关文章推荐
jquery对dom的操作常用方法整理
Jun 25 Javascript
Js操作树节点自动折叠展开的几种方法
May 05 Javascript
JavaScript中循环遍历Array与Map的方法小结
Mar 12 Javascript
jQuery 判断是否包含在数组中Array[]的方法
Aug 03 Javascript
JavaScript中关键字 in 的使用方法详解
Oct 17 Javascript
微信小程序开发之录音机 音频播放 动画实例 (真机可用)
Dec 08 Javascript
fullCalendar中文API官方文档
Feb 07 Javascript
基于JavaScript实现轮播图原理及示例
Apr 10 Javascript
JavaScript无缝滚动效果的实例代码
Mar 27 Javascript
Angularjs修改密码的实例代码
May 26 Javascript
css和js实现弹出登录居中界面完整代码
Nov 26 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
Jun 19 jQuery
Angular中的ng-template及angular 使用ngTemplateOutlet 指令的方法
Aug 08 #Javascript
深入理解Promise.all
Aug 08 #Javascript
vue js秒转天数小时分钟秒的实例代码
Aug 08 #Javascript
vue devtools的安装与使用教程
Aug 08 #Javascript
jQuery AJAX 方法success()后台传来的4种数据详解
Aug 08 #jQuery
通过jquery的ajax请求本地的json文件方法
Aug 08 #jQuery
Vue 开发音乐播放器之歌手页右侧快速入口功能
Aug 08 #Javascript
You might like
PHP5.3.1 不再支持ISAPI
2010/01/08 PHP
PHP Memcached + APC + 文件缓存封装实现代码
2010/03/11 PHP
Yii框架登录流程分析
2014/12/03 PHP
Yii框架结合sphinx,Ajax实现搜索分页功能示例
2016/10/18 PHP
提高javascript效率 一次判断,而不要次次判断
2012/03/30 Javascript
JS实现的省份级联实例代码
2013/06/24 Javascript
JavaScript限定复选框的选择个数示例代码
2013/08/25 Javascript
JSuggest自动匹配下拉框使用方法(示例代码)
2013/12/27 Javascript
JS动态改变表格边框宽度的方法
2015/03/31 Javascript
基于jQuery实现的无刷新表格分页实例
2016/02/17 Javascript
JS动态给对象添加属性和值的实现方法
2016/10/21 Javascript
Bootstrap3.3.7导航栏下拉菜单鼠标滑过展开效果
2017/10/31 Javascript
微信小程序顶部导航栏可滑动并选中放大
2019/12/05 Javascript
如何在selenium中使用js实现定位
2020/08/18 Javascript
一篇文章带你从零快速上手Rollup
2020/09/07 Javascript
用Python解析XML的几种常见方法的介绍
2015/04/09 Python
python学习入门细节知识点
2018/03/29 Python
pytorch自定义二值化网络层方式
2020/01/07 Python
Pytorch模型转onnx模型实例
2020/01/15 Python
在python中使用nohup命令说明
2020/04/16 Python
基于python实现matlab filter函数过程详解
2020/06/08 Python
python 对xml解析的示例
2021/02/27 Python
JPA面试常见问题
2016/11/14 面试题
.NET常见笔试题集
2012/12/01 面试题
大学生毕业鉴定
2014/01/31 职场文书
贷款委托书
2014/08/01 职场文书
2014年英语教研组工作总结
2014/12/06 职场文书
就业证明函
2015/06/17 职场文书
酒桌上的祝酒词
2015/08/12 职场文书
《所见》教学反思
2016/02/23 职场文书
python编写函数注意事项总结
2021/03/29 Python
uwsgi+nginx代理Django无法访问静态资源的解决
2021/05/10 Servers
SpringBoot 集成Redis 过程
2021/06/02 Redis
聊聊Python String型列表求最值的问题
2022/01/18 Python
mysql自增长id用完了该怎么办
2022/02/12 MySQL
VUE递归树形实现多级列表
2022/07/15 Vue.js