无需Flash录视频——HTML5中级进阶
前言
HTML5的权限越来越大了,浏览器可以直接调用摄像头、麦克风了,好激动啊。我们要用纯洁的HTML代码造出自己的天地。
视频采集
本篇介绍的栗子 都是在chrome 47 版本以上的,低版本的可能会出现白屏和错误。
1.安全环境
随着Chrome版本的升高,安全性问题也越来越被重视,较新版本的Chrome浏览器在调用一些API时需要页面处在安全环境中。本篇文章所介绍的API函数,都需要在安全环境中执行。如果处在非安全环境下 ( http页面 ) 这些API就会有意想不到的问题。
比如 getUserMedia()
就会报出警告,并执行出错。而在设备枚举enumerateDevices()
时,虽然不会报错,但是他隐藏了设备label。
getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.
根据谷歌的意思,常用的安全环境有如下
https 开头的地址页面
如果你做了一个视频测试的页面,想嘚瑟给局域网的其他人,但是又没有域名证书怎么办?
这时候只能通过修改其他人的hosts文件了
比如你的测试服务器IP地址是192.168.2.18,那么其他人的hosts文件修改如下:
#localhost 127.0.0.1
localhost 192.168.2.18
当使用别人的Chrome浏览器访问 http://localhost/[getUserMedi...时,就会顺利的执行这些API了。
但是移动端的浏览器并不认localhost,就算你修改了hosts ,移动端的浏览器根本不理你,解析都不解析。
所以想在手机上测试,只能老老实实申请个证书了。
2.设备枚举
在开启摄像头之前,先要把可以使用的麦克风和摄像头 ( 输入设备 ) 列出来,如果没有这两样设备也就无法继续。
代码如下:
<label for="audioDevice"> 录音设备: </label>
<select id="audioDevice">
</select>
<br>
<label for="videoDevice"> 录影设备: </label>
<select id="videoDevice">
</select>
<script>
navigator.mediaDevices.enumerateDevices().then(function (data) {
data.forEach(function (item) {
if(item.kind=="audioinput"){ //麦克风
document.getElementById("audioDevice").innerHTML += "<option value='"+ item.deviceId +"'>" + item.label + " </option> "
}else if(item.kind=="videoinput"){ //摄像头
document.getElementById("videoDevice").innerHTML += "<option value='"+ item.deviceId +"'>" + item.label + " </option> "
}
})
},function (error) {
console.log(error);
})
</script>
效果如下图,和浏览器自己获取的一模一样。
注意:上图的实例中,浏览器地址栏最右边的摄像头标识是需要使用 getUserMedia()
函数时才会出现。
<script>
var getUserMedia = navigator.webkitGetUserMedia; //Chrome浏览器的方法
getUserMedia.call(navigator, {
video:true, // 开启音频
audio:true // 开启视频
}, function(stream){
console.log(stream); // 成功获取媒体流
}, function(error){
//处理媒体流创建失败错误
});
</script>
这时候可以通过浏览器给出的菜单下拉选择设备。
3.设置参数,预览
我们可以通过代码来指定使用哪个摄像头和麦克风设备。
也可以通过代码设置视频的宽、高和帧率。
代码如下:
<video id="video" autoplay></video> <!-- 一定要有 autoplay -->
<script>
var getUserMedia = navigator.webkitGetUserMedia ;
getUserMedia.call(navigator, {
"audio":{
"mandatory":{
"sourceId":"" // 指定设备的 deviceId
}
},
"video":{
"optional":[
{"minWidth":400},
{"maxWidth":400}, // 数字类型,固定宽度
{"minHeight":220},
{"maxHeight":220}, // 数字类型,固定高度
{"frameRate":"12"} // 帧率
],"mandatory":{
"sourceId":"" // 指定设备的 deviceId
}
}
}, function(stream){
//绑定本地媒体流到video标签用于输出
document.getElementById("video").src = URL.createObjectURL(stream);
}, function(error){
//处理媒体流创建失败错误
});
</script>
输出的视频流通过blob对象链接绑定到video标签输出。
这个deviceId
就是从上文设备枚举 enumerateDevices()
获取到的。
两种设备,如果有一个deviceId
填写不正确,就会报出一个DevicesNotFoundError
的错误。而且一旦指定了设备后,浏览器自己的设备选择就会变成灰色不可选。
视频的宽高,并不会因为填写的数值比例不合法而失真。
比如你设定了宽度30,高度100,那么他会从视频中心截取 30x100 的画面,而不是把原画面挤压到这个30x100的尺寸。
效果如下:
如果您的预览一片漆黑,或者只有一个小黑点,那么说明您的摄像头正在被占用...
吐槽:这个getUserMedia()
函数的参数,w3的官方文档链接如下:
https://www.w3.org/TR/mediaca...
可是Chrome并没有遵循它,而且差距还挺大...
视频保存
1. 格式支持
Chrome浏览器是大力推广webm的视频格式的。可以用MediaRecorder.isTypeSupported("video/webm")
来测试是否支持这种类型的编码。如果返回true,那么我们录制的视频就可以被保存为这种指定的格式。如果不指定,那么将会使用浏览器自动指定的文件格式。文档原话如下
If this paramater is not specified, the UA will use a platform-specific default format.
但是这个默认值却无法直接获取,全靠猜...
2. 视频录制 MediaRecorder
我们使用 MediaRecorder
来录制视频,参数是通过getUserMedia()
获取的媒体流。
通过绑定
ondataavailable
事件,来获取视频片段数据,并在内存中累积。录制的开始和结束分别使用
start
和stop
函数。执行
start
之后会周期性触发ondataavailable
事件。执行
stop
之后会停止触发ondataavailable
事件。录制结束后,把累计的片段数据保存为blob对象,并从浏览器下载存为视频文件。
代码如下:
<script>
var getUserMedia = navigator.webkitGetUserMedia ;
var g_stream = null, g_recorder = null;
function startPreview(){
getUserMedia.call(navigator, {
video:true,
audio:true
}, function(stream){
g_stream = stream;
}, function(error){
});
}
function stopRecording(){
g_recorder.stop();
}
function startRecording(){
var chunks = [];
g_recorder = new MediaRecorder(g_stream,{mimeType:"video/webm"});
g_recorder.ondataavailable = function(e) {
chunks.push(e.data);
}
g_recorder.onstop = function(e) {
var blob = new Blob(chunks, { 'type' : 'video/webm' });
var audioURL = URL.createObjectURL(blob);
window.open(audioURL);
}
g_recorder.start();
}
</script>
注意:本例并没有填写视频文件头,所以保存出来的视频文件没有时间轨,无法快进和跳跃。可以用格式工厂转
“莫基了”上面有一个录制音频的例子 传送门
这篇文章的DEMO请戳 这里
相关阅读
多屏互动——H5中级进阶
前端,想说爱你不容易!
无需Flash实现图片裁剪——HTML5中级进阶
作者信息
作者来自力谱宿云 LeapCloud 团队_UX成员:王诗诗 【原创】
力谱宿云 LeapCloud 团队首发:https://blog.maxleap.cn/archi...
欢迎关注微信订阅号:MaxLeap_yidongyanfa
本文转载于:无需Flash录视频——HTML5中级进阶
无需Flash录视频——HTML5中级进阶的更多相关文章
- 无需Flash实现图片裁剪——HTML5中级进阶
前言 图片裁剪上传,不仅是一个很贴合用户体验的功能,还能够统一特定图片尺寸,优化网站排版,一箭双雕. 需求就是那么简单,在浏览器里裁剪图片并上传到服务器. 我第一个想到的方法就是,将图片和裁剪参数(x ...
- Flash+fms视频录制在项目中的实际应用
Flash+fms视频录制在项目中的实际应用 前言:以下只是记录本人在项目中的应用,而flash+fms视频录制有多种实现方式,具体可根据实际情况而定! 1:古人云:工欲善其事,必先利其器,首先安装f ...
- [C++中级进阶]001_C++0x里的完美转发到底是神马?
[C++中级进阶]001_C++0x里的完美转发到底是神马? 转载至:http://www.cnblogs.com/alephsoul-alephsoul/archive/2013/01/10/285 ...
- 我的第一个项目:用kinect录视频库
kinect深度视频去噪 kinectmod32.dll http://pan.baidu.com/s/1DsGqX 下载后改名kinect.dll 替换掉Redist\OpenNI2\Drivers ...
- Android 音视频深入 五 完美的录视频(附源码下载)
本篇项目地址,名字是录视频,求star https://github.com/979451341/Audio-and-video-learning-materials 这一次的代码录视频在各个播放器都 ...
- Android 音视频深入 四 录视频MP4(附源码下载)
本篇项目地址,名字是<录音视频(有的播放器不能放,而且没有时长显示)>,求star https://github.com/979451341/Audio-and-video-learnin ...
- Android录屏命令、Android录Gif、Android录视频
NoHttp开源地址:https://github.com/yanzhenjie/NoHttp NoHttp具体使用文档已公布,你想知道的全都有,请点我移步! 版权声明:转载请注明本文转自严振杰的博客 ...
- html5结合flash实现视频文件在所有主流浏览器兼容播放
来源:http://blog.csdn.net/freshlover/article/details/7535785/ 由于html5的出现,让网页中的视频.音频有了更加便捷的实现方式.但是video ...
- Html5学习进阶一 视频和音频
HTML5 规定了一种通过 video 元素来包含视频的标准方法. 视频格式 当前,video 元素支持两种视频格式: Internet Explorer Firefox 3.5 Opera 10 ...
随机推荐
- Python:GUI库tkinter(二)
学习自: Python GUI之tkinter窗口视窗教程大集合(看这篇就够了) - 洪卫 - 博客园 Tkinter简明教程 - 知乎 TkDocs_官方文档 一个Tkinter库较为全面的总结,很 ...
- websocket原理和基于c/c++实现的websocket协议栈(更新中)
参考: 博客1:http://blog.sina.com.cn/s/blog_bf397e780102w25k.html https://www.cnblogs.com/barrywxx/p/7412 ...
- python实用脚本-通过jenkins界面化导出数据
1.jenkins 配置 2.jenkins 脚本 ansible-playbook /opt/test.yaml --extra-vars "loanno=${loanno}" ...
- WPF子窗体
效果: 1. 点击WPF主窗体上的一个按钮,弹出子窗体, 2. 窗体最小化后,在菜单栏中点击子窗体,会连带显示它所从属的主窗体. 1. 在WPF项目中,已有主窗体MainWindow,再新建子窗体Ch ...
- laravel7 下拉搜索
html:页面 首先给下拉框一个页面改变事件,将下拉框的值发送至后台,进行查询 <select name="interest" id="serarch" ...
- git配置修改,git自定义命令,合并命令
一.自定义合并命令 将add commit push合并 git config --global alias.cmp '!f() { git add -A && git commit ...
- Java安装与卸载
Java安装与卸载 Java优势 面向对象 可移植性,跨平台易用 高性能 为分布式设计 具有动态性 支持多线程 安全性 健壮性,运行前会对内存进行检查 Java三大版本 JavaSE:标准版 Java ...
- rsyn实现服务器源码同步
近期技术总监提出,要建立预生产环境,代码实现灰度发布.需要多台服务器源码保持一致. 实施步骤 1.安装rsyn服务端并添加环境变量. 2.安装客户端并配置环境变量. 3.更改配置文件并开放防火墙端口. ...
- Open Babel的安装与使用
技术背景 Open Babel是化学领域常用的一个文件格式转换工具,它可以支持xyz的坐标格式.SMILES表达式.InChI表达式和mol以及mol2等格式之间的互相转化.比如说,你只有一个甲烷的S ...
- 分布式 PostgreSQL 集群(Citus),分布式表中的分布列选择最佳实践
确定应用程序类型 在 Citus 集群上运行高效查询要求数据在机器之间正确分布.这因应用程序类型及其查询模式而异. 大致上有两种应用程序在 Citus 上运行良好.数据建模的第一步是确定哪些应用程序类 ...