首页说出现的问题:根据video的loadeddata事件的触发来绘制第一帧,但是绘制出来总是黑屏
- 解决:后来发现video加上preload属性等于auto就可以绘制成功了。
- 代码:
window.onload = function () {
var url = "http://1257092661.vod2.myqcloud.com/0d1bb4cevodtransgzp1257092661/bf15d8205285890807073233140/v.f30.mp4";
// var url = "http://imgshop.woojia.com/newimages/s-20200421/100/45552b258e8c8c723930046033e368b5.mp4";
// var imgUrl = "http://imgshop.woojia.com/newimages/s-20200821/36/9faceee175b8e1b5d35cb6e4f8ce8797.jpeg";
var resolve = getVideoBase64(url);
console.log("resolve:",resolve);
resolve.then(dataURL => {
console.log("dataURL:",dataURL);
});
function getVideoBase64(url) {
return new Promise(function (resolve, reject) {
var dataURL = '';
const video = document.createElement("video");
video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
video.setAttribute('src', url);
video.setAttribute('width', 400);
video.setAttribute('height', 400);
video.setAttribute("preload", "auto"); // 就是加上预加载之后绘制就成功了
// document.body.append(video);
video.addEventListener('loadeddata', function () {
var canvas = document.createElement("canvas"),
width = video.width, //canvas的尺寸和图片一样
height = video.height;
canvas.width = width;
canvas.height = height;
canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
resolve(dataURL);
// document.body.append(canvas);
});
})
}
- 原因:
preload=auto:指页面开始加载的时候就可以开始加载视频。
preload=metadata: 指当页面加载后仅加载元数据。
preload=none: 页面加载时视频不加载。
虽然设置了onloadeddata事件才去画它的第一帧,按理说应该视频已经加载出了第一帧了,但是由于没有设置preload=auto并没有截图到第一帧。(好像不管有没有preload都会执行onloadeddata)
所以要想截图第一帧就必须让它自动加载。因为各浏览器对preload不设置时的默认值可能不同还是手动设置一下比较好。
onloadeddata事件:当媒介数据已加载时才会执行的回调
- 尝试过的方法
- 以为onloadeddata事件执行时视频还没有加载出第一帧。
更换了事件发现不行;
给onloadeddata加延时结果神奇的发现有时候可以有时候又不行; - 以为drawImage也会因为绘制大的数据的而导致失败(比较傻)。
所以给绘制的图片减少过像素,结果是刚减少过可以了,试了几次又失败了。
最后附上base64转blob的方法
/**
* @param dataUrl base64 数据
* File接口基于Blob,继承了Blob的功能并进行了扩展,故blob对象也可以当作file对象一样当作文件上传。
*/
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while(n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr],{type:mime});
};