遇到问题
在开发中,测试反馈了一个问题,就是在前端上传视频后,视频无法回显,显示黑屏。
于是我要来了测试上传的视频,看了下后缀名是.mp4, 用vlc打开播放正常,于是我开始了爬坑之旅。
查找原因
因为后缀名和播放都是正常的,先考虑是不是视频编码格式问题。
首先查看MDN文档,查看html支持的视频格式,了解到支持的视频后缀有如下: mp4, webm, ogg,那我们的mp4的视频类型应该没有问题的。
那就开始看看视频编码格式问题,查看视频编码的方法我们就用vlc打开视频:

为了验证是不是编码格式的问题,用录屏软件和手机分别拍摄了一些视频做了测试,测试结果如下:
| 视频格式 | 视频编码信息(VLC) | 网页能否正常播放 |
|---|---|---|
| ev录制mp4 | H264-MPEG-4 AVCpart10 avc1) | 正常 |
| ev录制avi | MPEG-4 VideoFMP4) | 异常 |
| ev录制flv | Flash-Video FLV1) | 异常 |
| ev录制wmv | MS-MPEG-4-Video v3MP43) | 异常 |
| qq桌面端录制 | MPEG-4 VideoMP4V) | 异常 |
| qq手机端录制 | H264-MPEG-4 AVCpart10 avc1) | 正常 |
| tim录制 | H264-MPEG-4 AVCpart10 avc1) | 正常 |
| 微信录制 | H264-MPEG-4 AVCpart10 avc1) | 正常 |
根据上述结果可以看到,编码格式codec)和文件类型type,后缀名)会导致视频无法正常播放。
备注:
ev是windows下的一款录屏软件,测试提供的视频就是用qq桌面端功能录制的视频。
解决问题
目前前端操作,获取文件类型倒是比较简单,一般传输图片、文本等等都是根据file.type和file.name来判断是否允许上传。
但是我们这里只获取name和type也无法判断,我们上传的视频能否正常播放了。我找了很久的之后,发现了github上大神的写的一个框架 mp4box.js 可以帮助我们解决这个问题。
mp4box
安装
npm i mp4box -S
导入
import MP4Box from ‘mp4box’
校验代码
async videoBeforeUploadfile) {
const isVideo = file.type === 'video/mp4' || file.type === 'video/ogg' || file.type === 'video/webm';
const isLt30M = file.size / 1024 / 1024 < 30;
if !isVideo) {
this.$message.warning'请上传正确格式的视频!');
return Promise.reject)
} else {
if !isLt30M) {
this.$message.warning'上传视频文件大小不能超过 30MB!');
return Promise.reject)
}
}
// 正确的视频后缀会有mime信息
let result = await this.checkVideoCodefile)
let valid = this.getCodecValidresult.mime)
if !valid) {
this.$message.error'请上传正确的视频编码格式')
return Promise.reject)
}
},
async checkVideoCodefile) {
return new Promiseresolve, reject) => {
const mp4boxFile = MP4Box.createFile);
const reader = new FileReader);
reader.readAsArrayBufferfile);
reader.onload = function e) {
const arrayBuffer = e.target.result;
arrayBuffer.fileStart = 0;
mp4boxFile.appendBufferarrayBuffer);
};
mp4boxFile.onReady = function info) {
resolveinfo)
};
mp4boxFile.onError = function info) {
rejectinfo)
};
})
},
getCodecValidstr) {
let arr = str.split';')
return !!arr[1].includes'mp4a') || arr[1].includes'avc1'));
},
因为我是用了elementUI框架的组件,所以返回的值都是promise类型,大家自行修改为return false 就行了。因为判断codec 我感觉比较复杂我懒),所以我用了和类型判断和getCodecValid 简单的判断了一下编码格式。
通过这两种方式,我们可以获取到不能播放的视频格式了。接下来的处理大家各取所需,可以让用户继续传,但是没办法观看,让后端转码。或者直接拦截,不让用户传。或者提示,你传了可以,网页观看不了,自己下载下来观看。
其他框架
在发现和解决问题的过程中,我发现了几个不错的视频组件和转码框架。
bilibili的flv格式视频播放解决方案:flv.js
视频播放组件:Mui Player
常用的视频处理库:video.js
补充测试视频codec信息
| 视频格式 | 视频编码信息(VLC) | codec信息(MP4BOX) | 网页能否正常播放 |
|---|---|---|---|
| ev录制mp4 | H264-MPEG-4 AVCpart10 avc1) | video/mp4; codecs=”avc1.42c028″; profiles=”isom,iso2,avc1,mp41″ | 正常 |
| ev录制avi | MPEG-4 VideoFMP4) | null | 异常 |
| ev录制flv | Flash-Video FLV1) | null | 异常 |
| ev录制wmv | MS-MPEG-4-Video v3MP43) | null | 异常 |
| qq桌面端录制 | MPEG-4 VideoMP4V) | application/mp4; codecs=”mp4v”; profiles=”isom,iso2,mp41″ | 异常 |
| qq手机端录制 | H264-MPEG-4 AVCpart10 avc1) | video/mp4; codecs=”avc1.640020,mp4a.40.2″; profiles=”isom,iso2,avc1,mp41″ | 正常 |
| tim录制 | H264-MPEG-4 AVCpart10 avc1) | video/mp4; codecs=”avc1.64001f,mp4a.40.2″; profiles=”isom,iso2,avc1,mp41″ | 正常 |
| 微信录制 | H264-MPEG-4 AVCpart10 avc1) | video/mp4; codecs=”mp4a.40.2,avc1.64001f”; profiles=”mp42,isom” | 正常 |
参考
使用 JS 获取视频 Codec
MDN上关于video的基础使用
MDN上视频内容和音频
MDN上HTML的媒体支持:audio和video元素
有疑问或者问题,请留言,本人常在回复比较及时。
作者:Cirry
出处:http://www.cnblogs.com/cirry/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。


