加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

无需Flash录视频——HTML5中级进阶

发布时间:2020-12-15 19:59:26 所属栏目:百科 来源:网络整理
导读:前言 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.


根据谷歌的意思,常用的安全环境有如下


http://localhost

http://127.0.0.1

https 开头的地址页面

如果你做了一个视频测试的页面,想嘚瑟给局域网的其他人,但是又没有域名证书怎么办?

这时候只能通过修改其他人的hosts文件了

比如你的测试服务器IP地址是192.168.2.18,那么其他人的hosts文件修改如下:

#localhost 127.0.0.1localhost 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请戳?这里


原文链接


https://segmentfault.com/a/1190000007153229


原作者


力谱宿云


(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读