使用canvas检测HTML5视频解码错误
乍一看这标题,有点吊炸天的赶脚,canvas跟<video>能有什么联系?不过请放心我不是标题党。事情是这样的:
HTML5的<video>标签所支持的视频格式确实有限,mp4文件必须是H264编码的才行,若不是H264编码,在chrome下会只有声音没有画面,在FireFox下直接连声音也没有,而且控制台会显示警告:
因为浏览器使用的解码器也是H264的。如果用户在本地可以观看的mp4视频上传后却无法正常播放,这种体验是相当糟糕的。
我尝试在文件上传阶段进行检测,然而HTML5的FILE API能力也是有限的,只能获取文件名称、大小、MIME类型,对于视频的编码却无法检测到。
既然无法从上传阶段阻止用户,那么退一步讲,在视频无法播放的时候,我们希望可以检测到,并且给用户一个提示“视频解码错误”,这样他就不会有疑惑“我的视频为什么无法播放呢?”。
首先想到的是video的API,video有onerror事件,但是此事件只能在src地址错误或其他原因加载不到视频资源时触发,当加载到视频发生解码错误时,并不会触发。略蛋疼。这么看来按照标准的东西是无法检测到了,所以必须另辟蹊径了。答案就是:
canvas读取图片像素点的能力
前些天看了前端手记的这篇文章印象颇深,http://www.cssha.com/video2txt-canvas。利用canvas读取图片像素点,进而转化为文本图片。更厉害的是canvas的drawImage方法还可以传入视频,获取到视频某一帧的像素点。于是一个想法在脑中萦绕,解码错误的视频是没有画面的黑屏,我可以用canvas绘制视频,根据所绘制的内容来判断画面是不是在动,遂想到如下思路:
- 在视频开始播放时,每隔一定时间用canvas绘制一次视频画面
- 对每次canvas绘制的图片进行像素点采样,存入数组
- 扫描几次后,比较每次采样的像素点rgb值是否相同,即检测画面是否变化了
- 根据画面是否在“运动”来检测是否解码成功了
这种办法当然也有局限,下面是几个注意事项:
- canvas绘制视频画面的次数控制。绘制图片并采样获取像素点是消耗性能的,所以这个扫描过程不应该伴随视频播放的整个时间段。只需在开始播放的几秒内进行检测即可。
- 若恰巧有某个视频,开始的几秒内就是一个静止的画面,那检测就出错了。
局限归局限,先把想法写成代码试试,于是有如下代码:
//比较两个长度相等类型相同的数组是否相等
function arrayEq(a1,a2){
for(var i=0,len=a1.length;i<len;i++){
if(a1[i]!=a2[i]){
return false;
}
}
return true;
}
//比较采样得到的数组是否相等
function arrayAllEq(array){
for(var i=0,len=array.length;i<len;i++){
if(!arrayEq(array[i],array[i+1])){
return false;
}
}
return true;
} var can = $('<canvas id="canvas" style="display:none"></canvas>').appendTo('body');
var canvas = can.get(0);
var width = $('#vi').width();
var height = $('#vi').height();
var ctxt = canvas.getContext('2d');
var media = document.getElementById('vi');
var resultArray = [];
var stopScan = false;
var scanImg = function(){
if(stopScan)return false;
try{
ctxt.drawImage(media, 0, 0,width,height);
var data = ctxt.getImageData(0, 0, width,height).data;
var array = [];
for(var i =0,len = data.length; i<len;i+=4*100){
var red = data[i],
green = data[i+1],
blue = data[i+2],
alpha = data[i+3];
array.push(red,green,blue,alpha);
}
resultArray.push(array);
return true;
}
catch(e){
alert('视频解码错误,请使用H264编码的mp4文件!');
stopScan = true;
}
}
$('video').on('play',function(){
//每隔一定时间扫描一次画面
scanImg();
setTimeout(scanImg,1000);
setTimeout(scanImg,2000);
setTimeout(scanImg,3000);
setTimeout(scanImg,5000);
setTimeout(function(){
if(scanImg()){
if(arrayAllEq(resultArray)){
alert('视频解码错误,请使用H264编码的mp4文件!');
}
else{
alert('监测结束,视频正常');
}
}
},8000);
});
$('video').on('pause',function(){
stopScan = true;
});
当我怀着激动的心情开始测试时,发现事实真不是想象的那样。Chrome下,当一个视频无法解码时,drawImage方法直接无法执行,会报错。完了,美好的想法泡汤了。。。
不过转而一想,视频解码错误,drawImage方法就报错,如果写在try catch语句中,不就可以捕捉到了吗?看来还没到死路,这样连像素点采样都省了,可以直接检测到了。于是乎代码就简化成了下面这样:
//检测视频是否解码错误
function checkVideoParseError(){
var videos = $('video');
if(videos.length>0){
var can = $('<canvas id="canvas" style="display:none"></canvas>').appendTo('body');
var canvas = can.get(0);
var ctxt = canvas.getContext('2d');
var scanImg = function(video){
try{
ctxt.drawImage(video, 0, 0);
}
catch(e){
alert('视频解码错误,请使用H264编码的mp4文件!');
}
} videos.on('play',function(){
var _this = this;
scanImg(_this);
setTimeout(function(){scanImg(_this);},1000);
})
}
}
在1秒后的绘制图片动作会捕捉到异常。没想到,竟然这样成功了!
该方法纯属个人想出来的,还有诸多不完善之处,遇到同样问题的同学可以试试这个思路~
使用canvas检测HTML5视频解码错误的更多相关文章
- 绘制SVG内容到Canvas的HTML5应用
SVG与Canvas是HTML5上绘制图形应用的两种完全不同模式的技术,两种绘制图形方式各有优缺点,但两者并非水火不容,尤其是SVG内容可直接绘制在Canvas上的功能,使得两者可以完美的融合在一起, ...
- make: 警告:检测到时钟错误。您的创建可能是不完整的。
问题: make: 警告:检测到时钟错误.您的创建可能是不完整的. 原因:1. 文件时间不一致.(或者修改了系统时间) 如何解决:你touch *一下,然后重新编译 touch * touch命令有两 ...
- 7个华丽的基于Canvas的HTML5动画
说起HTML5,可能让你印象更深的是其基于Canvas的动画特效,虽然Canvas在HTML5中的应用并不全都是动画制作,但其动画效果确实让人震惊.本文收集了7个最让人难忘的HTML5 Canvas动 ...
- sql server 驱动程序在 \Device\RaidPort0 上检测到控制器错误。
sql server 驱动程序在 \Device\RaidPort0 上检测到控制器错误. 错误情况,如下图: 原因分析:硬盘故障 解决办法:进行迁移
- [LINUX]警告:检测到时钟错误。您的创建可能是不完整的。
[LINUX]警告:检测到时钟错误.您的创建可能是不完整的. 原因: 如果上一次编译时为20071001,你把系统时间改成20070901后再编译就会报这样的错误. 解决: 把时间 ...
- canvas与html5实现视频截图功能
这段时间一直在研究canvas,突发奇想想做一个可以截屏视频的功能,然后把图片拉去做表情包,哈哈哈哈哈哈~~ 制作方法: 1.在页面中加载视频 在使用canvas制作这个截图功能时,首先必须保证页面上 ...
- 避免HTML5六种错误用法
一.不要使用section作为div的替代品 人们在标签使用中最常见到的错误之一就是随意将HTML5的<section>等价于<div>--具体地说,就是直接用作替代品(用于样 ...
- 检测 HTML5\CSS3\JAVASCRIPT 在浏览器的适应情况
CSS3 Selectors Test : 这是CSS3.INFO网站提供的css选择器测试页面,它能够详细显示当前浏览器对所有CSS3选择器的支持情况.启动测试,浏览器会自动测验,并已列表的方式显示 ...
- 浏览器 canvas下载图片 网络错误
在使用html2canvas截取页面的时候发现图片死活保存不到本地,chrome一直报“网络错误”, 主要出现这个问题是canvas保存图片到本地时各个浏览器像素的限制不同, 所以将图片数据转换成Bl ...
随机推荐
- javascript面向对象(1)
主要内容: 在讲面向对象之前,我们先看一个示例: 类似这种情况大家都能够理解,但是,如果把代码改动一下,请再看一下: 为什么会这样? 如果把代码再改一下看看,如把变量改成b,则直接报错 JavaScr ...
- HTML字体及颜色设置
字体(FONT)标记(TAGS) 标题字体(Header) <h#> ... </h#> #=1, 2, 3, 4, 5, 6<h1>今天天气真好!</h1& ...
- vpn速度太慢?先从本地网络着手
使用VPN,用户们抱怨的最多的是速度太慢这个问题,导致网页打不开或者打开缓慢,游戏延迟变高或者根本无法游戏,甚至无法连接等.那么我们今天就来全面解析下VPN的速度是由什么因素引起的. vpn速度过慢 ...
- ServiceStack.OrmLite中的一些"陷阱"(1)
使用过ServiceStack.Ormlite的人都应该知道,其作为一个轻量级的ORM,使用的便捷度非常高,用起来就一个字:爽!而支撑其便捷度的,是库内大量地使用了扩展方法及静态变量. 首先先从源头入 ...
- .Net 对App.config和Web.config的访问操作(增、删、读、改)
一.首先引用Configuration 1)App.config如下: using System.Configuration;//若果还没有Configuration,右键引用文件夹添加引用,在.NE ...
- asp.net运行时错误:没有为扩展名".cshtml"注册的提供程序。
解决方法: 一. 在machine.config或web.config中的<compilation><buildProviders>节注册一个.请确保所注册的提供程序具有包含 ...
- 【Java学习笔记】集合转数组---toArray()
package p2; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ...
- Trie树(c++实现)
转:http://www.cnblogs.com/kaituorensheng/p/3602155.html http://blog.csdn.net/insistgogo/article/detai ...
- Robot Framework安装教程
第一步:安装Python,安装的版本是python-2.7.9.amd64.msi 安装教程详见地址:http://jingyan.baidu.com/article/c910274be14d64cd ...
- Raab判别法确定级数是否收敛