JS每隔一秒提取视频缩略图实例页面
回到相关文章 »效果:
1. 本地视频
2. 网络视频
//注意:需要允许跨域提供地址:https://imgservices-1252317822.image.myqcloud.com/coco/b12202023/67430f37.6y59kt.mp4
代码:
CSS代码:
.result:not(:empty) {
border: 1px dashed darkgray;
padding: 12px 16px;
margin-top: 24px;
}
HTML代码:
<h4>1. 本地视频</h4> <input type="file" id="file" accept="video/*"> <h4>2. 网络视频</h4> <input type="url" id="input" placeholder="在线视频地址"> <div id="result" class="result"></div>
JS代码:
const handleGetVideoThumb = function (url, options = {}) {
if (typeof url != 'string') {
return;
}
// 默认参数
const defaults = {
onLoading: () => {},
onLoaded: () => {},
onFinish: (arr) => {}
};
const params = Object.assign({}, defaults, options);
// 基于视频元素绘制缩略图,而非解码视频
const video = document.createElement('video');
// 静音
video.muted = true;
// 绘制缩略图的canvas画布元素
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d', {
willReadFrequently: true
});
// 绘制缩略图的标志量
let isTimeUpdated = false;
// 几个视频事件
// 1. 获取视频尺寸
video.addEventListener('loadedmetadata', () => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
// 开始执行绘制
draw();
});
// 2. 触发绘制监控
video.addEventListener('timeupdate', () => {
isTimeUpdated = true;
});
// 获取视频数据
params.onLoading();
// 请求视频地址,如果是本地文件,直接执行
if (/^blob:|base64,/i.test(url)) {
video.src = url;
} else {
fetch(url).then(res => res.blob()).then(blob => {
params.onLoaded();
// 赋予视频
video.src = URL.createObjectURL(blob);
});
}
// 绘制方法
const draw = () => {
const arrThumb = [];
const duration = video.duration;
let seekTime = 0.1;
const loop = () => {
if (isTimeUpdated) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(video, 0, 0, canvas.width, canvas.height);
canvas.toBlob(blob => {
arrThumb.push(URL.createObjectURL(blob));
seekTime += 1;
if (seekTime > duration) {
params.onFinish(arrThumb);
return;
}
step();
}, 'image/jpeg');
return;
}
// 监控状态
requestAnimationFrame(loop);
}
// 逐步绘制,因为currentTime修改生效是异步的
const step = () => {
isTimeUpdated = false;
video.currentTime = seekTime;
loop();
}
step();
}
};
const handleThumbUrl = function (arrUrl) {
result.innerHTML = arrUrl.map(url => `<img src="${url}">`).join('');
};
file.onchange = function (event) {
const file = event.target.files[0];
// 开始识别
const reader = new FileReader();
reader.onload = function (event) {
const url = URL.createObjectURL(new Blob([event.target.result]));
handleGetVideoThumb(url, {
onFinish: handleThumbUrl
});
};
reader.readAsArrayBuffer(file);
};
input.onchange = function () {
if (this.matches(':invalid')) {
new LightTip('请输入合法的URL地址', 2000, 'error');
return;
}
const url = this.value.trim();
if (!url) {
return;
}
handleGetVideoThumb(url, {
onLoading: () => {
result.innerHTML = '<ui-loading></ui-loading>';
},
onFinish: handleThumbUrl
});
};