MP4Box 借用HTML5 file api 本地读取 mp4 头信息
文章目录
上一篇博文介绍了 html5 file api
html5 提供了一套可以操作本地文件的 api ,但是有一定的局限性
必须由用户发起一个事件,所以你不要妄想着用户浏览器加载某个站点时,主动去读取他本地硬盘的资料....不可能的.
你的浏览器必须支持 html5 的 file api ,所以你也不要妄想去兼容IE6
用户发起行为比如: file upload 操作, 文件拖拽 等.
最近遇到一个需求
1.本地上传视频要保存到七牛服务器
2.提交切割视频任务 (大文件切割成多份)
3.返回视频截图 (按视频长短截取图片,供管理员审核视频内容)
七牛这边提供的有 js-sdk 和 node.js 2种调用方法
我们的处理过程是, 浏览器发起上传事件 --> 请求自己服务器api 获取 token --> 拿到 token 调用 七牛 js-sdk 上传视频到七牛服务器
七牛根据 token ,解析出任务列表,完成任务后 调用 我们服务器的 api 返回任务数据 (截图,切割,视频压缩转码 url 等)
这里需要注意:
浏览器上传文件到七牛时 所带的 token,里面包含了所有一切一切需要七牛做的任务....
当然,你也可以先上传文件到七牛,然后接口去请求七牛api 执行各种各样的 任务也是可以的.
但是,我们希望浏览器上传时,只请求七牛一次,同时把任务都定制好,告诉七牛,剩下的工作就是,坐等七牛回调 api 传过来 任务数据.
但是我们有一个任务是根据视频时长去截图,返回截图供管理员审核
那么问题来了
如何在浏览器上传视频文件时,就知道视频的播放时长呢????
这就是今天和大家分享的内容
浏览器通过 html5 file api 读取 mp4 头信息,获取视频播放长度.
用的的开源包 MP4Box
github地址: https://github.com/gpac/mp4box.js/
MP4Box 及支持服务器,也支持浏览器直接调用,今天的内容只包括 浏览器调用 MP4Box.js 本地读取 mp4 头信息.获取时长
首先下载 MP4Box.js 然后页面引用
然后定义一个 file 控件
定义一个 滚动条效果
再来一个信息输入显示的地方
给 file 控件的change 事件绑定函数:
<script>
var mp4box;
var progressbar;
var progresslabel;
var fileinput;
var chunkSize = 1024 * 1024; // bytes
function dragenter(e) {
e.stopPropagation();
e.preventDefault();
}
function drop(e) {
var file;
if (!e) {
file = document.getElementById('fileinput').files[0];
}
else {
file = e.dataTransfer.files[0];
}
if (file) {
parseFile(file);
}
}
function initialize() {
mp4box = new MP4Box(false);
}
function parseFile(file) {
var fileSize = file.size;
var offset = 0;
var self = this; // we need a reference to the current object
var readBlock = null;
var startDate = new Date();
initialize();
mp4box.onError = function (e) {
console.log("mp4box failed to parse data.");
};
var onparsedbuffer = function (mp4box, buffer) {
console.log("Appending buffer with offset " + offset);
buffer.fileStart = offset;
mp4box.appendBuffer(buffer);
}
var onBlockRead = function (evt) {
if (evt.target.error == null) {
onparsedbuffer(mp4box, evt.target.result); // callback for handling read chunk
offset += evt.target.result.byteLength;
progressbar.progressbar({value: Math.ceil(100 * offset / fileSize)});
} else {
console.log("Read error: " + evt.target.error);
return;
}
if (offset >= fileSize) {
progressbar.progressbar({value: 100});
console.log("Done reading file (" + fileSize + " bytes) in " + (new Date() - startDate) + " ms");
mp4box.flush();
finalizeUI();
return;
}
readBlock(offset, chunkSize, file);
}
readBlock = function (_offset, length, _file) {
var r = new FileReader();
var blob = _file.slice(_offset, length + _offset);
r.onload = onBlockRead;
r.readAsArrayBuffer(blob);
}
readBlock(offset, chunkSize, file);
}
function finalizeUI() {
var content = '';
if (!mp4box || !mp4box.moovStartSent) {
content += 'mp4 : 否<br/>';
} else {
var info = mp4box.getInfo();
var videoLength = 0;
content += 'mp4 : 是<br/>';
content += '创建时间:' + info.created + '<br/>';
content += '视频时长:' + info.duration + ' 毫秒<br/>';
if (info.tracks && info.tracks.length > 0) {
info.tracks.forEach(function (item) {
if (item.size){
videoLength += parseInt(item.size);
}
if(item.video){
content+='分辨率:'+item.video.height+ 'X'+ item.video.width+' <br/>';
}
});
content += '视频大小:' + videoLength / (1000 * 1000) + ' M <p style="color:white;">出自:<a style="color:white;" href="http://yijiebuyi.com/blog/a5cd9f53202cf1dbb10cf53e4726fca8.html" >MP4Box 借用HTML5 file api 本地读取 mp4 头信息</a></p><br/>';
}
}
$('#content').html('').html(content);
}
window.onload = function () {
progressbar = $('#progressbar');
progresslabel = $('#progress-label');
fileinput = $('#fileinput');
progressbar.progressbar({
value: 0,
change: function () {
progresslabel.text(
progressbar.progressbar("value") + "%");
},
complete: function () {
progresslabel.text("Loading Completed!");
}
});
fileinput.button();
}
</script>
运行页面我们看下效果
上传一个mp4 看看
大功告成,本地读取视频头信息成功.
对于mp4 的头信息,不一定放在头部,有时也会出现在尾部.如果你愿意用 file api 自己分析视频文件,找到头信息所在位置,然后解析出来也是可以的.
只是费时费力, MP4Box.js 帮我们做了很多繁杂的工作,调用 getInfo 方法准备获得视频头信息.