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 }); };